Commit 81cf84ad authored by ext-bershanska_a's avatar ext-bershanska_a
Browse files

runOPAL.py and simulation.py changed in order to work with OPTIMIZE (Issue #8)...

runOPAL.py and simulation.py changed in order to work with OPTIMIZE (Issue #8) and new features, sich as --filename and shortcuts, have been added
parent ef2f0f1b
......@@ -14,53 +14,62 @@ import subprocess
from simulation import Simulation
from opaldict import OpalDict
def getBaseName():
path ='.'
ext1 ='*.tmpl'
ext2 ='*.data'
templates = glob.glob(os.path.join(path,ext1))
datafiles = glob.glob(os.path.join(path,ext2))
if templates:
str1 = templates[0]
else:
print('No template file (.tmpl) found')
sys.exit()
if datafiles:
str2 = datafiles[0]
else:
print('No data file (.data) found')
sys.exit()
str1spl = str1.split('.')
str2spl = str2.split('.')
if str1spl[1] == str2spl[1]:
name = str2spl[1]
name = name.split('/')[1]
else:
print('Template and data filename do not match', str1spl, str2spl)
def getPaths(path, pattern, name):
result = glob.glob(os.path.join(path,pattern))
if not result:
print('No '+name+' file ('+pattern+') found')
sys.exit()
return result
def getBaseName(inputfilePath): # EDIT: more flexible (can have several *.data files)
templates = getPaths(inputfilePath, '*.tmpl', 'template')
datafiles = getPaths('.', '*.data', 'data')
name = templates[0].split('/')[-1][:-5] #NOTE: choose first (alphanumeric order) *.tmpl file by default
if os.path.isfile(os.path.join('.',name+'.data')):
return name
def printUsage():
print("./runOPAL.py [--help] [--quiet] [--info=num] [--test] [--keep] [--queue=qname] [--hypert=num] [--nobatch] [ATTR=SCANVALUE] {[ATTR=VALUE]}")
datafiles = getPaths('.', '*.data', 'data')
print('Template and data filename do not match, '+name+'.data expected')
sys.exit()
def printUsage(): #EDIT: reorder for readibility, add --filename and shortcuts
print("./runOPAL.py [--help] [--filename=str] [--test] [--quiet] [--info=num] [--test] [--keep] [--queue=qname] [--hypert=num] [--nobatch] [ATTR=SCANVALUE] {[ATTR=VALUE]}")
print("")
print("--help prints this message")
print("--test does everything but submitting the job")
print("--keep if same simulation has been run before, keep old data and abort")
print("--filename | -f=<str> sets base falie name for both *.data and *.tmpl")
print("--test | -t does everything but submitting the job")
print("--keep | -k if same simulation has been run before, keep old data and abort")
print("--nobatch run opal locally not using the batch system and waits until the job is done")
print("--noopt ignore optimization template (if any) and perform regular simulation")
print("--quiet suppress debug printout")
print("--info=<num> steers the std-output of OPAL. The range is 0 < num < 6 (default), from minimal to maximum output")
print("--info | -i=<num> steers the std-output of OPAL. The range is 0 < num < 6 (default), from minimal to maximum output")
print("--queue=<qname> defines in which queue the job goes. Overwrites QUEUE (deprecated SGE_QUEUE)")
print("--hypert=<num> defines the number of Hyper-Threads used. Default 0")
print("")
print("SCANVALUE=start:end:step, scans a parameter space, e.g. example TFWHM=0.85:0.90:0.01 ")
print("ATTR refers to a name in the data file")
print("")
print("Recognized environment variables: DISTRIBUTIONS, FIELDMAPS, OPAL_EXE_PATH, TEMPLATES, QUEUE, RAM, TIME (deprecated SGE_)")
print("Recognized environment variables: DISTRIBUTIONS, FIELDMAPS, OPTIMIZER, OPAL_EXE_PATH, TEMPLATES, QUEUE, RAM, TIME (deprecated SGE_)")
# temporary see issue #8
print("")
print("Important: runOPAL is currently not compatible with the commands OPTIMIZE and SAMPLE")
def checkCompat(tmplFile, incompatible): #NOTE: SAMPLE command not compatible with runOPAL (issue #8)
templateFile = open(tmplFile,'r')
for line in templateFile:
if line.startswith('//'):
continue
if any(command in line for command in incompatible):#'OPTIMIZE' in line or 'SAMPLE' in line:
print(', '.join(incompatible)+' command(s) currently not compatible with runOPAL')
sys.exit()
templateFile.close()
def traverseRanges(list, opaldict, args, doNobatch):
"""
Traverse all possible combinations of range variable values. Start simulation
......@@ -90,6 +99,7 @@ def traverseRanges(list, opaldict, args, doNobatch):
traverseRanges(tail, opaldict, args, doNobatch)
curval = curval + step
def main(argv):
"""
main method
......@@ -99,72 +109,80 @@ def main(argv):
doTest = False
doKeep = False
doNobatch = False
doOptimize = True #NOTE: this flag is opposite of --noopt (I want to optimize by default)
queue = ""
info = 6
hypert = 0
qid = -1
for arg in argv:
if arg.startswith("--test"):
inputfilePath = None
baseFileName = None
for arg in argv: #EDIT: reorder for readibility, add --filename and shortcuts
if arg.startswith("--help"):
printUsage()
exit()
elif arg.startswith("--filename") or arg.startswith("-f"):
baseFileName = arg.split("=")[1]
elif arg.startswith("--test") or arg.startswith("-t"):
doTest = True
elif arg.startswith("--hypert"):
hypert = int(arg.split("=")[1])
elif arg.startswith("--keep"):
elif arg.startswith("--keep") or arg.startswith("-k"):
doKeep = True
elif arg.startswith("--nobatch"):
doNobatch = True
elif arg.startswith("--info"):
elif arg.startswith("--noopt"):
doOptimize = False
elif arg.startswith("--quiet"):
quiet = True
elif arg.startswith("--info") or arg.startswith("-i"):
info = arg.split("=")[1]
elif arg.startswith("--queue"):
queue = arg.split("=")[1]
elif arg.startswith("--help"):
printUsage()
exit()
elif arg.startswith("--quiet"):
quiet = True
elif arg.startswith("--"):
elif arg.startswith("--hypert"):
hypert = int(arg.split("=")[1])
elif arg.startswith("-"): #EDIT: ignore any unknown argument '-', not just arg.startswith("--")
print(arg,'is not a valid option, see --help for the available options')
exit()
if (os.getcwd() == os.environ.get('TEMPLATES')):
print('Working directory is the same as the TEMPLATES directory! This is not allowed... bye!')
# safety check, EDIT: now for both TEMPLATES and OPTIMIZER
if os.getcwd() == os.environ.get('TEMPLATES') or os.getcwd() == os.environ.get('OPTIMIZER'):
print('Working directory is the same as the TEMPLATES or OPTIMIZER directory! This is not allowed... bye!')
sys.exit()
else:
# make sure we have no junk around
os.system('rm -f tmplbak17.tmpl')
if (os.environ.get('TEMPLATES')):
inputfilePath = os.environ.get('TEMPLATES')
os.system('rm -f tmplbak17.tmpl') # make sure we have no junk around (NOTE: don't create tmplbak17.tmpl)
if not os.path.isfile(inputfilePath + ".tmpl"):
os.system('cp ' + inputfilePath + '/*.tmpl .')
#EDIT: determine what kind of job should be ran
if doOptimize and os.environ.get('OPTIMIZER'):
print('job type: OPTIMIZATION')
inputfilePath = os.environ.get('OPTIMIZER')
#NOTE: maybe set tmpl dirctory for simulation
else:
ext1 ='*.tmpl'
if (glob.glob(os.path.join('.',ext1))):
print('job type: SIMULATION')
doOptimize = False
if os.environ.get('TEMPLATES'):
inputfilePath = os.environ.get('TEMPLATES')
#if not os.path.isfile(inputfilePath + ".tmpl"): #NOTE: Idk why this line is supposed to be here
# os.system('cp ' + inputfilePath + '/*.tmpl .')
# #print('Put .tmpl in local directory')
elif (glob.glob(os.path.join('.','*.tmpl'))):
inputfilePath = '../'
#print('.tmpl found in ./')
else:
print('Template file unknown -> exiting ...')
sys.exit()
baseFileName = getBaseName()
#EDIT: check that tmpl and data files can be found or guessed
if not baseFileName:
baseFileName = getBaseName(inputfilePath)
elif not os.path.isfile(os.path.join(inputfilePath,baseFileName+'.tmpl')):
print(baseFileName+'.tmpl cannot be found! Check if it exists in '+inputfilePath)
sys.exit()
print('baseFileName = '+baseFileName)
dataFile = baseFileName + '.data'
tmplFile = baseFileName + '.tmpl'
tmplFile = os.path.join(inputfilePath,baseFileName+'.tmpl') #EDIT: .tmpl file is no longer copied to wd
oinpFile = baseFileName + '.in' # the resulting OPAL input file
# Optimizer and Sample command currently not compatible with runOPAL (issue #8)
templateFile = open(tmplFile,'r')
for line in templateFile:
if line.startswith('//'):
continue
if 'OPTIMIZE' in line or 'SAMPLE' in line:
print('OPTIMIZE and SAMPLE command currently not compatible with runOPAL')
sys.exit()
templateFile.close()
if os.environ.get('TEMPLATES'):
if os.path.isfile(baseFileName + ".tmpl"):
os.system("mv " + baseFileName + ".tmpl tmplbak17.tmpl")
checkCompat(tmplFile, ['SAMPLE']) #EDIT: check compatibility
#create the dictionary
opaldict = OpalDict(dataFile)
......@@ -175,7 +193,7 @@ def main(argv):
if not opaldict.hasRanges():
sim = Simulation(opaldict)
qid = sim.run(N, baseFileName, inputfilePath, tmplFile, oinpFile, doTest, doKeep, doNobatch, info, queue, hypert, quiet)
qid = sim.run(N, baseFileName, inputfilePath, tmplFile, oinpFile, doTest, doKeep, doNobatch, doOptimize, info, queue, hypert, quiet)
if doNobatch:
print( "... finished!\n")
#else:
......@@ -205,16 +223,13 @@ def main(argv):
print(ranges)
#run simulations of all possible combinations
args = [N, baseFileName, inputfilePath, tmplFile, oinpFile, doTest, doKeep, doNobatch, info, queue, hypert, quiet]
args = [N, baseFileName, inputfilePath, tmplFile, oinpFile, doTest, doKeep, doNobatch, doOptimize, info, queue, hypert, quiet]
traverseRanges(list(ranges.items()), opaldict, args, doNobatch)
# clean up
os.system("rm -f *.bak ")
os.chdir("..")
# clean up
if os.path.isfile("tmplbak17.tmpl"):
os.system("mv tmplbak17.tmpl " + "." + baseFileName + ".tmpl")
#call main
if __name__ == "__main__":
......
......@@ -10,7 +10,7 @@ import sys,os,shutil, subprocess
#import numpy as np
# Helper methods
### Helper methods
def isInDirectory(filepath, directory):
# From https://stackoverflow.com/questions/3812849/how-to-check-whether-a-directory-is-a-sub-directory-of-another-directory
''' Check if filepath is inside directory '''
......@@ -23,14 +23,29 @@ def linkDirectory(path, name=''):
print (name + ' directory is subdirectory of working directory! runOPAL cannot handle this.. bye!')
sys.exit()
# lndir and if fails try cp
if os.system('lndir ' + path) != 0:
#print("lndir failed (possibly doesn't exist on this system), using cp -rs..."),
if os.system('lndir '+path) != 0:
print("lndir failed (possibly doesn't exist on this system), using ln -rs... \n"), #EDIT: '\n' added
if os.listdir(path):
os.system('cp -rs ' + path + '/* .')
os.system('ln -rs '+path+'/* .') #EDIT: changed from cp to ln
def linkFile(path, name): #EDIT: new helper function for convenience
'''Make a file available in working directory with a symbolic link'''
path = os.path.join(path,name)
if not os.path.isfile(path):
print (name+' cannot be found')
sys.exit()
os.system('ln -s '+path+' .')
def extractStr(line, name):
zero = line.find(name)
if zero < 0:
return None
start = min(x for x in [line.find('"',zero ), line.find("'", zero )] if x > 0) +1
end = min(x for x in [line.find('"',start), line.find("'", start)] if x > 0)
return line[start:end]
class Simulation:
class Simulation:
def __init__(self, opaldict):
self.opaldict = opaldict
self.dirname = ""
......@@ -51,12 +66,11 @@ class Simulation:
os.mkdir(self.dirname)
return True
def run(self,N, baseFileName, inputfilePath, tmplFile, oinpFile, doTest, doKeep, doNobatch, info, queue, hypert, quiet):
def run(self,N, baseFileName, inputfilePath, tmplFile, oinpFile, doTest, doKeep, doNobatch, doOptimize, info, queue, hypert, quiet):
# make directory name indicating changed values
self.dirname = baseFileName
if N >= 0:
self.dirname += str(N)
self.dirname += self.opaldict.generateDirectoryName()
try:
......@@ -78,7 +92,6 @@ class Simulation:
if not (os.path.isdir(fieldmapPath)):
print( 'Fieldmap directory unknown exiting ...')
sys.exit()
linkDirectory(fieldmapPath,'Fieldmap')
# Link distribution directory if present
......@@ -89,18 +102,39 @@ class Simulation:
# Read in the file
filedata = None
with open(inputfilePath + tmplFile, 'r') as file :
with open(tmplFile, 'r') as file :
filedata = file.read()
# do the replacements in the templatefile
for s,value in self.opaldict.items():
# Replace the target string
filedata = filedata.replace('_'+s+'_', str(value))
# Write the file out again
with open(oinpFile, 'w') as file:
file.write(filedata)
#EDIT: Link .tmpl and .dat files or OPTIMIZE
#NOTE: What's the best place to link tmpl file? $TEMPLATES, _TEMPLATEDIR_, or parisng?
if doOptimize:
flag = False
tmplDir = None
tmplIn = None
templateFile = open(oinpFile,'r')
for line in templateFile:
if not line.startswith('//'):
if 'OPTIMIZE' in line:
flag = True
if flag and not tmplDir:
tmplDir = extractStr(line,'TEMPLATEDIR')
if flag and not tmplIn:
tmplIn = extractStr(line,'INPUT').split('/')[-1]
templateFile.close()
linkFile('..', tmplIn[:-5]+'.data')
os.mkdir(tmplDir)
os.chdir(tmplDir)
linkFile(os.path.join('../..',tmplDir), tmplIn)
os.chdir('..')
if os.environ.get('OPAL_EXE_PATH'):
if doNobatch:
opalexe = os.environ.get('OPAL_EXE_PATH') + '/opal'
......@@ -113,8 +147,7 @@ class Simulation:
print( 'Using templatefile at ' + inputfilePath)
print( 'Using fieldmaps at ' + fieldmapPath)
print( 'Parameter set in ' + oinpFile + ' are:')
for s, value in sorted(self.opaldict.items()):
for s, value in sorted(self.opaldict.items()): #EDIT: fixed indentation
if quiet == False:
print( ' :::: ' + s + ' = ' + str(value))
......@@ -242,6 +275,8 @@ class Simulation:
os.chdir('..')
return qid
### Write for host
def WriteCori(self, opalexe, oinpFile, cores, time, ram, info, name):
title=oinpFile.partition(".")[0]
myfile = open(name,'w')
......@@ -255,6 +290,7 @@ class Simulation:
myfile.write(s1)
myfile.close()
def WriteEngaging(self, opalexe, oinpFile, cores, time, ram, info, name):
print("Writing SLURM run file for Engaging cluster at MIT")
......@@ -322,6 +358,7 @@ class Simulation:
outfile.write("#Note that mpirun knows from SLURM how many processor we have\n")
outfile.write("mpirun {} {} --info {} --warn 6\n".format(opalexe, oinpFile, info))
def WriteEdison(self, opalexe, oinpFile, cores, time, ram, info, name):
title=oinpFile.partition(".")[0]
......@@ -348,11 +385,7 @@ class Simulation:
def WriteMerlin5(self, opalexe, oinpFile, cores, time, ram, info, name, partition):
#
# ADA this is for the new PSI Merlin5
#
title = oinpFile.partition(".")[0]
myfile = open(name, 'w')
s1 = "#!/bin/bash -l \n"
......@@ -372,12 +405,11 @@ class Simulation:
myfile.write(s1)
myfile.close()
def WritePizDaint(self, opalexe, oinpFile, cores, time, ram, info, name, partition):
def WritePizDaint(self, opalexe, oinpFile, cores, time, ram, info, name, partition):
# XC40 Compute Nodes
# Intel Xeon E5-2696 v4 @ 2.10GHz (2x18 cores, 64/128 GB RAM)
# http://user.cscs.ch/computing_systems/piz_daint/index.html
coresPerNode = 36
title = oinpFile.partition(".")[0]
myfile = open(name, 'w')
......@@ -398,6 +430,7 @@ class Simulation:
myfile.write(s1)
myfile.close()
def WritePBSBlues(self, opalexe, oinpFile, cores, time, ram, info, queue):
# time <- export SGE_TIME="walltime=0:20:00"
# cores <- export CORES="nodes=1:ppn=16"
......@@ -437,6 +470,7 @@ class Simulation:
myfile.write(s1)
myfile.close()
def WriteBebop(self, opalexe, oinpFile, cores, time, ram, info, name, queue, hypert, quiet):
# BDW and KNL Compute Nodes at ANL
# http://www.lcrc.anl.gov/for-users/using-lcrc/running-jobs/running-jobs-on-bebop/
......@@ -501,6 +535,7 @@ class Simulation:
myfile.write(s1)
def WriteTheta(self, opalexe, oinpFile, cores, time, ram, info, queue, hypert):
# queue = default, debug-cache-quad, debug-flat-quad
# cores = min of 8 nodes for default queue
......@@ -564,8 +599,4 @@ class Simulation:
myfile.write(s1)
myfile.close()
os.chmod("run.sh", 0o775)
#aprun -n $n_mpi_ranks -N $n_mpi_ranks_per_node \
#--env OMP_NUM_THREADS=$n_openmp_threads_per_rank -cc depth \
# -d $n_hyperthreads_skipped_between_ranks \
# -j $n_hyperthreads_per_core \
# <executable> <executable args>
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment