]> SALOME platform Git repositories - tools/eficas.git/blob - Aster/Cata/cataSTA9/Macro/impr_oar_ops.py
Salome HOME
44cebeccc4c089cf0a10a1d8b5711ea5ccc3dd76
[tools/eficas.git] / Aster / Cata / cataSTA9 / Macro / impr_oar_ops.py
1 #@ MODIF impr_oar_ops Macro  DATE 07/11/2006   AUTEUR DURAND C.DURAND 
2 # -*- coding: iso-8859-1 -*-
3 #            CONFIGURATION MANAGEMENT OF EDF VERSION
4 # ======================================================================
5 # COPYRIGHT (C) 1991 - 2006  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.                                                  
10 #                                                                       
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.                              
15 #                                                                       
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
21 import aster
22 try :
23    from Utilitai.Utmess import UTMESS
24    from Utilitai.Table import Table
25    from Utilitai.partition import MAIL_PY
26 except :
27    pass
28
29 def buildTabString(tabLevel):
30    """
31       Construit une chaine de tabulation
32    """
33    chaine = ''
34    for i in range(0, tabLevel) :
35       chaine += '\t'
36       
37    return chaine
38    
39 def getBornes(listIn, valTest) :
40    """
41       Retourne un doublet de valeurs qui correspond aux valeurs de la liste qui encadrent la valeur (valTest)
42       Si val n'est pas encadrée par des valeurs de la liste, une des valeurs du doublet est None
43    """
44    v1 = None
45    v2 = None   
46    for val in listIn :
47       if valTest > val : v1 = val
48       if valTest < val : v2 = val
49       
50    # traitement des cas limites
51    if valTest == listIn[0] : v1 = listIn[0]
52    if valTest == listIn[len(listIn)-1] : v2 = listIn[len(listIn)-1]
53    
54    return (v1, v2) 
55
56 def interpoleLin(listDoublet, X) :
57    """
58       Interpole linéairement entre deux bornes définies par listDoublets[(X0, Y0), (X1, Y1)] la valeur Y en X
59    """
60    X0 = listDoublet[0][0]
61    Y0 = listDoublet[0][1]
62    X1 = listDoublet[1][0]
63    Y1 = listDoublet[1][1]
64    
65    return Y0 + (X - X0) * (Y1 - Y0) / (X1 - X0)
66
67 class interpolationError(Exception) :
68    def __init__(self) :
69       self.mess = 'Interpolation sur une valeur hors bornes'
70       self.otherExcept = Exception()
71         
72    def getMess(self) :
73       """ 
74          retourne le message associé à l'erreur
75       """
76       # Analyse les différents cas d'erreurs
77       if self.otherExcept == IOError :
78          self.mess += "\nProblème à l'ouverture du fichier\n"
79
80       return self.mess
81  
82 class XMLNode :
83     """
84         Classe gérant un noeud de l'arborescence XML
85         Un noeud possède :
86             - un nom de balise
87             - un commentaire (optionnel)
88             - un ensemble de "paramètres" (optionnels)
89             - une liste d'élément ou d'autres noeuds (optionnels/possibilité de balises vides) :
90
91         La classe propose : 
92             - une méthode "buildTree" qui parcoure le liste de manière récursive pour
93               produire l'arborescence XML en vu de son enregistrement ou son impression
94             - (TO DO) une methode statique "loadTree" qui produit un arbre XML à partir d'un fichier
95     """
96     def __init__(self, nomBalise, valeur = None, commentaire = None, **listOpt) :
97         self.nomBalise = nomBalise
98         self.commentaire = commentaire
99         self.param = listOpt
100         self.arbre=list()
101         if valeur != None : self.addValue(valeur) # None n'est pas 0 !
102
103     def getCommentaire(self) : return self.commentaire
104
105     def setCommentaire(sel, commentaire) : self.commentaire = commentaire
106
107     def getParametres(self) : return  self.param
108
109     def setParametres(self, parametres) : self.param = parametres    
110
111     def append(self, nodeName, valeur=None, commentaire = None, **listOpt) :
112         """
113             Ajoute un noeud à l'arborescence et retourne une référence sur ce noeud
114             On peut ajouter directement la valeur, si simple, associée à la balise
115         """
116         node = XMLNode(nodeName, valeur, commentaire)
117
118         self.arbre.append(node)
119
120         return self.arbre[len(self.arbre)-1]
121
122     def addValue(self, valeur):
123         """
124             Ajoute un élément "simple" (nombre, texte) à l'arborescence
125         """
126         self.arbre.append(valeur)
127             
128     def buildTree(self, tabLevel=0) :
129         """
130             Construit l'arborescence XML en parcourant récursivement la structure de donnée
131             et la retourne sous la forme d'une chaine de caractères
132
133             tabLevel permet de gérer l'indentation
134         """
135         # Construction de la chaine de tabulations nécessaire à une bonne lecture du fichier XML
136         tabString = buildTabString(tabLevel) 
137
138         XMLString = ''
139         
140         try :
141             # listOpt contient les paramètres optionnels de la balise
142             chaine = ''
143             for v in self.param.keys() :
144                 chaine = chaine + ' ' +  v  + '=' + self.param[v] 
145         except : pass
146         
147         baliseOuverture=tabString + "<" + self.nomBalise + chaine +">\n"
148         XMLString += baliseOuverture
149
150         if self.commentaire :
151             XMLString = XMLString + tabString + "\t<!--"+self.commentaire+"-->\n"
152
153         for elem in self.arbre :
154             try :
155                 XMLString += elem.buildTree(tabLevel+1)
156             except : # l'élément n'est pas un noeud
157                 XMLString = XMLString + tabString + '\t' + str(elem) + '\n'
158
159         XMLString = XMLString + tabString + "</"+self.nomBalise+">\n"
160
161         return XMLString
162
163     def save(self, fileObj) :
164         """ 
165          Construit le l'arborescence XML et l'écrit dans un fichier 
166          pointé par le handler passé en paramètres
167         """ 
168         try :
169             fileObj.write(self.buildTree())
170         except : pass
171
172 class OAR_element :
173    """
174       Classe de base des éléments manipulés par IMPR_OAR
175    """
176    def __init__(self) :
177       self.nodeComp = None
178       
179    def buildTree(self) : pass
180
181    def getNode(self) :
182       """
183          Renvoie le noeud XML construit par buildTree
184       """
185       return self.nodeComp
186    
187
188 class composant(OAR_element) :
189    """
190       Classe permettant de traiter les composants
191       
192       NB :
193       1. L utilisateur est suppose faire la meme coupe pour le calcul mecanique et le calcul thermo-mecanique 
194       2. Dans le cas d'un revetement, l'utilisateur est supposé définir son plan de coupe de telle sorte 
195          que la coupe de la structure et la coupe du revetement se raccordent
196    """
197    def __init__(self, **args) :
198       self.nodeComp = XMLNode("COMPOSANT") # Racine de l'arborescence composant
199       
200       self.diametre = args['DIAMETRE']
201       self.origine  = args['ORIGINE']
202       self.coef_u   = args['COEF_U']
203       self.angle_c  = args['ANGLE_C']
204       self.revet    = args['REVET']
205       
206       self.lastAbscisse = None # Permet de gerer le recouvrement des points de coupe entre revetement et structure
207       self.num_char = -1
208       self.type_char = ''
209       self.tabAbscisses = list()
210       self.tabAbscisses_S = None
211       self.dictMeca = dict()
212       self.dictMeca_S = None # Pas créé car optionnel
213       self.epaisseur = 0.0
214       self.epaisseur_R = 0.0
215
216       # dictionnaire gérant le résultat contraintes en fonction des instants et des abscisses
217       self.dictInstAbscSig = dict()
218       self.dictInstAbscSig_S = None # Création si nécessaire
219       # dictionnaire gérant le résultat température en fonction des instants et des abscisses
220       self.dictInstAbscTemp = dict()
221       self.dictInstAbscTemp_S = None # facultatif 
222       self.list_inst = None
223       self.num_tran = None    
224
225       self.noResuMeca = False
226       self.noResuTher = False
227       
228       # 1. resultat mecanique
229       try : 
230          # On ne construit qu'une table des abscisses et une table des contraintes.
231          # Le revetement est obligatoirement en interne on commence par lui
232          para_resu_meca = args['RESU_MECA']
233          self.num_char = para_resu_meca['NUM_CHAR']
234          self.type_char = para_resu_meca['TYPE']
235
236          if self.revet == 'OUI' :
237             # Construction de la table complementaire si revetement
238             self.dictMeca_S = dict()
239             self.tabAbscisses_S = list()
240             self.buildTablesMeca('TABLE_S', para_resu_meca, self.tabAbscisses_S, self.dictMeca_S)
241             self.epaisseur_R = abs(self.tabAbscisses_S[len(self.tabAbscisses_S)-1] - self.tabAbscisses_S[0])
242          
243          self.buildTablesMeca('TABLE', para_resu_meca, self.tabAbscisses, self.dictMeca, offset=self.epaisseur_R)
244         
245          if self.revet == 'OUI' :
246             self.mergeDictMeca() # merge les tableaux resultats du revetement et de la structure
247
248          # Calcul de l'épaisseur de la coupe.
249          self.epaisseur = abs(self.tabAbscisses[len(self.tabAbscisses)-1] - self.tabAbscisses[0])
250  
251       except : 
252          self.noResuMeca = True
253       
254       # 2. Résultat thermique
255       try :
256          para_resu_ther = RESU_THER
257          self.num_tran = para_resu_ther['NUM_TRAN']
258          self.tabAbscisses = list()
259          self.tabAbscisses_S = None
260          
261          listInst = list()
262          if self.revet == 'OUI' :
263             # Le revetement est obligatoirement en interne on commence par lui
264             # 1. Construction champ temperature
265             self.dictInstAbscTemp_S = dict()
266             self.buildTemp('TABLE_ST', para_resu_ther, self.dictInstAbscTemp_S)
267          
268             # 2. Construction de la "table" des contraintes
269             self.dictInstAbscSig_S = dict()
270             self.tabAbscisses_S = list()
271             self.buildTablesTher('TABLE_S', para_resu_ther, self.tabAbscisses_S, self.dictInstAbscSig_S)
272                
273             # 3. calcul de l'épaisseur
274             self.epaisseur_R = abs(self.tabAbscisses_S[len(self.tabAbscisses_S)-1] - self.tabAbscisses_S[0])
275          
276          # Pour la structure
277          # 1. Construction champ température
278          self.buildTemp('TABLE_TEMP', para_resu_ther, self.dictInstAbscTemp, self.epaisseur_R)
279
280          # 2. Construction de la table des contraintes
281          self.buildTablesTher('TABLE_T', para_resu_ther, self.tabAbscisses, self.dictInstAbscSig, offset=self.epaisseur_R)
282         
283          if self.revet == 'OUI' :
284             self.mergeDictTher() # merge les tableaux resultats du revetement et de la structure
285             
286          if  not(self.compareListAbscTher()) :
287             UTMESS('F', 'IMPR_OAR', 'LES COUPES MECANIQUES ET THERMIQUE DOIVENT PARTAGER LES MEMES ABSCISSES')
288             
289          try :
290             self.interpoleInstants() # Interpolation des instants de la table des température sur celle de la table mécanique
291          except interpolationError, err:
292             UTMESS('F', 'IMPR_OAR', err.getMess())
293
294          # 3. Calcul de l'épaisseur de la coupe.
295          self.epaisseur = abs(self.tabAbscisses[len(self.tabAbscisses)-1] - self.tabAbscisses[0])
296
297       except :
298          self.noResuTher = True
299       
300       # Construction de l arborescence
301       self.buildTree() 
302            
303                 
304    def getAbscisses(self, dicoTable, tableAbsc, offset=0.0) :
305       """
306          Récupère la liste des abscisses
307       """
308       # récupération des abscisses
309       ABSCISSES = dicoTable['ABSC_CURV']
310      
311       valeurAbsc = 0.0
312       for val in ABSCISSES :
313          valeurAbsc = val + offset
314          tableAbsc.append(valeurAbsc)
315          
316    def buildTablesMeca(self, label, para_resu, tableAbsc, dictMeca, offset=0.0) :
317       """
318          Construction des tableaux mécanique 
319       """ 
320       sigma_xml   = ( 'S_RR', 'S_TT', 'S_ZZ', 'S_RT', 'S_TZ', 'S_ZR' )
321       
322       table_meca = para_resu[label].EXTR_TABLE() 
323       
324       # Utilisation des méthodes de la classe table
325       dictTable = table_meca.values()
326
327       # récupération des abscisses
328       self.getAbscisses(dictTable, tableAbsc, offset)
329       
330       # Construction de la table mécanique principale
331       for val in sigma_xml :
332          dictMeca[val] = list()
333
334       S_XX = dictTable['SIXX']
335       S_YY = dictTable['SIYY']
336       S_ZZ = dictTable['SIZZ']
337       S_XY = dictTable['SIXY']
338       S_YZ = dictTable['SIYZ']
339       S_XZ = dictTable['SIXZ']
340       for v1, v2, v3, v4, v5, v6 in zip(S_XX, S_YY, S_ZZ, S_XY, S_YZ, S_XZ) :
341          dictMeca['S_RR'].append(v1)
342          dictMeca['S_TT'].append(v2)
343          dictMeca['S_ZZ'].append(v3)
344          dictMeca['S_RT'].append(v4)
345          dictMeca['S_TZ'].append(v5)
346          dictMeca['S_ZR'].append(v6)
347     
348    def mergeDictMeca(self) :
349       """
350       Merge des résultats mécaniques issus de la structure et du revetement
351       """
352       # Merge des listes d'abscisses
353       # Le revetement est interieur la derniere abscisse du revetement doit etre egal a la premiere de la structure
354       if self.tabAbscisses_S[len(self.tabAbscisses_S)-1] != self.tabAbscisses[0] :
355          UTMESS('F', 'IMPR_OAR', 'LES COUPES DU REVETEMENT ET DE LA STRUCTURE DOIVENT PARTAGER UNE ABSCISSE COMMUNE')
356          
357       # On construit une table des abscisses tempopraire
358       tableAbscTemp = self.tabAbscisses_S
359       
360       # On recopie la table des abscisses en sautant le premier
361       debut = True
362       for val in self.tabAbscisses :
363          if debut :
364             debut = False
365             continue
366          tableAbscTemp.append(val)
367          
368       self.tabAbscisses = tableAbscTemp
369       
370       # On construit des listes de travail intermédiaires que l'on commence par remplir avec les tables "supplémentaires"
371       dictMecaBis = self.dictMeca_S
372       
373       # On recopie les éléments de la structure dans le tableau
374       debut = True
375       for v1, v2, v3, v4, v5, v6 in zip(self.dictMeca['S_RR'], self.dictMeca['S_TT'], self.dictMeca['S_ZZ'], self.dictMeca['S_RT'], self.dictMeca['S_TZ'], self.dictMeca['S_ZR']) :
376          if debut :
377             debut = False
378             continue
379          dictMecaBis['S_RR'].append(v1)
380          dictMecaBis['S_TT'].append(v2)
381          dictMecaBis['S_ZZ'].append(v3)
382          dictMecaBis['S_RT'].append(v4)
383          dictMecaBis['S_TZ'].append(v5)
384          dictMecaBis['S_ZR'].append(v6)
385          
386       # On restitue ensuite la liste globale dans self.dictMeca
387       self.dictMeca = dictMecaBis
388
389   
390    def buildTemp(self, label, para_resu, dictInstAbscTemp, offset=0.0):
391       """
392          Récupération du champ température aux noeuds avec interpolation sur les "instants" du calcul mécanique
393       """
394       table_temp = para_resu[label].EXTR_TABLE()
395
396       # Utilisation des méthodes de la classe table
397       dictTable = table_temp.values()
398       
399       # On construit un dictionnaire associant un "instant" avec un couple ("abscisse", "température")
400
401       # 1. Récupération de la liste des instants
402       INSTANTS = dictTable['INST']
403       for val in INSTANTS :
404          dictInstAbscTemp[val] = 0 # On crée juste les clés du dictionnaire
405          
406       listTables = list() # liste de tables contenant une table pas instant
407       for inst in dictInstAbscTemp.keys():
408          listTables.append(table_temp.INST == inst)
409          
410       # 2. Récupération des abscisses
411       tableAbsc = list()
412       self.getAbscisses(listTables[0].values(), tableAbsc, offset)
413       
414       # 3. Récupération des températures
415       tableTemp = list() # liste de liste de température (1 par instant)
416       for tb in listTables :
417          TEMPERATURE = tb.values()['TEMP']
418          tableTemp.append(TEMPERATURE)
419          
420       # 4. Construction de dictInstAbscTemp
421       for i in range(0, len(dictInstAbscTemp.keys())):
422          listDoublets = list()
423          for absc, temp in zip(tableAbsc, tableTemp[i]) :
424             listDoublets.append((absc,temp))
425             
426          inst = dictInstAbscTemp.keys()[i]
427          dictInstAbscTemp[inst] = listDoublets
428          
429    def buildTablesTher(self, label, para_resu, tabAbscisses, dictInstAbscSig, offset=0.0) :
430       """
431          Construction des tableaux thermo-mécanique
432          listDictTher contient un dictionnaire par numéro d'ordre 
433       """
434       table_temp = para_resu[label].EXTR_TABLE()   
435
436       # On construit un dictionnaire associant un "instant" avec une liste de couples ("abscisse", liste de "sigma")
437
438       # Utilisation des méthodes de la classe table
439       dictTable = table_temp.values()
440       
441       # On construit un dictionnaire associant un "instant" avec un couple ("abscisse", "température")
442
443       # 1. Récupération de la liste des instants
444       INSTANTS = dictTable['INST']
445       for val in INSTANTS :
446          dictInstAbscSig[val] = 0 # On crée juste les clés du dictionnaire
447          
448       listTables = list() # liste de tables contenant une table pas instant
449       for inst in dictInstAbscSig.keys():
450          listTables.append(table_temp.INST == inst)
451          
452       # 2. Récupération des abscisses
453       self.getAbscisses(listTables[0].values(), tabAbscisses, offset)
454          
455       # 3. Récupération des listes de sigma
456       listListListSigAbscInst = list() # liste des sigma par abscisse par instant
457       for tbl in listTables:
458          listListSigAbscInst = list()
459          
460          # On crée une table pour chaque instant
461          S_XX = tbl.values()['SIXX']
462          S_YY = tbl.values()['SIYY']
463          S_ZZ = tbl.values()['SIZZ']
464          S_XY = tbl.values()['SIXY']
465          S_YZ = tbl.values()['SIYZ']
466          S_XZ = tbl.values()['SIXZ']
467          for v1, v2, v3, v4, v5, v6 in zip(S_XX, S_YY, S_ZZ, S_XY, S_YZ, S_XZ) :
468             listSigAbsc = list() # Liste des sigmas pour une abscisse
469             listSigAbsc.append(v1)
470             listSigAbsc.append(v2)
471             listSigAbsc.append(v3)
472             listSigAbsc.append(v4)
473             listSigAbsc.append(v5)
474             listSigAbsc.append(v6)
475             
476             listListSigAbscInst.append(listSigAbsc)
477             
478          listListListSigAbscInst.append(listListSigAbscInst)
479          
480       # 4. Assemblage du dictionnaire
481       for i in range(0, len(dictInstAbscSig.keys())) :
482          listDoublet = list()
483          for j in range(0, len(tabAbscisses)) :
484            listDoublet.append((tabAbscisses[j], listListListSigAbscInst[i][j]))
485                
486          dictInstAbscSig[dictInstAbscSig.keys()[i]] = listDoublet 
487
488    def mergeDictTher(self) : 
489       """
490          Merge les resultats issus de la coupe du revetement avec ceux issus de la coupe de la structure
491       """
492       # Merge des listes d'abscisses
493       # Le revetement est interieur la derniere abscisse du revetement doit etre egal a la premiere de la structure
494       if self.tabAbscisses_S[len(self.tabAbscisses_S)-1] != self.tabAbscisses[0] :
495          UTMESS('F', 'IMPR_OAR', 'LES COUPES DU REVETEMENT ET DE LA STRUCTURE DOIVENT PARTAGER UNE ABSCISSE COMMUNE')
496          
497       # On construit une table des abscisses tempopraire
498       tableAbscTemp = self.tabAbscisses_S
499       
500       # On recopie la table des abscisses en sautant le premier
501       debut = True
502       for val in self.tabAbscisses :
503          if debut :
504             debut = False
505             continue
506          tableAbscTemp.append(val)
507          
508       self.tabAbscisses = tableAbscTemp
509        
510       # On construit des listes de travail intermédiaires que l'on commence par remplir avec les tables "supplémentaires"
511       dictInstAbscSigBis = self.dictInstAbscSig_S
512       dictInstAbscTempBis = self.dictInstAbscTemp_S
513       
514       # On recopie les élément thermiques de la structure principale en sautant la première abscisse de la structure
515       for key in dictInstAbscTempBis.keys() : # Les dictionnaires partagent les memes instants
516          debut = True
517          for valTher in self.dictInstAbscTemp[key] :
518             if debut :
519                debut = False
520                continue
521             dictInstAbscTempBis[key].append(valTher)
522             
523       # On recopie les élément mécaniques de la structure principale en sautant la première abscisse de la structure
524       for key in dictInstAbscSigBis.keys() : # Les dictionnaires partagent les memes instants
525          debut = True
526          for valSig in self.dictInstAbscSig[key] :
527             if debut :
528                debut = False
529                continue
530             dictInstAbscSigBis[key].append(valSig)
531
532       # On restitue ensuite la liste globale dans self.dictInstAbscSig
533       self.dictInstAbscSig = dictInstAbscSigBis
534       self.dictInstAbscTemp = dictInstAbscTempBis
535
536    def compareListAbscTher(self) :
537       """
538          Vérifie que la coupe du champ thermique et la coupe mécanique partagent les memes abscisses
539       """
540       # 1. Récupération des abscisses associées aux températures
541       listAbsc = list()
542       lstDoublet = self.dictInstAbscTemp[self.dictInstAbscTemp.keys()[0]]
543       for val in lstDoublet :
544          listAbsc.append(val[0])
545          
546       # 2. Comparaison des deux listes 
547       for A1, A2 in zip(self.tabAbscisses, listAbsc) :
548          if A1 != A2 : return False
549       
550       return True
551       
552    def interpoleInstants(self) :
553       """
554          Interpole les résultats thermique sur les instants des résultats mécaniques
555       """
556       # 1. récupération des instants des deux tables
557       listInstTher = self.dictInstAbscTemp.keys()
558       listInstMeca = self.dictInstAbscSig.keys()
559       
560       # 2. calcul de la liste des bornes de la table thermique qui encadrent les résultats mécaniques
561       dictInstAbscTemp = dict()
562       listAbscTemp = list()
563       listBornes = list()
564       for inst in listInstMeca :
565          bornes = getBornes(listInstTher, inst)
566          # Si une des bornes n'est pas définie, on lance une exception
567          if not(bornes[0]) or not(bornes[1]) : raise interpolationError
568           
569          abscTempInf = self.dictInstAbscTemp[bornes[0]] # Liste de doublet (abscisse, temperature) pour la borne inférieure
570          abscTempSup = self.dictInstAbscTemp[bornes[1]] # Liste de doublet (abscisse, temperature) pour la borne supérieure
571          
572          listAbscTemp = list() # liste de couples abscisses/Température
573          for A1, A2 in zip(abscTempInf, abscTempSup) : # A1 et A2 sont des doublets abscisse/Temperature
574             temperature = interpoleLin( ((bornes[0], A1[1]), (bornes[1], A2[1])), inst)   
575             listAbscTemp.append((A1[0], temperature)) # on aurait pu tout aussi bien prendre A2[0] (c est pareil ...)
576             
577          dictInstAbscTemp[inst] = listAbscTemp
578          
579       # remplacement de l'ancienne table par la nouvelle
580       self.dictInstAbscTemp = dictInstAbscTemp
581
582    def buildTree(self) :
583       """
584          Construction (en mémoire) de l'arborescence du document XML
585       """
586       sigma_xml   = ( 'S_RR', 'S_TT', 'S_ZZ', 'S_RT', 'S_TZ', 'S_ZR' )
587
588       # Création de l'arborescence "géométrie"
589       nodeGeomComp = self.nodeComp.append("GEOM_COMPO")
590       nodeGeomComp.append("REVETEMENT", valeur=self.revet)
591       if self.revet == 'OUI' :
592          nodeGeomComp.append("EP_REVET", valeur=self.epaisseur_R)
593       nodeLigneCoupe = nodeGeomComp.append("LIGNE_COUPE")
594       nodeLigneCoupe.append("EPAISSEUR_EF", valeur=self.epaisseur)
595       nodeLigneCoupe.append("DIAM_EXT_EF", valeur=self.diametre)
596       nodeLigneCoupe.append("ORI_ABSC", valeur=self.origine)
597       
598       if self.noResuMeca == False :
599          # Création des abscisses
600          for val in self.tabAbscisses :
601             nodeLigneCoupe.append("ABSCISSE", val)
602       
603          nodeLigneCoupe.append('PSI', self.angle_c)
604       
605          # Création des résultats mécaniques
606          nodeSigma_u = self.nodeComp.append("SIGMA_UNITE")
607          nodeSigma_u.append("NUM_MECA", valeur=self.num_char)
608          nodeSigma_u.append("NOM_MECA", valeur=self.type_char)
609          nodeSigma_meca = nodeSigma_u.append("SIGMA_MECA")
610          
611          for i in range(0, len(self.tabAbscisses)) :
612             for val in self.dictMeca.keys() :
613                nodeSigma_meca.append(val, valeur = self.dictMeca[val][i])
614      
615       # Création de l'arborescence "résultat thermo_mécanique"
616       if self.noResuTher == False :
617          # Création des abscisses
618          listDoublet = self.dictInstAbscTemp[self.dictInstAbscTemp.keys()[0]]
619          for val in listDoublet :
620             nodeLigneCoupe.append("ABSCISSE", val[0])
621             
622          nodeLigneCoupe.append('PSI', self.angle_c)
623             
624          # Création des résultats mécaniques
625          nodeSigma_ther_c = self.nodeComp.append("SIGMA_THER_C")
626          nodeSigma_ther_c.append("NUM_TRANSI_THER", valeur=self.num_tran)
627          
628          for inst in self.dictInstAbscTemp.keys() : # boucle sur les instants
629             nodeSigma_ther = nodeSigma_ther_c.append("SIGMA_THER")
630             nodeSigma_ther.append("INSTANT", valeur=inst)
631             
632             # boucle sur les abscisses
633             for doubletAbscSig, doubletAbscTemp in zip(self.dictInstAbscSig[inst], self.dictInstAbscTemp[inst]) : 
634                nodeSigma_point = nodeSigma_ther.append("SIGMA_POINT")
635                for val, label in zip(doubletAbscSig[1], sigma_xml) :
636                   nodeSigma_point.append(label, valeur = val)
637                
638                nodeSigma_point.append("TEMPERATURE", doubletAbscTemp[1]) 
639
640 class tuyauterie(OAR_element) :
641    """
642       Classe permettant de traiter les tuyauteries
643    """
644    def __init__(self, **args) :
645       self.nodeComp = XMLNode("TUYAUTERIE")
646       try :
647          self.para_resu_meca = args['RESU_MECA']
648          self.num_char = self.para_resu_meca['NUM_CHAR']
649       
650          #Gestion du maillage
651          self.maillage = self.para_resu_meca['MAILLAGE']
652          mapy = MAIL_PY()
653          mapy.FromAster(self.maillage)
654       
655          self.ma = [val.rstrip() for val in mapy.correspondance_mailles]
656          self.no = [val.rstrip() for val in mapy.correspondance_noeuds]
657       
658          self.dictMailleNoeuds = dict()
659          for val in self.ma :
660             self.dictMailleNoeuds[val] = list()
661       
662          for i in range(0, len(mapy.co)) :
663             self.dictMailleNoeuds[self.ma[i]].append(self.no[mapy.co[i][0]])
664             self.dictMailleNoeuds[self.ma[i]].append(self.no[mapy.co[i][1]])
665       
666          self.dictNoeudValTorseur = dict()
667          self.buildTableTorseur()
668       
669       except :
670          UTMESS('F', 'IMPR_OAR', "ERREUR D'ACCES AUX DONNEES")
671
672       # Construction de l arborescence
673       self.buildTree() 
674        
675
676    def buildTableTorseur(self) :
677       """
678          Construit un dictionnaire associant un noeud à un torseur exprimé sous la forme d'une liste de valeurs
679       """
680       table_temp = self.para_resu_meca['TABLE'].EXTR_TABLE()   
681
682       # Utilisation des méthodes de la classe table
683       dictTable = table_temp.values()
684       
685       # 1. Récupération de la liste des noeuds
686       NOEUDS = dictTable['NOEUD']
687       for val in NOEUDS :
688          self.dictNoeudValTorseur[val.rstrip()] = list() # On crée juste les clés du dictionnaire
689          
690       N   = dictTable['N']
691       VY  = dictTable['VY']
692       VZ  = dictTable['VZ']
693       MT  = dictTable['MT']
694       MFY = dictTable['MFY']
695       MFZ = dictTable['MFZ']
696       
697       for no, n, vy, vz, mt, mfy, mfz in zip(NOEUDS, N, VY, VZ, MT, MFY, MFZ):
698          no = no.rstrip()
699          self.dictNoeudValTorseur[no].append(n)
700          self.dictNoeudValTorseur[no].append(vy)
701          self.dictNoeudValTorseur[no].append(vz)
702          self.dictNoeudValTorseur[no].append(mt)
703          self.dictNoeudValTorseur[no].append(mfy)
704          self.dictNoeudValTorseur[no].append(mfz)
705          
706          
707    def buildTree(self) :
708       """
709          Construction (en mémoire) de l'arborescence du document XML
710       """
711       torseur_XML   = ( 'FX', 'FY', 'FZ', 'MX', 'MY', 'MZ' )
712
713       # Création de l'arborescence "torseur"
714       nodeTMG = self.nodeComp.append("TORSEUR_MECA-GRP")
715       nodeTM = nodeTMG.append("TORSEUR_MECA")
716       nodeTM.append("oar:CHAR-REF", self.num_char)
717       nodeMTG = nodeTM.append("MAILLE_TORSEUR-GRP")
718       nodeMT = nodeMTG.append("MAILLE_TORSEUR")
719       for MA in self.dictMailleNoeuds.keys() : # Boucle sur les mailles
720          nodeMT.append("oar:MAILLE-REF", MA)
721          for NO in self.dictMailleNoeuds[MA] : # 2 noeuds
722             nodeTorseur = nodeMT.append("oar:TORSEUR")
723             for val, cle in zip(self.dictNoeudValTorseur[NO], torseur_XML) : # 6 valeurs
724                nodeTorseur.append(cle, val)
725       
726       
727
728 def impr_oar_ops(self, TYPE_CALC, **args) :
729    """
730    Macro IMPR_OAR
731    Ecrit des fichiers au format XML selon la DTD OAR Fichier
732    
733    IMPR_OAR va etre utilise en deux fois d abord calcul mecanique, 
734    ensuite calcul thermique ce qui implique qu il ne peut y avoir qu'une seule des deux options a la fois
735    """
736    # La macro compte pour 1 dans la numérotation des commandes
737    self.set_icmd(1)
738    
739    obj = None
740    
741    if TYPE_CALC=='COMPOSANT' :
742       obj = composant(**args)
743    elif TYPE_CALC=='MEF' : 
744       UTMESS('F', 'IMPR_OAR', 'FONCTION NON IMPLANTEE') 
745    elif TYPE_CALC=='TUYAUTERIE' :
746       obj = tuyauterie(**args) 
747    else :
748       UTMESS('F', 'IMPR_OAR', 'Mot clé facteur inconnu')
749
750    # Ecriture dans le fichier
751    # Récupération de la LU du fichier de sortie
752    try :
753       unite = args['UNITE']
754    except :
755       unite = 38
756       
757    try :
758       ajout=args['AJOUT']
759    except :
760       ajout='NON'
761          
762    name = 'fort.'+str(unite)
763    try :
764       if ajout=='NON' :  # nouveau fichier
765          fileObj = open(name, 'wt')
766       else :            # extension du fichier existant
767          fileObj = open(name, 'a+t')
768    except IOError :
769       UTMESS('F', 'IMPR_OAR', "Erreur à l'ouverture du fichier") 
770    else :
771       obj.getNode().save(fileObj)
772       fileObj.close()