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