From 121497647930955094f16d038d3c114b3efe9dd6 Mon Sep 17 00:00:00 2001 From: Eric Fayolle Date: Thu, 1 Sep 2022 18:11:57 +0200 Subject: [PATCH] =?utf8?q?Diverses=20am=C3=A9liorations=20pour=20la=20gest?= =?utf8?q?ion=20et=20le=20lancement=20des=20incertitudes?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- generator/generator_UQ.py | 46 +++++++++++++++++------- generator/post_csv_rn.py | 72 +------------------------------------- generator/textePersalys.py | 44 +++++++++++++++++------ 3 files changed, 69 insertions(+), 93 deletions(-) diff --git a/generator/generator_UQ.py b/generator/generator_UQ.py index e709a3d6..40627a1d 100644 --- a/generator/generator_UQ.py +++ b/generator/generator_UQ.py @@ -41,7 +41,7 @@ from .textePersalys import optionalResultTaylor, optionalPrintResultTaylor from .textePersalys import centralTendencyMC, resultMC from .textePersalys import critereArretMC, advancedParameterMC from .textePersalys import optionalResultMC, optionalPrintResultMC -from .textePersalys import yacsJobParameters +from .textePersalys import yacsJobParameters, yacsJobClusterParameters, yacsJobClusterMultiJob def entryPoint(): """ @@ -88,7 +88,7 @@ class UQGenerator(PythonGenerator): def creeNomsFichiers(self,fichier): print ('creeNomsFichiers', fichier) - self.cheminFichierComm=os.path.dirname(fichier) + self.cheminFichierComm=os.path.abspath(os.path.dirname(fichier)) if fichier.endswith('.comm'): self.fichierSansSuffixe=os.path.basename(fichier[:-5]) if self.fichierSansSuffixe.endswith('_UQ'): @@ -161,6 +161,7 @@ class UQGenerator(PythonGenerator): self.nomsDesVariablesInput.append(mc.variableDeterministe.nom) self.mcIncertains.append(mc.variableDeterministe) sectionOutput = etapeIncertitude.getChildOrChildInBloc('Output')[0] + self.ScriptPosttraitement = sectionOutput.getChildOrChildInBloc('ScriptPosttraitement').valeur self.chaineDesVariablesInput=self.chaineDesVariablesInput[0:-2] sectionPropagation = etapeIncertitude.getChildOrChildInBloc('Propagation')[0] @@ -231,15 +232,22 @@ class UQGenerator(PythonGenerator): self.NbDeBranches = sectionExecution.getChildOrChildInBloc('NbDeBranches').valeur if sectionExecution.getChildOrChildInBloc('ExecutionMode') != None : self.ExecutionMode = sectionExecution.getChildOrChildInBloc('ExecutionMode').valeur - self.NbOfProcs = sectionExecution.getChildOrChildInBloc('NbOfProcs').valeur self.JobName = sectionExecution.getChildOrChildInBloc('JobName').valeur self.ResourceName = sectionExecution.getChildOrChildInBloc('ResourceName').valeur self.Login = sectionExecution.getChildOrChildInBloc('Login').valeur self.WorkDirectory = sectionExecution.getChildOrChildInBloc('WorkDirectory').valeur self.ResultDirectory = sectionExecution.getChildOrChildInBloc('ResultDirectory').valeur - MultiJobStudy=sectionExecution.getChildOrChildInBloc('MultiJobStudy') + self.ScriptDeLancement = sectionExecution.getChildOrChildInBloc('ScriptDeLancement').valeur + NbOfProcs = sectionExecution.getChildOrChildInBloc('NbOfProcs') # None si 'desktop', vérification à faire ds jobmanager + MultiJobStudy=sectionExecution.getChildOrChildInBloc('MultiJobStudy') # None si 'desktop' + if (NbOfProcs != None): + self.NbOfProcs = NbOfProcs.valeur + else: + self.NbOfProcs = None if (MultiJobStudy != None): self.MultiJobStudy = MultiJobStudy.valeur + else: + self.MultiJobStudy = None self.creeScriptPersalys() #else : # TODO : creer ici le script URANIE @@ -283,7 +291,7 @@ class UQGenerator(PythonGenerator): def getStrInitList(l): return getStrVarList( map(lambda x:'self.{} = {}'.format(x,x),l), '\n'+2*self.indent1 ) def getStrReplaceVarList(l): - return getStrVarList( map(lambda x:"'@{}@': repr(self.{})".format(x,x), l), ',' ) + return getStrVarList( map(lambda x:"'@ {} @': repr(self.{})".format(x,x), l), ',' ) def getStrSelfVarList(l): return getStrVarList( map(lambda x:'self.{}'.format(x),l), ',' ) @@ -300,7 +308,10 @@ class UQGenerator(PythonGenerator): chaineInitDesVariablesInput = getStrInitList(self.nomsDesVariablesInput), commFileUQBalise = self.fichierUQBalise, commFileUQComm = self.fichierUQComm, - nproc = self.NbOfProcs, + nproc = self.NbOfProcs, #En local le nombre de procs est inutile + #sauf si lancement mpi externe au script applicatif + # auquel cas != NbOfTasks du jobmanager car + # on ne compte pas les threads replaceDataList = getStrReplaceVarList(self.nomsDesVariablesInput) ) @@ -378,19 +389,30 @@ class UQGenerator(PythonGenerator): inFiles.append(os.path.join(self.cheminFichierComm,pyFile)) pyFile = self.fichierUQBalise inFiles.append(os.path.join(self.cheminFichierComm,pyFile)) - scriptFile = "ib_test.sh" - inFiles.append(os.path.join(self.cheminFichierComm,scriptFile)) - postFile = "post_csv.py" - inFiles.append(os.path.join(os.getcwd(),postFile)) + scriptFile = os.path.abspath(self.ScriptDeLancement ) + inFiles.append(scriptFile) + postFile = os.path.abspath(self.ScriptPosttraitement ) + inFiles.append(postFile) + + if (self.ExecutionMode == 'cluster'): + txtYacsJobClusterParameters=yacsJobClusterParameters.format( + nprocs = self.NbOfProcs, + wckey = wckey + ) + else: + txtYacsJobClusterParameters="" + txtYacsJobParameters=yacsJobParameters.format( nomEtude = self.JobName, workDirectory = self.WorkDirectory, resultDirectory = self.ResultDirectory, resourceName = self.ResourceName, - nprocs = self.NbOfProcs, - wckey = wckey, + nbBranches = self.NbDeBranches, inFiles = repr(inFiles) ) + txtYacsJobParameters+=txtYacsJobClusterParameters + if ( self.MultiJobStudy != None): + txtYacsJobParameters+= yacsJobClusterMultiJob self.txtScriptPersalys += mainPersalys.format( nomEtude=nomEtude, diff --git a/generator/post_csv_rn.py b/generator/post_csv_rn.py index 057e6386..e3ad0685 100644 --- a/generator/post_csv_rn.py +++ b/generator/post_csv_rn.py @@ -90,79 +90,9 @@ def get_result_from_csv(variableName:str, functionList, filename:str=None, delim print(sys.stderr,"The transient duration name {} differs from the file's header one {}".format(transientName, header_transient_name)) return -1 #TODO Exception ? - date_value_array=np.loadtxt(file_csv, delimiter = delimiter, skiprows = 1)[:,1:3] + date_value_array=np.loadtxt(filename, delimiter = delimiter, skiprows = 1)[:,1:3] valList=[] for func in functionList: valList.append(func(date_value_array)) return valList -def get_result_from_csv_v0(variableName:str, function, filename:str=None, delimiter=','): - from csv import reader - - #ex: file_csv = "Fuel temperature@Thermalhydraulics@MAX.csv" - if filename == None: filename = variableName+'.csv' - - with open(filename, "r") as csv_file: - csv_reader = reader(csv_file, delimiter=delimiter) - header = next(csv_reader) - header_variable_name=header[-1] - if header_variable_name != variableName: - print(sys.stderr,"The variable name {} differs from the file's header one {}".format(variableName, header_variable_name)) - return -1 #TODO Exception ? - # print("Header:") - # print(", ".join(header)) - # print("Values:") - # for row in csv_reader: - # print(", ".join(row)) - return function(csv_reader)[-1] - -# import csv - -# #fich_csv = "Execution_APOLLO3/Neutronic power@Neutronics@SUM.csv" -# fich_csv = "Fuel temperature@Thermalhydraulics@MAX.csv" -# file_csv = open(fich_csv) - -# fich_sort = 'point.res' - -# csvReader = csv.reader(file_csv, delimiter=',') -# header = [] -# header = next(csvReader) -# # Pour APOLLO3 ? -# # if len(header) != 2: -# # print("Correction des headers contenant des espaces") -# # tmp = header -# # header = [] -# # header.append(tmp[1]) -# # header.append(tmp[-2] + " " + tmp[-1]) -# print(header) - -# rows = [] -# for row in csvReader: -# ligne = [] -# for elem in row: -# if elem != '': -# ligne.append(float(elem)) -# rows.append(ligne) -# #print(ligne) -# print(rows) - -# # reperage des valeurs min et max -# point_min = rows[0] -# point_max = rows[0] -# for point in rows: -# if point[2] < point_min[2]: -# point_min = point -# if point[2] > point_max[2]: -# point_max = point - -# # impression dans un fichier res de sortie -# print("point min") -# print(point_min) -# print("point max") -# print(point_max) - -# txt = "# time_min min time_max max\n" -# txt += "{0} {1} {2} {3}".format(point_min[0],point_min[1],point_max[0],point_max[1]) - -# file_sort = open(fich_sort,'w') -# file_sort.write(txt) diff --git a/generator/textePersalys.py b/generator/textePersalys.py index 21f69cab..5a1e49d8 100644 --- a/generator/textePersalys.py +++ b/generator/textePersalys.py @@ -9,8 +9,8 @@ headerScriptPersalys = """#! /usr/bin/env python3 # -------------------------------------------------------------------------- # Script Eficas genere pour lancement Etude Probabiliste # --------------------------------------------------------------------------- -# Utilisation standalone avec salome : -# salome shell -- python3 mon_fichier.py +# Exemple d'utilisation standalone avec salome : +# salome start -k -t python3 mon_fichier_uq_genere.py # Chargement du module systeme import sys @@ -88,26 +88,34 @@ class Study: #section spécifique au code de calcul comm_file_uq_balise = '{commFileUQBalise}' - self.nproc = {nproc} + self.nproc = {nproc} # La présence de cette variable dépend + # du mode de lancement MPI + # S'il est géré par le script appelé à partir du MDD, il est inutile de le stocker self.comm_file_uq_balise = os.path.join(self.workdir, comm_file_uq_balise) shutil.copy(comm_file_uq_balise, self.comm_file_uq_balise) self.comm_file_uq_comm = os.path.join(self.workdir, '{commFileUQComm}') replace_data(self.comm_file_uq_balise, {{ {replaceDataList} }} , self.comm_file_uq_comm) + #TODO: Lancer la validation du fichier généré avant tout lancement pass def get_result_from_csv(self,postProcessedVar, aggregationFctList): - from post_csv import get_result_from_csv + from post_csv_rn import get_result_from_csv #Fonctions a implementer dans un fichier post_csv pour définir #comment l'aggrégation des valeurs peut se faire - from post_csv import vInitialTime, vHalfTime, vFinalTime, vMean, vSum, vMin, vMax + from post_csv_rn import vInitialTime, vHalfTime, vFinalTime, vMean, vSum, vMin, vMax print('--------------------------------------- 4 ---------------------------------------') - return get_result_from_csv(postProcessedVar, aggregationFctList) + savdir=os.getcwd() + os.chdir(self.workdir) + results = get_result_from_csv(postProcessedVar, aggregationFctList) + os.chdir(savdir) + return results def run_case(self): print('--------------------------------------- 5 ---------------------------------------') #os.chdir(self.workdir) + # Si lancement mpi externe à ib_test.sh il faut utiliser self.nproc : mpiexec -n self.nproc ib_test.sh o,e,c = self.do_sh(command="ib_test.sh", execdir=self.workdir) if o != None : print('o.decode() : ',o.decode()) if e != None : print('e.decode() : ',e.decode()) @@ -126,7 +134,7 @@ getResultCall=""" {variableOutputList} = study.get_result_from_csv( '{nomVarP # ------------------------ fonctionPersalys = """ def _exec({chaineDesVariablesInput}): - from post_csv import vInitialTime, vHalfTime, vFinalTime, vMean, vSum, vMin, vMax + from post_csv_rn import vInitialTime, vHalfTime, vFinalTime, vMean, vSum, vMin, vMax print('--------------------------------------- 00 ---------------------------------------') @@ -286,15 +294,31 @@ optionalPrintResultMC={ # ##nputSample=designOfExperiment.getInputSample() # ##computeQuantile=inputSample.computeQuantile(0.95) + +#En local le nombre de procs est inutile yacsJobParameters=""" + yacsPhysicalModel.jobParameters().salome_parameters.resource_required.name = '{resourceName}' yacsPhysicalModel.jobParameters().salome_parameters.job_name = '{nomEtude}' yacsPhysicalModel.jobParameters().salome_parameters.work_directory = '{workDirectory}' yacsPhysicalModel.jobParameters().salome_parameters.result_directory = '{resultDirectory}' - yacsPhysicalModel.jobParameters().salome_parameters.resource_required.name = '{resourceName}' + yacsPhysicalModel.jobParameters().salome_parameters.in_files = {inFiles} # Chemins des fichiers locaux à copier dans work_directory + yacsPhysicalModel.jobParameters().nb_branches = {nbBranches} # nombre de jobs parallèles +""" + +# Le nombre de procs du job manager est uniquement utile pour les clusters +yacsJobClusterParameters=""" yacsPhysicalModel.jobParameters().salome_parameters.resource_required.nb_proc = {nprocs} yacsPhysicalModel.jobParameters().salome_parameters.wckey = '{wckey}' - yacsPhysicalModel.jobParameters().salome_parameters.in_files = {inFiles} # Chemins des fichiers locaux à copier dans work_directory - yacsPhysicalModel.jobParameters().nb_branches = {nprocs} # nombre de jobs parallèles +""" + +# Ces 3 lignes permettent de modifier le mode d'évaluation par défaut qui est +# d'avoir toutes les évaluations dans un seul job. +# Ici jobs seront crées dynamiquement pour lancer chaque évaluation +# chaque job demandera la réservation de nprocs processus. +yacsJobClusterMultiJob=""" +import pydefx +multiJobModel = pydefx.MultiJobStudy() # mode un job par évaluation +yacsPhysicalModel.setJobModel(multiJobModel) """ yacsJobParametersRef=""" -- 2.39.2