1 #@ MODIF reca_interp Macro DATE 31/10/2006 AUTEUR ASSIRE A.ASSIRE
2 # -*- coding: iso-8859-1 -*-
3 # RESPONSABLE ASSIRE A.ASSIRE
4 # CONFIGURATION MANAGEMENT OF EDF VERSION
5 # ======================================================================
6 # COPYRIGHT (C) 1991 - 2002 EDF R&D WWW.CODE-ASTER.ORG
7 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
8 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
9 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
10 # (AT YOUR OPTION) ANY LATER VERSION.
12 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
13 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
14 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
15 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.
17 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
18 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
19 # 1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
20 # ======================================================================
22 import os, sys, pprint
29 from Utilitai.Utmess import UTMESS
31 def UTMESS(code,sprg,texte):
32 fmt='\n <%s> <%s> %s\n\n'
33 print fmt % (code,sprg,texte)
34 if code=='F': sys.exit()
37 #===========================================================================================
40 # INTERPOLATION, CALCUL DE SENSIBILITE, ETC....
42 #--------------------------------------
45 def __init__ (self,result_exp,poids) :
46 self.resu_exp = result_exp
49 # ------------------------------------------------------------------------------
51 def InterpolationLineaire (self, x0, points) :
53 Interpolation Lineaire de x0 sur la fonction discrétisée yi=points(xi) i=1,..,n
55 # x0 = Une abscisse (1 colonne, 1 ligne)
56 # points = Tableau de n points (2 colonnes, n lignes)
57 # on suppose qu'il existe au moins 2 points,
58 # et que les points sont classés selon les abscisses croissantes
61 if ( x0 < points[0][0] ) or ( x0 > points[n-1][0] ) :
62 txt = "Problème lors de l'interpolation du calcul dérivé sur les données expérimentale!"
63 txt += "\nValeur à interpoler : " + str(x0)
64 txt += "\nDomaine couvert par l'experience : [" + str(points[0][0]) + ":" + str(points[n-1][0]) + "]"
65 UTMESS('F','MACR_RECAL', txt)
68 while x0 > points[i][0]:
71 y0 = (x0-points[i-1][0]) * (points[i][1]-points[i-1][1]) / (points[i][0]-points[i-1][0]) + points[i-1][1]
78 # ------------------------------------------------------------------------------
80 def DistVertAdimPointLigneBrisee (self, M, points) :
82 Distance verticale d'un point M à une ligne brisée composée de n points
84 # M = Point (2 colonnes, 1 ligne)
85 # points = Tableau de n points (2 colonnes, n lignes)
86 # on suppose qu'il existe au moins 2 points,
87 # et que les points sont classés selon les abscisses croissantes
89 if ( M[0] < points[0][0] ) or ( M[0] > points[n-1][0] ):
92 while M[0] > points[i][0]:
94 y_proj_vert = (M[0]-points[i-1][0]) * (points[i][1]-points[i-1][1]) / (points[i][0]-points[i-1][0]) + points[i-1][1]
95 d = (M[1] - y_proj_vert)
96 # Attention: la distance n'est pas normalisée
97 # Attention: problème si points[0][0] = points[1][0] = M[0]
98 # Attention: problème si M[1] = 0
102 # ------------------------------------------------------------------------------
104 def _Interpole(self, F_calc,experience,poids) : #ici on passe en argument "une" experience
106 La Fonction Interpole interpole une et une seule F_calc sur F_exp et renvoie l'erreur seulement
111 n_exp = len(experience) # nombre de points sur la courbe expérimentale num.i
112 stockage = Numeric.ones(n_exp, Numeric.Float) # matrice de stockage des erreurs en chaque point
113 for j in xrange(n_exp) :
114 d = self.DistVertAdimPointLigneBrisee(experience[j], resu_num)
116 stockage[n] = d/experience[j][1]
117 except ZeroDivisionError:
120 n = n + 1 # on totalise le nombre de points valables
121 err = Numeric.ones(n, Numeric.Float)
124 err[i] = poids*stockage[i]
128 # ------------------------------------------------------------------------------
130 def multi_interpole(self, L_F, reponses):
132 Cette fonction appelle la fonction interpole et retourne les sous-fonctionnelles J et l'erreur.
133 On interpole toutes les reponses une à une en appelant la methode interpole.
137 for i in range(len(reponses)):
138 err = self._Interpole(L_F[i],self.resu_exp[i],self.poids[i])
141 # print "L_erreur=", L_erreur
143 # On transforme L_erreur en tab num
146 for i in range(len(L_erreur)):
147 dim.append(len(L_erreur[i]))
148 dim_totale = Numeric.sum(dim)
149 L_J = self.calcul_J(L_erreur)
151 erreur = Numeric.zeros((dim_totale),Numeric.Float)
152 for n in range(len(L_erreur)):
153 for i in range(dim[n]):
154 erreur[i+a] = L_erreur[n][i]
156 del(L_erreur) #on vide la liste puisqu'on n'en a plus besoin
160 # ------------------------------------------------------------------------------
162 def multi_interpole_sensib(self, L_F, reponses):
164 Cette fonction retourne seulement l'erreur, elle est appelée dans la methode sensibilité.
165 On interpole toutes les reponses une à une en appelant la methode interpole.
169 for i in range(len(reponses)):
170 err = self._Interpole(L_F[i], self.resu_exp[i], self.poids[i])
172 # On transforme L_erreur en tab num
176 # ------------------------------------------------------------------------------
178 def calcul_J(self,L_erreur):
180 for i in range(len(L_erreur)):
182 for j in range(len(L_erreur[i])):
183 total = total + L_erreur[i][j]**2
188 # ------------------------------------------------------------------------------
190 def norme_J(self,L_J_init,L_J,unite_resu=None):
192 Cette fonction calcul une valeur normée de J
194 for i in range(len(L_J)):
196 L_J[i] = L_J[i]/L_J_init[i]
197 except ZeroDivisionError:
198 message= 'Problème de division par zéro dans la normalisation de la fonctionnelle.\n'
199 message=message+'Une des valeurs de la fonctionnelle initiale est nulle ou inférieure à la précision machine : %.2f \n'%L_J_init
201 fic=open(os.getcwd()+'/fort.'+str(unite_resu),'a')
204 UTMESS('F', "MACR_RECAL", message)
212 # ------------------------------------------------------------------------------
214 # def sensibilite(self,objet,UL,F,L_deriv_sensible,val,para,reponses,pas,unite_resu,LIST_SENSI=[],LIST_DERIV=[],INFO=1):
216 def sensibilite(self, CALCUL_ASTER, F, L_deriv_sensible, val, pas):
218 # CALCUL_ASTER est l'objet regroupant le calcul de F et des derivées, ainsi que les options
220 para = CALCUL_ASTER.para
221 reponses = CALCUL_ASTER.reponses
222 unite_resu = CALCUL_ASTER.UNITE_RESU
223 LIST_SENSI = CALCUL_ASTER.LIST_SENSI
224 LIST_DERIV = CALCUL_ASTER.LIST_DERIV
225 INFO = CALCUL_ASTER.INFO
229 # Erreur de l'interpolation de F_interp : valeur de F interpolée sur les valeurs experimentales
230 F_interp = self.multi_interpole_sensib(F, reponses) #F_interp est une liste contenant des tab num des reponses interpolés
232 # Creation de la liste des matrices de sensibilités
234 for i in range(len(reponses)):
235 L_A.append(Numeric.zeros((len(self.resu_exp[i]),len(val)),Numeric.Float) )
237 for k in range(len(val)): # pour une colone de A (dim = nb parametres)
239 # On utilise les differences finies pour calculer la sensibilité
240 # --------------------------------------------------------------
241 # Dans ce cas, un premier calcul_Aster pour val[k] a deja ete effectué, on effectue un autre calcul_Aster pour val[k]+h
243 if para[k] not in LIST_SENSI:
246 if INFO>=2: UTMESS('I','MACR_RECAL','On utilise les differences finies pour calculer la sensibilite de : %s ' % para[k])
248 fic=open(os.getcwd()+'/fort.'+str(unite_resu),'a')
249 fic.write('\nCalcul de la sensibilité par differences finies pour : '+para[k])
256 # Calcul_Aster pour la valeur perturbée
257 F_perturbe, L_deriv = CALCUL_ASTER.calcul_Aster(val)
259 # Erreur de l'interpolation de F_perturb : valeur de F (perturbée) interpolée sur les valeurs experimentales
260 F_perturbe_interp =self.multi_interpole_sensib(F_perturbe, reponses)
262 # On replace les parametres a leurs valeurs initiales
265 # Calcul de L_A (matrice sensibilité des erreurs sur F interpolée)
266 for j in range(len(reponses)):
267 for i in range(len(self.resu_exp[j])):
269 L_A[j][i,k] = -1*(F_interp[j][i] - F_perturbe_interp[j][i])/h
270 except ZeroDivisionError:
271 fic=open(os.getcwd()+'/fort.'+str(unite_resu),'a')
272 fic.write('\n Probleme de division par zéro dans le calcul de la matrice de sensiblité')
273 fic.write('\n Le parametre '+para[k]+'est nul ou plus petit que la précision machine')
275 UTMESS('F','MACR_RECAL',"Probleme de division par zéro dans le calcul de la matrice de sensiblité.\n Le parametre "+para[k]+"est nul ou plus petit que la précision machine")
279 # On utilise le calcul de SENSIBILITE
280 # --------------------------------------------------------------
281 # Dans ce cas, L_deriv_sensible a deja ete calculé pour le premier calcul pour val[k], aucun autre calcul_F n'est a lancer
283 if INFO>=2: UTMESS('I','MACR_RECAL','On utilise le calcul de SENSIBILITE pour : %s ' % para[k])
286 fic=open(os.getcwd()+'/fort.'+str(unite_resu),'a')
287 fic.write('\nCalcul de la sensibilité par la SENSIBILITE pour : '+para[k])
290 L_deriv_sensible_interp = L_deriv_sensible
292 # Calcul de L_A (matrice sensibilité des erreurs sur F interpolée)
293 for j in range(len(reponses)):
294 for i in range(len(self.resu_exp[j])):
296 # On interpole la fonction derivée aux points experimentaux
297 val_derivee_interpolee = self.InterpolationLineaire( self.resu_exp[j][i][0], L_deriv_sensible_interp[ para[k] ][:][j] )
299 # Application du poids de la reponse courante j
300 val_derivee_interpolee = val_derivee_interpolee*self.poids[j]
303 L_A[j][i,k] = -1.* ( val_derivee_interpolee ) / self.resu_exp[j][i][1]
304 except ZeroDivisionError:
305 L_A[j][i,k] = -1.* ( val_derivee_interpolee )
308 # --------------------------------------------------------------
310 # On construit la matrice de sensiblité sous forme d'un tab num
312 for i in range(len(L_A)):
313 dim.append(len(L_A[i]))
314 dim_totale = Numeric.sum(dim)
316 A = Numeric.zeros((dim_totale,len(val)),Numeric.Float)
317 for n in range(len(L_A)):
318 for k in range(len(val)):
319 for i in range(dim[n]):
320 A[i+a][k] = L_A[n][i,k]
323 del(L_A) # On ecrase tout ce qu'il y a dans L_A puisqu'on n'en a plus besoin