1 #@ MODIF macr_recal_ops Macro DATE 04/11/2008 AUTEUR ASSIRE A.ASSIRE
2 # -*- coding: iso-8859-1 -*-
3 # CONFIGURATION MANAGEMENT OF EDF VERSION
4 # ======================================================================
5 # COPYRIGHT (C) 1991 - 2002 EDF R&D WWW.CODE-ASTER.ORG
6 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
7 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
8 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
9 # (AT YOUR OPTION) ANY LATER VERSION.
11 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
12 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
13 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
14 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.
16 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
17 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
18 # 1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
19 # ======================================================================
20 # RESPONSABLE ASSIRE A.ASSIRE
22 import os, sys, copy, math
33 type_fonctionnelle = 'float'
35 from externe_mess import UTMESS
37 # --------------------------------------------------------------------------------------------------
38 def Ecriture_Fonctionnelle(output_file, type_fonctionnelle, fonctionnelle):
40 try: os.remove(output_file)
43 f=open(output_file, 'w')
44 if type_fonctionnelle == 'vector':
45 fonctionnelle = str(fonctionnelle.tolist())
46 fonctionnelle = fonctionnelle.replace('[','')
47 fonctionnelle = fonctionnelle.replace(']','')
48 f.write(str(fonctionnelle))
52 # --------------------------------------------------------------------------------------------------
53 def Ecriture_Derivees(output_file, derivees):
55 try: os.remove(output_file)
58 # On sort si il n'y a pas de derivees a imprimer
59 if not derivees: return
63 for l in range(len(a[:,0])):
65 for c in range(len(a[0,:])):
66 ligne.append( str(a[l,c]) )
67 txt += ','.join(ligne) + '\n'
69 f=open(output_file, 'w')
74 # --------------------------------------------------------------------------------------------------
75 def Sortie(LIST_NOM_PARA, LIST_PARA, val, CALCUL_ASTER, Mess):
76 """ Sortie de la macro, on renvoie les parametres obtenus """
78 import Cata, aster, Macro
79 from Cata.cata import DEFI_LIST_REEL
81 from externe_mess import UTMESS
82 from Macro import reca_message
83 from Macro import reca_algo
84 from Macro import reca_interp
85 from Macro import reca_utilitaires
86 from Macro import reca_calcul_aster
87 from Macro.reca_controles import gestion
89 if CALCUL_ASTER.METHODE != 'EXTERNE':
90 txt = "Nombre d'evaluation de la fonction : " + str(CALCUL_ASTER.evaluation_fonction)
91 UTMESS('I','MACR_RECAL',txt)
94 LIST_NOM_PARA_ALPHA = [ para[0] for para in LIST_PARA ]
95 LIST_NOM_PARA_ALPHA.sort()
97 for i in LIST_NOM_PARA:
98 lival.append( val[ LIST_NOM_PARA_ALPHA.index(i) ] )
99 nomres = DEFI_LIST_REEL(VALE=lival)
104 # --------------------------------------------------------------------------------------------------
105 def macr_recal_externe( RESU_EXP, LIST_PARA, RESU_CALC, UNITE_ESCL=3, POIDS=None, LIST_DERIV=None,
106 ITER_MAXI=10, ITER_FONC_MAXI=100, RESI_GLOB_RELA=1.e-6, UNITE_RESU=91, PARA_DIFF_FINI=0.001,
107 GRAPHIQUE=None, SUIVI_ESCLAVE='NON', METHODE='EXTERNE', INFO=1, **args ):
109 Entree du mode EXTERNE (ici macr_recal_ops.py est traite comme un fichier Python et non pas par le superviseur Aster)
116 GRAPHIQUE0 = {'PILOTE': '', 'AFFICHAGE': 'TOUTE_ITERATION', 'UNITE': 90, 'FORMAT': 'XMGRACE'}
117 for k in GRAPHIQUE0.keys():
118 if not GRAPHIQUE.has_key(k): GRAPHIQUE[k] = GRAPHIQUE0[k]
120 if optparse_prefix_graph: args['prefix_graph'] = opts.prefix_graph
121 else: args['prefix_graph'] = os.getcwd() + os.sep + 'graph'
123 # Les parametres passes sur la ligne de commande surchargent les parametres de la commande MACR_RECAL
124 if optparse_INFO: INFO=opts.INFO
125 if optparse_follow_output:
126 if opts.follow_output == True: SUIVI_ESCLAVE='OUI'
127 else: SUIVI_ESCLAVE='NON'
129 if optparse_objective:
130 if type_fonctionnelle=='vector': args['FONCTIONNELLE']='VECTORIELLE'
131 else: args['FONCTIONNELLE']='SCALAIRE'
133 if optparse_gradient:
134 if opts.gradient=='normal': args['GRADIENT']='NORMAL'
135 elif opts.gradient=='adim': args['GRADIENT']='ADIMENSIONNE'
136 else: args['GRADIENT']='NON_CALCULE'
139 fonctionnelle, gradient = macr_recal(UNITE_ESCL, RESU_EXP, POIDS, LIST_PARA, LIST_DERIV, RESU_CALC,
140 ITER_MAXI, ITER_FONC_MAXI, RESI_GLOB_RELA, UNITE_RESU, PARA_DIFF_FINI,
141 GRAPHIQUE, SUIVI_ESCLAVE, METHODE, INFO, **args )
143 return fonctionnelle, gradient
145 # --------------------------------------------------------------------------------------------------
146 def force_list(obj, typref=list):
147 """Retourne 'obj' sous forme d'une liste de 'typref'.
149 if type(obj) not in (list, tuple):
150 assert type(obj) == typref, '%s != %s' % (type(obj), typref)
154 if type(elt) != typref:
158 # --------------------------------------------------------------------------------------------------
159 def macr_recal_ops(self,UNITE_ESCL, RESU_EXP, POIDS, LIST_PARA, LIST_DERIV, RESU_CALC,
160 ITER_MAXI, ITER_FONC_MAXI, RESI_GLOB_RELA,UNITE_RESU,PARA_DIFF_FINI,
161 GRAPHIQUE, SUIVI_ESCLAVE, METHODE, INFO, **args ):
162 """Macro commande realisant le recalage de modeles Aster"""
163 # Initialisation du compteur d'erreurs
168 from Cata import cata
169 from Cata.cata import DEFI_LIST_REEL, CREA_TABLE, TEST_TABLE
170 from Cata.cata import OPER, MACRO
172 from Macro import reca_message
173 from Macro import reca_algo
174 from Macro import reca_interp
175 from Macro import reca_utilitaires
176 from Macro import reca_calcul_aster
177 from Macro.reca_controles import gestion
178 from externe_mess import UTMESS
180 # Gestion des Exceptions
181 prev_onFatalError = aster.onFatalError()
182 aster.onFatalError('EXCEPTION')
184 # La macro compte pour 1 dans l'execution des commandes
188 self.DeclareOut('nomres',self.sd)
190 # Declaration de toutes les commandes Aster
191 for k,v in cata.__dict__.items() :
192 if isinstance(v, (OPER, MACRO)):
193 self.current_context[k]= v
194 self.current_context['_F']=cata.__dict__['_F']
196 macr_recal(UNITE_ESCL, force_list(RESU_EXP, Numeric.ArrayType), POIDS, force_list(LIST_PARA), LIST_DERIV, force_list(RESU_CALC),
197 ITER_MAXI, ITER_FONC_MAXI, RESI_GLOB_RELA,UNITE_RESU,PARA_DIFF_FINI,
198 GRAPHIQUE, SUIVI_ESCLAVE, METHODE, INFO, **args)
200 aster.onFatalError(prev_onFatalError)
204 # --------------------------------------------------------------------------------------------------
205 def macr_recal(UNITE_ESCL, RESU_EXP, POIDS, LIST_PARA, LIST_DERIV, RESU_CALC,
206 ITER_MAXI, ITER_FONC_MAXI, RESI_GLOB_RELA,UNITE_RESU,PARA_DIFF_FINI,
207 GRAPHIQUE, SUIVI_ESCLAVE, METHODE, INFO, **args ):
209 from externe_mess import UTMESS
211 if os.environ.has_key('ASTER_ROOT'):
212 sys.path.append(os.path.join(os.environ['ASTER_ROOT'], 'ASTK', 'ASTK_SERV', 'lib'))
214 try: sys.path.append(os.path.join(aster.repout, '..', 'ASTK', 'ASTK_SERV', 'lib'))
217 from as_profil import ASTER_PROFIL
219 UTMESS('F','MACR_RECAL',"Impossible d'importer le module as_profil ! Vérifier la variable d'environnement ASTER_ROOT ou mettez a jour ASTK.")
221 import Macro, Utilitai
222 from Macro import reca_message
223 from Macro import reca_algo
224 from Macro import reca_interp
225 from Macro import reca_utilitaires
226 from Macro import reca_calcul_aster
227 from Macro.reca_controles import gestion
228 if( METHODE != 'EXTERNE'):
229 from Utilitai.optimize import fmin, line_search, line_search_BFGS, approx_fprime, approx_fhess_p, fminBFGS, fminNCG
231 if( METHODE == 'EXTERNE'):
235 dGRAPHIQUE=GRAPHIQUE[0].cree_dict_valeurs(GRAPHIQUE[0].mc_liste)
236 if dGRAPHIQUE.has_key('FORMAT') and dGRAPHIQUE['FORMAT'] == 'GNUPLOT':
237 # On essaie d'importer Gnuplot -> PAS DE GRAPHIQUE
242 if INFO>=1: UTMESS('A','MACR_RECAL',"Le logiciel Gnuplot ou le module python Gnuplot.py n'est pas disponible. On desactive l'affichage des courbes par Gnuplot.")
245 #_____________________________________________
247 # VERIFICATION PREALABLE SUR MEM_ASTER
248 #_____________________________________________
250 # Lecture du fichier .export
251 list_export = glob('*.export')
252 if len(list_export) == 0:
253 UTMESS('F','MACR_RECAL',"Probleme : il n'y a pas de fichier .export dans le repertoire de travail!")
254 elif len(list_export) >1:
255 UTMESS('F','MACR_RECAL',"Probleme : il y a plus d'un fichier .export dans le repertoire de travail!")
257 prof = ASTER_PROFIL(list_export[0])
259 mem_aster = prof['mem_aster'][0]
260 memjeveux = prof.args.get('memjeveux')
262 if mem_aster in ('', '100'):
263 if INFO>=1: UTMESS('A','MACR_RECAL',"Attention : il faut specifier une valeur pour 'mem_aster' (menu Option de ASTK) " \
264 "pour limiter la memoire allouee au calcul maitre.")
267 UTMESS('F','MACR_RECAL',"Probleme : aucune valeur pour le parametre 'memjeveux'. Verifier le .export")
271 memjeveux_esclave = float(memjeveux)
273 memjeveux_esclave = float(memjeveux) / float(mem_aster) * 100. - float(memjeveux)
275 UTMESS('F','MACR_RECAL',"Probleme : verifier les valeurs des parametres 'mem_aster' et 'memjeveux'")
277 if INFO>=1: UTMESS('I','MACR_RECAL',"Information : les calculs esclaves utiliseront : %.1f Mega Mots." % memjeveux_esclave)
280 #_____________________________________________
283 #_____________________________________________
285 # Liste des parametres utilisant la sensibilité
286 if not LIST_DERIV: LIST_DERIV = {}
287 LIST_SENSI = LIST_DERIV.keys()
289 # Stocke l'ordre initial des parametres pour restituer dans le bon ordre les valeurs en sortie de la macro
290 LIST_NOM_PARA = [ para[0] for para in LIST_PARA ]
292 # On classe les parametres
296 # Defini si on utilise le mot-clé SENSIBILITE pour IMPR_TABLE ou non
297 if len(LIST_SENSI) >0: table_sensibilite = True
298 else: table_sensibilite = False
300 # Defini si on ajoute l'echo des calculs esclaves dans le mess du calcul maitre
301 follow_output = False
302 if SUIVI_ESCLAVE and SUIVI_ESCLAVE=='OUI': follow_output = True
303 # if( METHODE == 'EXTERNE') and mode_python: follow_output = opts.follow_output
305 # Pour les algorithmes d'optimize, on a des limitations
306 if METHODE in ['FMIN', 'FMINBFGS', 'FMINNCG']:
307 # On ne peut tracer qu'a la derniere iteration
309 if GRAPHIQUE['AFFICHAGE']=='TOUTE_ITERATION': UTMESS('I','MACR_RECAL',"Pour l'algorithme " + METHODE + " on ne peut tracer qu'a la derniere iteration")
310 # Les bornes ne sont pas gerees
311 UTMESS('I','MACR_RECAL',"Pour l'algorithme " + METHODE + " on ne tient pas compte des bornes sur les parametres.")
313 #_______________________________________________
315 # GESTION DE L'OPTION FACULTATIVE POUR LES POIDS
316 #_______________________________________________
318 POIDS=Numeric.ones(len(RESU_EXP))
321 #_____________________________________________
323 # GESTION DES ERREURS DE SYNTAXE
324 #_____________________________________________
325 texte_erreur, texte_alarme = gestion(UNITE_ESCL,LIST_PARA,RESU_CALC,RESU_EXP,POIDS,GRAPHIQUE,UNITE_RESU,METHODE)
326 if (texte_erreur != ""):
327 UTMESS('F', "MACR_RECAL", texte_erreur)
328 if (texte_alarme != ""):
329 UTMESS('A', "MACR_RECAL", texte_alarme)
332 #_____________________________________________
335 #_____________________________________________
337 if( METHODE != 'EXTERNE'):
339 restant,temps_iter=0.,0.
340 restant,temps_iter,err=reca_utilitaires.temps_CPU(restant,temps_iter)
342 para,val,borne_inf,borne_sup = reca_utilitaires.transforme_list_Num(LIST_PARA,RESU_EXP)
344 # Pour l'algorithme externe, les valeurs sont celles lues dans le fichier input.txt
345 if( METHODE == 'EXTERNE') and mode_python: val = val_externe
347 val_init = copy.copy(val)
349 # OBJET "PARAMETRES GLOBAUX"
350 PARAMETRES = reca_calcul_aster.PARAMETRES(
352 UNITE_RESU=UNITE_RESU,
354 fich_output='./REPE_OUT/output_esclave.txt',
356 follow_output=follow_output,
357 table_sensibilite=table_sensibilite,
358 memjeveux_esclave=memjeveux_esclave,
359 PARA_DIFF_FINI=PARA_DIFF_FINI,
361 ITER_FONC_MAXI=ITER_FONC_MAXI,
364 if( METHODE == 'EXTERNE'):
365 PARAMETRES.fich_output = './tmp_macr_recal/output_esclave.txt'
366 type_fonctionnelle = 'float'
367 if args.has_key('FONCTIONNELLE') and args['FONCTIONNELLE'] == 'VECTORIELLE':
368 PARAMETRES.vector_output = True
369 type_fonctionnelle = 'vector'
371 # On utilise le critere en erreur plutot que normalise
372 elif METHODE in ['FMIN', 'FMINBFGS', 'FMINNCG']: PARAMETRES.error_output = True
375 CALCUL_ASTER = reca_calcul_aster.CALCUL_ASTER(PARAMETRES, UL=UNITE_ESCL, para=para, reponses=RESU_CALC, LIST_SENSI=LIST_SENSI, LIST_DERIV=LIST_DERIV)
377 # Instances des classes pour le calcul de l'erreur et le dimensionnemnt/adim
378 Simul = reca_interp.Sim_exp(RESU_EXP,POIDS)
379 Dim = reca_algo.Dimension(copy.copy(val_init),para)
381 CALCUL_ASTER.Simul = Simul
382 CALCUL_ASTER.Dim = Dim
383 CALCUL_ASTER.reca_algo = reca_algo
386 CALCUL_ASTER.UNITE_GRAPHIQUE = GRAPHIQUE['UNITE']
389 # Instance de la classe gérant l'affichage des resultats du calcul de l'optimisation
390 Mess = reca_message.Message(para,RESU_EXP,copy.copy(val_init),UNITE_RESU)
392 if( METHODE != 'EXTERNE'):
394 txt = "Lancement de l'optimisation avec la methode : " + METHODE
395 if INFO>=1: UTMESS('I','MACR_RECAL',txt)
400 #-------------------------------------------------------------------------------
401 # Methode EXTERNE (en fait juste une evaluation de la fonction puis on sort)
403 if( METHODE == 'EXTERNE'):
405 # On sauvegarde le fichier esclave si celui-ci est fort.UL (sinon il sera ecrase)
406 fic_esclave = './fort.'+str(UNITE_ESCL)
407 txt_old_esclave = None
408 if os.path.isfile(fic_esclave):
409 f = open(fic_esclave,'r')
410 txt_old_esclave = f.read()
413 # try: os.remove('./fort.'+str(UNITE_ESCL))
417 txt = '\nPARAMETRES : ' + str([ para[0] for para in LIST_PARA ]) + ' ' + str(val)
420 # Execution de l'esclave
421 if args.has_key('GRADIENT') and args['GRADIENT']!='NON_CALCULE':
424 fonctionnelle, residu, A_nodim, A = CALCUL_ASTER.calcul_FG(val)
426 # Ecriture du fichier grad.txt contenant les derivees
427 if args['GRADIENT'] == 'ADIMENSIONNE': gradient = A
428 else: gradient = A_nodim
430 # Ecriture du fichier contenant le gradient
431 if not mode_python: Ecriture_Derivees(output_file='./fort.1901', derivees=gradient)
435 fonctionnelle = CALCUL_ASTER.calcul_F(val)
438 # Ecriture du fichier contenant la fonctionnelle
439 if not mode_python: Ecriture_Fonctionnelle(output_file='./fort.1900', type_fonctionnelle=type_fonctionnelle, fonctionnelle=fonctionnelle)
442 if type(fonctionnelle) == float: txt = '---> fonctionnelle : ' + str(fonctionnelle)
443 else: txt = '---> norme fonctionnelle : ' + str( math.sqrt( (Numeric.sum( [x**2 for x in fonctionnelle] )) ) )
446 # Affichage de la valeur de la fonctionnelle
447 if mode_python and opts.INFO==-1: print txt
449 # Affichage de la norme du gradient (AA: a remplacer par une formule de norme L2 !!)
452 for l in range(len(gradient[:,0])):
453 for c in range(len(gradient[0,:])):
454 norme += ( gradient[l,c] * gradient[l,c] )
455 norme = math.sqrt(norme)
456 txt = '---> norme du gradient : ' + str(norme)
458 if mode_python and opts.INFO==-1: print txt
461 try: os.remove('./fort.'+str(UNITE_ESCL))
464 # On remet l'ancien fichier esclave si c'etait fort.UL
466 f = open(fic_esclave,'w')
467 f.write(txt_old_esclave)
474 # On va ensuite jusqu'au bout (pour l'impression des graphes)
478 #-------------------------------------------------------------------------------
479 # Algorithme FMIN (pas d'adimensionnement car n'utilise pas de gradient)
481 elif( METHODE == 'FMIN'):
482 val, fval, warnflag = fmin(CALCUL_ASTER.calcul_F, val, maxiter=ITER_MAXI, maxfun=ITER_FONC_MAXI, fulloutput=1)
484 iter_fonc = CALCUL_ASTER.evaluation_fonction
486 Mess.ecrire("\nDerniere iteration : ")
487 Mess.affiche_etat_final_convergence(iter,ITER_MAXI,iter_fonc,ITER_FONC_MAXI, RESI_GLOB_RELA,residu=0,Act=[])
488 Mess.affiche_fonctionnelle(fval)
489 Mess.affiche_valeurs(val)
490 if warnflag==1: Mess.ecrire("Attention : le nombre maximum d'evaluations de la fonction (ITER_FONC_MAXI) a ete atteint")
491 if warnflag==2: Mess.ecrire("Attention : le nombre maximum d'iteration de l'algorithme (ITER_MAXI) a ete atteint")
493 nomres = Sortie(LIST_NOM_PARA, LIST_PARA, val, CALCUL_ASTER, Mess)
497 #-------------------------------------------------------------------------------
498 # Pour tous les autres methodes, on adimensionne
500 # Calcul d'initialisation de F, ici L_deriv_sensible ne contient que les termes calculés par la sensibilité, les autres termes sont nuls
501 L_init, L_deriv_sensible = CALCUL_ASTER.calcul_Aster(val, INFO)
503 L_J_init, erreur = Simul.multi_interpole(L_init, RESU_CALC)
504 J_init = Simul.norme_J(copy.copy(L_J_init),copy.copy(L_J_init),UNITE_RESU)
507 A = Simul.sensibilite(CALCUL_ASTER, L_init, L_deriv_sensible, val, PARA_DIFF_FINI)
508 A = Dim.adim_sensi(A)
510 l = reca_algo.lambda_init(Numeric.matrixmultiply(Numeric.transpose(A),A))
512 gradient_init =reca_algo.calcul_gradient(A,erreur) #utile pour le test de convergence, on prend les valeurs dimensionnées
513 residu = reca_algo.test_convergence(gradient_init,erreur,A,Numeric.zeros(len(gradient_init),Numeric.Float))
515 Mess.affiche_result_iter(iter,J,val,residu,Numeric.array([]))
516 # On teste un manque de temps CPU
517 restant,temps_iter,err=reca_utilitaires.temps_CPU(restant,temps_iter)
522 CALCUL_ASTER.L_init = L_init
523 CALCUL_ASTER.L_J_init = L_J_init
524 CALCUL_ASTER.J_init = J_init
525 CALCUL_ASTER.A_init = A
526 CALCUL_ASTER.gradient_init = gradient_init
527 CALCUL_ASTER.residu_init = residu
530 #-------------------------------------------------------------------------------
531 # Methode FMINBFGS et FMINNCG
533 if METHODE in ['FMINBFGS', 'FMINNCG']:
535 fprime=CALCUL_ASTER.calcul_G
538 if args.has_key('GRADIENT') and args['GRADIENT'] == 'NON_CALCULE': fprime=None
540 if fprime: UTMESS('I','MACR_RECAL',"Les derivees sont calculees par Aster")
541 else: UTMESS('I','MACR_RECAL',"Les derivees sont calculees par l'algorithme")
543 # Lancement de l'optimisation
544 if METHODE == 'FMINBFGS':
545 val, fval, func_calls, grad_calls, warnflag = fminBFGS(CALCUL_ASTER.calcul_F, val, fprime=fprime, maxiter=ITER_MAXI, avegtol=RESI_GLOB_RELA, fulloutput=1)
547 elif METHODE == 'FMINNCG':
548 val, fval, func_calls, grad_calls, hcalls, warnflag = fminNCG(CALCUL_ASTER.calcul_F, val, fprime=fprime, fhess_p=None, fhess=None, maxiter=ITER_MAXI, avextol=RESI_GLOB_RELA, fulloutput=1)
550 # Affichage des messages de sortie
551 iter_fonc = CALCUL_ASTER.evaluation_fonction
552 Mess.ecrire("\nDerniere iteration : ")
553 Mess.affiche_etat_final_convergence(iter,ITER_MAXI,iter_fonc,ITER_FONC_MAXI, RESI_GLOB_RELA,residu=0,Act=[])
554 Mess.affiche_fonctionnelle(fval)
555 Mess.affiche_valeurs(val)
556 # if warnflag==1: Mess.ecrire("\nAttention : le nombre maximum d'evaluations de la fonction (ITER_FONC_MAXI) a ete atteint")
557 # if warnflag==2: Mess.ecrire("\nAttention : le nombre maximum d'iteration de la methode (ITER_MAXI) a ete atteint")
559 # Permet d'avoir un diagnostic NOOK pour le job
560 if warnflag: iter=ITER_MAXI
568 #-------------------------------------------------------------------------------
569 # Methode Levenberg-Marquardt
572 #_____________________________________________
574 # BOUCLE PRINCIPALE DE L'ALGORITHME
575 #_____________________________________________
576 epsilon = 10.*RESI_GLOB_RELA
577 while((residu > RESI_GLOB_RELA) & (iter<ITER_MAXI)):
579 new_val, s, l, Act = reca_algo.Levenberg_bornes(val,Dim,val_init,borne_inf,borne_sup,A,erreur,l,UNITE_RESU)
581 # Calcul de F, ici L_deriv_sensible ne contient que les termes calculés par la sensibilité, les autres termes sont nuls
582 L_F, L_deriv_sensible = CALCUL_ASTER.calcul_Aster(new_val, INFO)
584 new_L_J,new_erreur = Simul.multi_interpole(L_F, RESU_CALC)
585 new_J = Simul.norme_J(L_J_init,new_L_J,UNITE_RESU)
586 l = reca_algo.actualise_lambda(l,Dim.adim(val),Dim.adim(new_val),A,erreur,new_J,J)
588 val = copy.copy(new_val)
589 erreur = copy.copy(new_erreur)
592 # Calcul de la matrice des sensibilites
593 A = Simul.sensibilite(CALCUL_ASTER, L_F, L_deriv_sensible, val, PARA_DIFF_FINI)
594 A = Dim.adim_sensi(A)
597 residu = reca_algo.test_convergence(gradient_init,erreur,A,s)
599 # Affichage iteration
600 Mess.affiche_result_iter(iter,J,val,residu,Act)
601 txt = "Informations de convergence :"
602 txt += '\n=======================================================\n'
603 txt += "Fin de l'iteration "+str(iter)+" :\n"
604 txt += '\n=> Fonctionnelle = '+str(J)
605 txt += '\n=> Residu = '+str(residu)
606 txt += '\n=======================================================\n'
607 if INFO>=1: UTMESS('I','MACR_RECAL',txt)
610 if GRAPHIQUE['AFFICHAGE']=='TOUTE_ITERATION':
611 GRAPHE_UL_OUT=GRAPHIQUE['UNITE']
612 pilote=GRAPHIQUE['PILOTE']
613 reca_utilitaires.graphique(GRAPHIQUE['FORMAT'],L_F,RESU_EXP,RESU_CALC,iter,GRAPHE_UL_OUT,pilote)
615 # On teste un manque de temps CPU
616 restant,temps_iter,err=reca_utilitaires.temps_CPU(restant,temps_iter)
622 #_____________________________________________
625 # CONVERGENCE OU ECHEC
626 #_____________________________________________
627 iter_fonc = CALCUL_ASTER.evaluation_fonction
628 Mess.affiche_etat_final_convergence(iter,ITER_MAXI,iter_fonc,ITER_FONC_MAXI, RESI_GLOB_RELA,residu,Act)
629 reca_algo.calcul_etat_final(para,A,iter,ITER_MAXI,RESI_GLOB_RELA,residu,Mess)
632 #-------------------------------------------------------------------------------
635 #_____________________________________________
637 # FIN DES ITERATIONS POUR TOUS LES ALGOS
638 #_____________________________________________
643 # Pour les algorithmes d'optimize.py, on ne peut tracer qu'a la derniere iteration
644 if (GRAPHIQUE['AFFICHAGE']=='ITERATION_FINALE') or (METHODE in ['FMIN', 'FMINBFGS', 'FMINNCG']):
646 if (METHODE=='EXTERNE' and GRAPHIQUE['AFFICHAGE']=='TOUTE_ITERATION'):
648 if not args.has_key('prefix_graph'): fichier='graph'
649 else: fichier = args['prefix_graph']
651 if INFO>=1: UTMESS('I','MACR_RECAL',"Trace des graphiques")
652 GRAPHE_UL_OUT=GRAPHIQUE['UNITE']
653 pilote=GRAPHIQUE['PILOTE']
654 reca_utilitaires.graphique(GRAPHIQUE['FORMAT'],L_F,RESU_EXP,RESU_CALC,iter,GRAPHE_UL_OUT,pilote,fichier)
656 if( METHODE == 'EXTERNE'):
657 # if mode_python: return fonctionnelle, gradient
658 return fonctionnelle, gradient
660 # Si pas de convergence alors diagnostic NOOK_TEST_RESU
661 if residu > RESI_GLOB_RELA:
662 from Cata.cata import CREA_TABLE, TEST_TABLE
664 _tmp.append( { 'PARA': 'ITER_MAXI', 'LISTE_R': 0.0, } )
665 motscle= {'LISTE': _tmp }
667 TBL=CREA_TABLE(**motscle);
669 TEST_TABLE(TABLE=TBL,
671 NOM_PARA='ITER_MAXI',
674 #_____________________________________________
676 # CREATIONS DE LA LISTE DE REELS CONTENANT
677 # LES VALEURS DES PARAMETRES A CONVERGENCE
678 #_____________________________________________
681 nomres = Sortie(LIST_NOM_PARA, LIST_PARA, val, CALCUL_ASTER, Mess)
696 #-------------------------------------------------------------------------------
697 if __name__ == '__main__':
701 from optparse import OptionParser, OptionGroup
702 from externe_mess import UTMESS
704 p = OptionParser(usage='usage: %s fichier_export [options]' % sys.argv[0])
705 p.add_option('-i', '--input', action='store', dest='input', type='string', default='input.txt', help='fichier contenant les parametres')
706 p.add_option('-o', '--output', action='store', dest='output', type='string', default='output.txt', help='fichier contenant la fonctionnelle')
707 p.add_option('-g', '--output_grad', action='store', dest='output_grad', type='string', default='grad.txt', help='fichier contenant le gradient')
708 p.add_option('-p', '--prefix_graph', action='store', dest='prefix_graph', type='string', default='graph', help='prefixe des fichiers contenant les courbes')
709 p.add_option('-v', '--info', action='store', dest='INFO', type='int', help='niveau de message (-1, 0, 1, 2)')
710 p.add_option('-f', '--follow', action='store', dest='follow_output', type='string', help="affiche ou non l'output du fichier Aster (True/False)")
711 p.add_option('-F', '--objective', action='store', dest='objective', type='string', help="type de la fonctionnelle (float/vector)")
712 p.add_option('-G', '--gradient', action='store', dest='gradient' , type='string', default='no', help="calcul du gradient par Aster (no/normal/adim)")
713 p.add_option('-d', '--display', action='store', dest='display' , type='string', help="renvoi du DISPLAY (pour que la creation des courbes soit moins genante)")
715 # p.add_option('-n', '--name', action='store', dest='name', type='string', default='optim', help="prefixe du fichier de bilan")
717 opts, args = p.parse_args()
719 # renvoi du DISPLAY (pour que la creation des courbes soit moins genante)
720 if opts.display: os.environ['DISPLAY'] = opts.display
724 optparse_input = optparse_output = optparse_output_grad = optparse_prefix_graph = optparse_INFO = optparse_follow_output = optparse_objective = optparse_gradient = optparse_name = None
726 if opts.INFO==None: opts.INFO=0
728 if opts.input: optparse_input = True
729 if opts.output: optparse_output = True
730 if opts.output_grad: optparse_output_grad = True
731 if opts.prefix_graph: optparse_prefix_graph = True
732 if opts.INFO in [-1, 0, 1, 2]: optparse_INFO = True
733 if opts.follow_output in ['True', 'False']: optparse_follow_output = True
734 if opts.objective in ['float', 'vector']: optparse_objective = True
735 if opts.gradient in ['no', 'normal', 'adim']: optparse_gradient = True
736 # if opts.name: optparse_name = True
738 if opts.follow_output=='True': opts.follow_output=True
739 if opts.follow_output=='False': opts.follow_output=False
744 fichier_export = args[0]
745 if not os.path.isfile(fichier_export): fichier_export = None
748 input_file = opts.input
749 output_file = opts.output
750 output_grad = opts.output_grad
751 type_fonctionnelle = opts.objective
754 if os.environ.has_key('ASTER_ROOT'):
755 sys.path.append(os.path.join(os.environ['ASTER_ROOT'], 'ASTK', 'ASTK_SERV', 'lib'))
757 from as_profil import ASTER_PROFIL
759 UTMESS('F','MACR_RECAL',"Impossible de determiner l'emplacement d'Aster ! Fixer le chemin avec la variable d'environnement ASTER_ROOT.")
761 # Efface les fichiers resultats
762 try: os.remove(output)
764 try: os.remove(output_grad)
768 # Si le fichier export n'est pas en argument on prend l'export qui est dans le rep courant
769 if not fichier_export:
770 # Lecture du fichier .export
771 list_export = glob('*.export')
772 if len(list_export) != 1:
773 UTMESS('F','MACR_RECAL',"Impossible de determiner le fichier .export a utiliser. Specifier le sur la ligne de commande.")
775 fichier_export = list_export[0]
776 prof = ASTER_PROFIL(fichier_export)
778 # Execution du fichier .comm
781 for lab in ('data', 'resu'):
782 l_fr = getattr(prof, lab)
787 if not dico['isrep']:
788 # Ancien .comm a executer
789 if dico['type'] == 'comm' and dico['ul'] == '1':
790 nom_comm = dico['path']
793 for lab in ('param',):
794 l_fr = getattr(prof, lab)
796 # print l_fr['version']
797 try: os.environ['ASTER_VERSION'] = l_fr['version'][0]
802 UTMESS('F','MACR_RECAL',"Probleme : le fichier .comm n'est pas defini dans le .export.")
803 if not os.path.isfile(nom_comm):
804 UTMESS('F','MACR_RECAL',"Probleme : le fichier .comm suivant n'est pas defini : " + nom_comm)
808 # -------------------------------------------------------------------
809 # Lecture des valeurs d'entree
810 if INFO==2: UTMESS('I',NOMPRO,"Lecture du fichier : " + input_file)
812 f = open(input_file, 'r')
815 txt = txt.replace(',', ' ')
816 val_externe = [ float(x) for x in txt.strip().split() ]
818 UTMESS('F',NOMPRO,"Probleme : impossible de lire le fichier d'entree :\n" + input_file)
819 if INFO>=2: UTMESS('I',NOMPRO,"Parametres d'entree : " + str(val_externe))
820 if optparse_INFO and opts.INFO == -1: print '\n'+ str(val_externe)
823 # -------------------------------------------------------------------
824 # Efface les fichiers d'entree et de sortie
825 try: os.remove(input_file)
827 try: os.remove(output_file)
829 try: os.remove(output_grad)
835 # --------------------------------------------------------------------------------------------------------
836 # --------------------------------------------------------------------------------------------------------
837 # --------------------------------------------------------------------------------------------------------
838 # Ci-dessous on extrait le fichier de commande jusqu'a la commande MACR_RECAL exclue (fichiernew)
839 # Puis la commande MACR_RECAL (commandenew)
840 # Ensuite on annule l'effet des commandes Aster et on evalue en Python les deux chaines de textes
842 # Lecture du fichier .comm
847 # Extraction des deux parties dans le fichier de commande
854 for ligne in fichier.split('\n'):
855 if ligne.find( txt1 )!=-1 and ligne.find( txt2 )!=-1 and ligne.strip()[0]!='#':
857 index_deb1 = fichier.index(ligne)
858 fichiernew=fichier[:index_deb1]
859 # if debug: print 80*'*' + 2*'\n'+fichiernew+80*'*' + 2*'\n'
860 if fichiernew and ligne.find( txt2 )!=-1: nb_par+=1
861 if fichiernew and ligne.find( txt3 )!=-1: nb_par-=1
862 if fichiernew and nb_par==0:
863 index_fin1 = fichier.index(ligne)+len(ligne)
864 commandenew=fichier[index_deb1:index_fin1]
866 # Remplace le nom de concept a gauche du signe egal
867 index_deb2 = commandenew.index(txt1)
868 commandenew='fonctionnelle, gradient='+commandenew[index_deb2:]+ '\n'
870 if debug: print 80*'*' + 2*'\n'+commandenew+80*'*' + 2*'\n'
872 if not fichiernew or not commandenew:
873 txt = "Probleme : Le fichier de commande :\n" + nom_comm + "\n ne semble pas comporter la commande MACR_RECAL"
874 UTMESS('F',NOMPRO,txt)
877 # -------------------------------------------------------------------
878 # Import du module Utilitai
879 sys.path.append(os.path.join(os.getcwd(), 'Python'))
880 sys.path.append(os.path.join(os.environ['ASTER_ROOT'], os.environ['ASTER_VERSION'], 'bibpyt'))
883 from Utilitai.System import ExecCommand
885 UTMESS('F','MACR_RECAL',"Probleme : impossible d'importer le module Utilitai! Prevenir la maintenance.")
888 # -------------------------------------------------------------------
889 # On annule les commandes Aster du fichier maitre .comm
890 def DEBUT(*args, **kwargs): pass
891 def FIN(*args, **kwargs): pass
892 def MACR_RECAL(*args, **kwargs): pass
893 def _F(*args, **kwargs): return kwargs
894 def DEFI_LIST_REEL(*args, **kwargs): pass
895 def DEFI_FONCTION(*args, **kwargs): pass
896 def TEST_FONCTION(*args, **kwargs): pass
897 def DEFI_CONSTANTE(*args, **kwargs): pass
900 # -------------------------------------------------------------------
901 # Evaluation du fichier de commande Aster jusqu'a MACR_RECAL
906 txt = "Le mode EXTERNE tourne en mode degrade. Lire la documentation."
907 UTMESS('A',NOMPRO,txt)
910 exec(commandenew.replace(txt1, 'macr_recal_externe'))
912 # exec(commandenew.replace(txt1, 'macr_recal_externe'))
913 # except Exception, err:
915 # txt = "Erreur lors de l'execution de la commande MACR_RECAL"
916 # UTMESS('F',NOMPRO,txt)
918 Ecriture_Fonctionnelle(output_file, type_fonctionnelle, fonctionnelle)
919 Ecriture_Derivees(output_grad, gradient)
923 # --------------------------------------------------------------------------------------------------------
924 # --------------------------------------------------------------------------------------------------------
925 # --------------------------------------------------------------------------------------------------------
926 # Si l'evaluation du fichier de commande Aster jusqu'a MACR_RECAL a echoue, on execute Aster "normalement"
930 new_fichier_comm = os.getcwd() + os.sep + 'tmp_comm'
931 new_fichier_export = os.getcwd() + os.sep + fichier_export.split('/')[-1] + '_new'
933 # Lecture du fichier .comm
938 # -------------------------------------------------------------------
939 # Modification du fichier .comm (changement des valeurs, ecriture du resultat dans un fichier)
940 if INFO==2: UTMESS('I',NOMPRO,"Lecture du fichier : " + nom_comm)
941 f = open(nom_comm, 'r')
942 ok1 = ok3 = ok4 = False
945 if ligne.find('MACR_RECAL')!=-1 and ligne.strip()[0]!='#': # On determine le nom du concept sortant de MACR_RECAL
947 _RESU_ = ligne.split('=')[0].strip()
949 elif ligne.strip()[:len(_PARAM_)] == _PARAM_: # On change les parametres : la variables _PARAM_
951 txt += _PARAM_ + " = " + str(val_externe) + '\n'
952 elif ligne.find('METHODE')!=-1 and ligne.strip()[0]!='#': # On verifie bien que la methode externe est choisi
953 if ligne.find("EXTERNE")!=-1:
959 if not ok1: UTMESS('F',NOMPRO,"Probleme : il faut mettre les parametres sous la forme d'une ligne python " + str(_PARAM_) + " = [param1, param2, ...]")
960 if not ok3: UTMESS('F',NOMPRO,"Probleme : la commande MACR_RECAL n'a pas ete trouvee dans le .comm")
961 if not ok4: UTMESS('F',NOMPRO,"Probleme : dans la commande MACR_RECAL, il faut choisir METHODE='EXTERNE'")
963 txt = txt.replace('_RESU_', _RESU_)
965 # Ecriture du nouveau fichier comm temporaire
966 if INFO==2: UTMESS('I',NOMPRO,"Ecriture du fichier : " + new_fichier_comm)
967 f = open(new_fichier_comm, 'w')
971 # On remplace dans l'export par le nouveau .comm
972 prof = ASTER_PROFIL(fichier_export)
973 for lab in ('data', 'resu'):
974 l_fr = getattr(prof, lab)
978 if not dico['isrep']:
979 # On remplace par le nouveau .comm
980 if dico['type'] == 'comm' and dico['ul'] == '1':
981 dico['path'] = new_fichier_comm
984 # dico['path'] = os.path.join(tmp_macr_recal, os.path.basename(dico['path']))
986 # On ajoute au profil le fichier output.txt (unite logique 1900)
987 try: os.remove('./fort.1900')
989 if not output_file.find(os.sep)!=-1: output_file = os.getcwd() + os.sep + output_file
990 prof.Set('R', {'type':'libr', 'isrep':False, 'path': output_file, 'ul':1900, 'compr': False} )
992 # On ajoute au profil le fichier grad.txt (unite logique 1901)
993 if optparse_gradient and opts.gradient!='no':
994 try: os.remove('./fort.1901')
996 output_grad = opts.gradient
997 if not output_grad.find(os.sep)!=-1: output_grad = os.getcwd() + os.sep + output_grad
998 prof.Set('R', {'type':'libr', 'isrep':False, 'path': output_grad, 'ul':1901, 'compr': False} )
1001 # Ecriture du nouveau fichier export
1003 if INFO==2: UTMESS('I',NOMPRO,"Ecriture du fichier : " + new_fichier_export)
1004 prof.WriteExportTo(new_fichier_export)
1006 UTMESS('F',NOMPRO,"Probleme : Impossible d'ecrire le fichier export : " + new_fichier_export)
1007 if debug: prof.WriteExportTo('/tmp/exp')
1010 # chemin vers as_run
1011 if os.environ.has_key('ASTER_ROOT'):
1012 as_run = os.path.join(os.environ['ASTER_ROOT'], 'ASTK', 'ASTK_SERV', 'bin', 'as_run')
1015 if INFO>=1: UTMESS('A', nompro, "Variable d'environnement ASTER_ROOT absente, " \
1016 "on essaiera avec 'as_run' dans le $PATH.")
1019 # Import du module Utilitai
1020 sys.path.append(os.path.join(os.environ['ASTER_ROOT'], os.environ['ASTER_VERSION'], 'bibpyt'))
1023 from Utilitai.System import ExecCommand
1025 UTMESS('F','MACR_RECAL',"Probleme : impossible d'importer le module Utilitai! Prevenir la maintenance.")
1028 # Lancement d'Aster avec le deuxieme export
1029 cmd = '%s %s' % (as_run, new_fichier_export)
1030 if INFO>=2: UTMESS('I','MACR_RECAL',"Lancement de la commande : " + cmd)
1031 iret, txt_output = ExecCommand(cmd, follow_output=opts.follow_output,verbose=opts.follow_output)
1032 if INFO>=2: UTMESS('I','MACR_RECAL',"Fin du lancement de la commande : " + cmd)
1034 try: os.remove(new_fichier_comm)
1036 try: os.remove(new_fichier_export)