# -*- coding: iso-8859-1 -*-
#
#-------------------------------------------------------------------------------
# Code_Saturne version 1.3
# ------------------------
#
#
# This file is part of the Code_Saturne User Interface, element of the
# Code_Saturne CFD tool.
#
# Copyright (C) 1998-2007 EDF S.A., France
#
# contact: saturne-support@edf.fr
#
# The Code_Saturne User Interface is free software; you can redistribute it
# and/or modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 of
# the License, or (at your option) any later version.
#
# The Code_Saturne User Interface is distributed in the hope that it will be
# useful, but WITHOUT ANY WARRANTY; without even the implied warranty
# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with the Code_Saturne Kernel; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301 USA
#
#-------------------------------------------------------------------------------
"""
This module modify the "lance" script file
- BatchRunningModel
"""
#-------------------------------------------------------------------------------
# Standard modules import
#-------------------------------------------------------------------------------
import sys, unittest
import os, sys, string, types, re
#-------------------------------------------------------------------------------
# Library modules import
#-------------------------------------------------------------------------------
import Base.Toolbox as Tool
from SolutionDomainModel import SolutionDomainModel
from CoalCombustion import CoalCombustionModel
#-------------------------------------------------------------------------------
# Class BatchRunningModel
#-------------------------------------------------------------------------------
class BatchRunningModel:
"""
This class modify saturne running file (lance)
"""
def __init__(self, case):
"""
Simple constructor.
"""
self.case = case
# we get up batch script file
key = self.case['computer']
# FIXME: la ligne suivante est-elle utile ?
if not self.case['batchScript'][key]: return
self.script1 = self.case['scripts_path'] + "/" \
+ self.case['batchScript'][key]
self.saveBatchScriptFile()
# Read the batch script file line by line.
# All lines are stored in a list called "self.lines".
#
f = open(self.script1, 'rw')
self.lines = f.readlines()
f.close()
# DicoValues's initialisation
self.initDicoValues()
def saveBatchScriptFile(self):
"""
Save a backup file before any modification.
There is only one backup for the entire session.
"""
key = self.case['computer']
script2 = self.script1 + "~"
if self.case['backupBatchScript'][key] == "no" \
or not os.path.isfile(script2):
os.popen('cp ' + self.script1 + " " +script2)
self.case['backupBatchScript'][key] = "yes"
def initDicoValues(self):
"""
Tkinter variables declaration.
"""
self.dicoValues = {}
self.dicoValues['IFOENV'] = '1'
self.dicoValues['LONGIA'] = '0'
self.dicoValues['LONGRA'] = '0'
self.dicoValues['PARAM'] = ""
self.dicoValues['VERSION'] = ""
self.dicoValues['NOMBRE_DE_PROCESSEURS'] = '1'
self.dicoValues['LISTE_PROCESSEURS'] = ""
self.dicoValues['FICHIERS_DONNEES_UTILISATEUR'] = ""
self.dicoValues['FICHIERS_RESULTATS_UTILISATEUR'] = ""
self.dicoValues['CS_TMP_PREFIX'] = ""
self.dicoValues['MAILLAGE'] = ""
self.dicoValues['COMMANDE_RC'] = ""
self.dicoValues['COMMANDE_DF'] = ""
self.dicoValues['COMMANDE_PERIO'] = ""
self.dicoValues['COMMANDE_SYRTHES'] = ""
self.dicoValues['PBS_JOB_NAME'] = ""
self.dicoValues['PBS_nodes'] = '1'
self.dicoValues['PBS_ppn'] = '2'
self.dicoValues['PBS_walltime'] = '1:00:00'
self.dicoValues['PBS_mem'] = '320'
self.dicoValues['MODE_EXEC'] = ""
self.dicoValues['OPTIMISATION'] = ""
self.dicoValues['LISTE_LIB_SAT'] = ""
self.dicoValues['OPTION_LIB_EXT'] = ""
self.dicoValues['VALGRIND'] = ""
self.dicoValues['ARG_CS_OUTPUT'] = ""
self.dicoValues['ARG_CS_VERIF'] = ""
self.dicoValues['DONNEES_THERMOCHIMIE'] = ""
model = CoalCombustionModel(self.case).getCoalCombustionModel()
if model == 'coal_homo':
self.dicoValues['DONNEES_THERMOCHIMIE'] = 'dp_FCP'
def getRegex(self, word):
"""
Get regular expression to extract line without comment
"""
## fonctionne mais incomplète: regex = re.compile(r"""(^\s*""" + word + r""".*$)""")
## fonctionne en tenant compte des lignes commencant par # :
## regex = re.compile(r"""(^(?#)^\s*""" + word + r""".*$)""")
#tient compte à la fois des commentaires et des "$word":
regex = re.compile(r"""(^(?#)^\s*(?<!$)""" + word + r""".*$)""")
return regex
def getLineToModify(self, regex, txt):
"""
Search word in txt if and only if it's not a comment
"""
pattern = None
if regex != None :
pattern = regex.search(txt)
return pattern
def substituteLine(self, pattern, newword, txt):
"""
Substitute pattern by newword
"""
new_pattern = pattern.re.sub(newword, txt, re.VERBOSE)
return new_pattern
def getValueInPattern(self, pattern, word, dico):
"""
Return value of pattern
"""
self.dicoValues[word] = dico
resu = pattern.group().split('=')
L = resu[1]
for i in range(2,len(resu)): L = L + "="+ resu[i]
resu = L
if resu:
if resu.split(' ')[0] == '': resu = resu.split(' ')[1]
if resu == '""': resu =''
else:
resu =''
self.dicoValues[word] = resu
return self.dicoValues[word]
def removeQuotes(self, line, index=0, word=""):
"""
1) Delete quotes and return caracters,
2) Return the associated value of the word
"""
if not line: return ""
ch = line[index+len(word):]
if not ch: return ""
ch = string.join(string.split(ch))
try:
if ch[-1:] == '\n': ch = ch[:-1]
except IndexError:
pass
try:
if ch[-1:] == '"': ch = ch[:-1]
except IndexError:
pass
try:
if ch[0] == '"': ch = ch[1:]
except IndexError:
pass
ch = string.join(string.split(ch))
return ch
def addQuotes(self, ch):
"""
Add quotes in front of and behind string c.
"""
ch = string.join(string.split(ch))
if string.rfind(ch, " ") != -1:
ch = '"' + ch + '"'
return ch
def readBatchScriptFile(self):
"""
Fill self.dicoValues reading the backup file.
"""
lines = self.lines
list = ['PBS_JOB_NAME','PBS_nodes','PBS_ppn','PBS_walltime','PBS_mem']
for k in self.dicoValues.keys():
if k not in list and k != 'DONNEES_THERMOCHIMIE':
nbkey = 0
for i in range(len(lines)):
reg = self.getRegex(k)
if reg != None:
pat = self.getLineToModify(reg, lines[i])
if pat != None:
nbkey = nbkey + 1
if nbkey == 1:
ch = self.getValueInPattern(pat, k, self.dicoValues)
ch = self.removeQuotes(str(ch))
self.dicoValues[k] = ch
else:
# If there are more than one occurence of the keyword in the
# batch script file, only the first one is modified
#
pass
if self.case['computer'] == "cluster":
for (word, ind, lab) in [('#PBS -j eo -N ', 0, 'PBS_JOB_NAME')]:
for i in range(len(lines)):
index = string.rfind(lines[i], word)
if index == ind:
self.dicoValues[lab] = self.removeQuotes(lines[i], ind, word)
for (word, next, lab) in [('#PBS -l nodes', ':ppn' , 'PBS_nodes'),
(':ppn' ,',walltime', 'PBS_ppn'),
(',walltime' ,',mem' , 'PBS_walltime'),
(',mem' , 'mb' , 'PBS_mem')]:
word = word + "="
for i in range(len(lines)):
ind1 = string.rfind(lines[i], word)
ind2 = string.rfind(lines[i], next)
if ind1 != -1 and ind2 != -1:
ch = lines[i][ind1+len(word):ind2]
self.dicoValues[lab] = ch
self.initializeBatchScriptFile()
def initializeBatchScriptFile(self):
"""
Initialize the backup file from reading dictionary self.dicoValues the first time.
"""
# keywords about Enveloppe Code_Saturne
#
# Basic verification
#
node_ecs = self.case.xmlGetNode('solution_domain')
if not Tool.GuiParam.matisse:
if not node_ecs:
tkMessageBox.showwarning(t.WARNING, "todo: pas de rubrique enveloppe !")
# MAILLAGE
#
try:
meshList = SolutionDomainModel(self.case).getMeshList()
meshes = string.join(meshList)
if meshes:
self.dicoValues['MAILLAGE'] = meshes
else:
tkMessageBox.showwarning (t.WARNING, "todo: pas de maillage !")
except:
self.dicoValues['MAILLAGE'] = ''
# COMMANDE_RC
#
try:
commande_rc = SolutionDomainModel(self.case).getPasteCommand()
if commande_rc:
self.dicoValues['COMMANDE_RC'] = commande_rc
except:
self.dicoValues['COMMANDE_RC'] = ''
# COMMANDE_DF
#
try:
commande_df = SolutionDomainModel(self.case).getCutCommand()
if commande_df:
self.dicoValues['COMMANDE_DF'] = commande_df
except:
self.dicoValues['COMMANDE_DF'] = ''
# COMMANDE_PERIO
#
try:
commande_pr = SolutionDomainModel(self.case).getPerioCommand(1)
if commande_pr:
self.dicoValues['COMMANDE_PERIO'] = commande_pr
except:
self.dicoValues['COMMANDE_PERIO'] = ''
# COMMANDE_SYRTHES
#
try:
commande_syrthes = SolutionDomainModel(self.case).getSyrthesCommand()
if commande_syrthes:
self.dicoValues['COMMANDE_SYRTHES'] = commande_syrthes
except:
self.dicoValues['COMMANDE_SYRTHES'] = ''
# keywords for all computers
#
self.dicoValues['PARAM'] = os.path.basename(self.case['xmlfile'])
def updateBatchScriptFile(self, keyword=None):
"""
Update the backup file from reading dictionary self.dicoValues.
"""
lines = self.lines
if self.case['computer'] == "cluster":
self.dicoValues['NOMBRE_DE_PROCESSEURS'] = ""
for k in self.dicoValues.keys():
nbkey = 0
if keyword: k = keyword
for i in range(len(lines)):
if self.getRegex(k) != None:
pat = self.getLineToModify(self.getRegex(k),lines[i])
if pat != None:
nbkey = nbkey + 1
if nbkey == 1:
ch = self.addQuotes(str(self.dicoValues[k]))
new = k + "=" + ch
lines[i] = self.substituteLine(pat, new, lines[i])
if keyword: break
# keywords only for the PBS Cluster
#
if self.case['computer'] == "cluster":
if self.dicoValues['PBS_nodes'] == 0: self.dicoValues['PBS_nodes'] = 1
if self.dicoValues['PBS_ppn'] == 0: self.dicoValues['PBS_ppn']= 1
for (word, ind, var) in [('#PBS -j eo -N ', 0, self.dicoValues['PBS_JOB_NAME']) ]:
for i in range(len(lines)):
index = string.rfind(lines[i], word)
if index == ind:
if type(var) != types.StringType :
var = str(var)
if var == "0" : var=""
lines[i] = word + var + '\n'
for (word, ind, next) in [('#PBS -l nodes', 0, ':ppn')]:
for i in range(len(lines)):
ind1 = string.rfind(lines[i], word)
ind2 = string.rfind(lines[i], next)
if ind1 == ind and ind2 != -1:
ch = ""
for (w,dic) in [('#PBS -l nodes=', self.dicoValues['PBS_nodes']) ,
(':ppn=', self.dicoValues['PBS_ppn']) ,
(',walltime=', self.dicoValues['PBS_walltime']) ,
(',mem=', self.dicoValues['PBS_mem'])]:
ch = ch + w + str(dic)
lines[i] = ch + "mb\n"
f = open(self.script1, 'w')
f.writelines(lines)
f.close()
os.system('chmod +x ' + self.script1)
#-------------------------------------------------------------------------------
# BatchRunningModel test class
#-------------------------------------------------------------------------------
class BatchRunningModelTestCase(unittest.TestCase):
"""
"""
def setUp(self):
"""
This method is executed before all 'check' methods.
"""
from Base.XMLengine import Case
from Base.XMLinitialize import XMLinit
from Base.Toolbox import GuiParam
GuiParam.lang = 'en'
self.case = Case(None)
XMLinit(self.case)
domain = SolutionDomainModel(self.case)
domain.setMesh('mail1.des', 'des')
domain.setMesh('mail2.des', 'des')
domain.setMesh('mail3.des', 'des')
self.case['xmlfile'] = 'NEW.xml'
self.case['computer'] = 'station'
self.case['scripts_path'] = os.getcwd()
self.case['batchScript'] = {'cluster': 'lance_PBS', 'ccrt': 'lance_LSF', 'station': 'lance_test'}
self.case['backupBatchScript'] = {'cluster': 'yes', 'ccrt': 'yes', 'station': 'yes'}
lance_test = '# test \n'\
'#IFOENV=6\n'\
'IFOENV=999\n'\
'#LONGIA=99999999999 \n'\
'LONGIA=123\n'\
'LONGRA=324\n'\
'PARAM=NEW.xml\n'\
'VERSION=tutu\n'\
'NOMBRE_DE_PROCESSEURS=2\n'\
'LISTE_PROCESSEURS=\n'\
'FICHIERS_DONNEES_UTILISATEUR=data\n'\
'FICHIERS_RESULTATS_UTILISATEUR=titi\n'\
'CS_TMP_PREFIX=/home/picard\n'\
'MAILLAGE=\n'\
'COMMANDE_RC=" -rc -couleur 98 99 -fraction 0.1 -plan 0.8"\n'\
'COMMANDE_DF=\n'\
'COMMANDE_PERIO=\n'\
'COMMANDE_SYRTHES=\n'\
'MODE_EXEC=complet\n'\
'OPTIMISATION=''\n'\
'LISTE_LIB_SAT=''\n'\
'OPTION_LIB_EXT=''\n'\
'VALGRIND=''\n'\
'ARG_CS_OUTPUT=''\n'\
'ARG_CS_VERIF=''\n'
lance_PBS = '# test \n'\
'#\n'\
'# CARTES BATCH POUR LE CLUSTER CHATOU sous PBS\n'\
'#\n'\
'#PBS -l nodes=16:ppn=1,walltime=34:77:22,mem=832mb\n'\
'#PBS -j eo -N super_toto\n'
lance_LSF = '# test \n'\
'#\n'\
'# CARTES BATCH POUR LE CCRT (Nickel/Chrome/Tantale sous LSF)\n'\
'#\n'\
'#BSUB -n 2\n'\
'#BSUB -c 00:05\n'\
'#BSUB -o super_tataco.%J\n'\
'#BSUB -e super_tatace.%J\n'\
'#BSUB -J super_truc\n'
self.f = open('lance_test','w')
self.f.write(lance_test)
self.f.close()
self.f = open('lance_PBS','w')
self.f.write(lance_PBS)
self.f.close()
self.f = open('lance_LSF','w')
self.f.write(lance_LSF)
self.f.close()
def tearDown(self):
"""
This method is executed after all 'check' methods.
"""
os.remove(self.case['batchScript']['station'])
os.remove(self.case['batchScript']['cluster'])
os.remove(self.case['batchScript']['ccrt'])
def checkGetRegexAndGetLineToModify(self):
""" Check whether the BatchRunningModel class could be get line"""
mdl = BatchRunningModel(self.case)
txt1 = '# fic = 1 '
txt2 = ' fic=2'
txt3 = 'fic=33'
txt4 = ' fic =55'
txt5 = ' fic = 55'
txt6 = ' fic = " fic jklm " '
regex1 = mdl.getRegex('fic')
regex2 = mdl.getRegex('fic')
regex3 = mdl.getRegex('fic')
regex4 = mdl.getRegex('fic')
regex5 = mdl.getRegex('fic')
regex6 = mdl.getRegex('fic')
pat1 = mdl.getLineToModify(regex1,txt1)
pat2 = mdl.getLineToModify(regex2,txt2)
pat3 = mdl.getLineToModify(regex3,txt3)
pat4 = mdl.getLineToModify(regex4,txt4)
pat5 = mdl.getLineToModify(regex5,txt5)
pat6 = mdl.getLineToModify(regex6,txt6)
assert pat1 == None, 'Could not get pat1 to modify text'
assert pat2.group() == ' fic=2', 'Could not get pat2 to modify text'
assert pat3.group() == 'fic=33', 'Could not get pat3 to modify text'
assert pat4.group() == ' fic =55', 'Could not get pat4 to modify text'
assert pat5.group() == ' fic = 55', 'Could not get pat5 to modify text'
assert pat6.group() == ' fic = " fic jklm " ', 'Could not get pat6 to modify text'
def checkGetValueInPattern(self):
""" Check whether the class could be get value from regular expression"""
mdl = BatchRunningModel(self.case)
dico = {}
txt = 'fic=33'
txt1 = '# fic = 1 '
txt2 = ' fic=2'
txt5 = ' fic = 55'
regex = mdl.getRegex('fic')
pat = mdl.getLineToModify(regex,txt)
value = mdl.getValueInPattern(pat, 'fic', dico)
regex1 = mdl.getRegex('fic')
pat1 = mdl.getLineToModify(regex1,txt1)
regex2 = mdl.getRegex('fic')
pat2 = mdl.getLineToModify(regex2,txt2)
value2 = mdl.getValueInPattern(pat2, 'fic', dico)
regex5 = mdl.getRegex('fic')
pat5 = mdl.getLineToModify(regex5,txt5)
value5 = mdl.getValueInPattern(pat5, 'fic', dico)
assert value == '33','could not get value from regular expression'
assert pat1 == None,'could not get value1 from regular expression'
assert value2 == '2','could not get value2 from regular expression'
assert value5 == '55','could not get value5 from regular expression'
def checkSubstituteLine(self):
""" Check whether the BatchRunningModel class could be substitute line"""
mdl = BatchRunningModel(self.case)
txt1 = ' fic='
txt2 = ' fic= rien'
pat1 = mdl.getLineToModify(mdl.getRegex('fic'),txt1)
new1 = mdl.substituteLine(pat1,'vacances',txt1)
pat2 = mdl.getLineToModify(mdl.getRegex('fic'),txt2)
new_pat2 = 'fic=' + 'vacances'
new2 = mdl.substituteLine(pat2,new_pat2,txt2)
assert new1 == 'vacances','could not substitute line from regular expression'
assert new2 == 'fic=vacances','could not substitute line from regular expression'
## assert pat1 == 'None','could not get value1 from regular expression'
def checkReadBatchScriptFile(self):
""" Check whether the BatchRunningModel class could be read file"""
self.case['computer'] = 'station'
mdl = BatchRunningModel(self.case)
mdl.readBatchScriptFile()
dico = {\
'LONGIA': '123',
'LONGRA': '324',
'LISTE_PROCESSEURS': '',
'PBS_nodes': '1',
'MAILLAGE': 'mail1.des mail2.des mail3.des',
'PBS_JOB_NAME': '',
'COMMANDE_DF': '',
'IFOENV': '999',
'FICHIERS_RESULTATS_UTILISATEUR': 'titi',
'PARAM': 'NEW.xml',
'NOMBRE_DE_PROCESSEURS': '2',
'FICHIERS_DONNEES_UTILISATEUR': 'data',
'COMMANDE_RC': '-rc -couleur 98 99 -fraction 0.1 -plan 0.8',
'VERSION': 'tutu',
'CS_TMP_PREFIX': '/home/picard',
'COMMANDE_SYRTHES': '',
'PBS_ppn': '2',
'PBS_walltime': '1:00:00',
'PBS_mem': '320',
'COMMANDE_PERIO': '',
'MODE_EXEC':'complet',
'OPTIMISATION':'',
'LISTE_LIB_SAT':'',
'OPTION_LIB_EXT':'',
'VALGRIND':'',
'ARG_CS_OUTPUT':'',
'ARG_CS_VERIF':'',
'DONNEES_THERMOCHIMIE':''}
for k in mdl.dicoValues.keys():
if mdl.dicoValues[k] != dico[k]:
print "\nwarning for key: ", k
print " read value in the script:", mdl.dicoValues[k]
print " reference value:", dico[k]
assert mdl.dicoValues[k] == dico[k], 'could not read the batch script file'
assert mdl.dicoValues == dico, 'could not read batch script file'
def checkReadBatchScriptPBS(self):
""" Check whether the BatchRunningModel class could be read file"""
self.case['computer'] = 'cluster'
mdl = BatchRunningModel(self.case)
mdl.readBatchScriptFile()
dico_PBS = {\
'PBS_nodes': '16',
'MAILLAGE': 'mail1.des mail2.des mail3.des',
'PBS_JOB_NAME': 'super_toto',
'COMMANDE_DF': '',
'IFOENV': '1',
'PARAM': 'NEW.xml',
'NOMBRE_DE_PROCESSEURS': '1',
'FICHIERS_DONNEES_UTILISATEUR': '',
'COMMANDE_RC': '',
'CS_TMP_PREFIX': '',
'COMMANDE_SYRTHES': '',
'PBS_ppn': '1',
'PBS_walltime': '34:77:22',
'PBS_mem': '832',
'COMMANDE_PERIO': ''}
for k in dico_PBS.keys():
if mdl.dicoValues[k] != dico_PBS[k] :
print "\nwarning for key: ", k
print " read value in the script:", mdl.dicoValues[k]
print " reference value:", dico_PBS[k]
assert mdl.dicoValues[k] == dico_PBS[k], 'could not read the batch script file'
def checkUpdateBatchScriptFile(self):
""" Check whether the BatchRunningModel class could update file"""
mdl = BatchRunningModel(self.case)
mdl.readBatchScriptFile()
mdl.dicoValues['LONGIA']='888888'
mdl.dicoValues['NOMBRE_DE_PROCESSEURS']='48'
dico_updated = mdl.dicoValues
mdl.updateBatchScriptFile()
mdl.readBatchScriptFile()
dico_read = mdl.dicoValues
assert dico_updated == dico_read, 'error on updating batch script file'
def checkUpdateBatchScriptPBS(self):
""" Check whether the BatchRunningModel class could update file"""
mdl = BatchRunningModel(self.case)
mdl.readBatchScriptFile()
mdl.dicoValues['PBS_mem']='512'
mdl.dicoValues['PBS_walltime']='12:42:52'
dicoPBS_updated = mdl.dicoValues
mdl.updateBatchScriptFile()
mdl.readBatchScriptFile()
dicoPBS_read = mdl.dicoValues
assert dicoPBS_updated == dicoPBS_read, 'error on updating PBS batch script file'
def suite():
testSuite = unittest.makeSuite(BatchRunningModelTestCase, "check")
return testSuite
def runTest():
print "BatchRunningModelTestCase"
runner = unittest.TextTestRunner()
runner.run(suite())
#-------------------------------------------------------------------------------
# End of BacthRunningModel
#-------------------------------------------------------------------------------
syntax highlighted by Code2HTML, v. 0.9.1