Salome HOME
CCAR: merge de la version 1.14 dans la branche principale
[tools/eficas.git] / Aster / Cata / cataSTA8 / ops.py
1 #@ MODIF ops Cata  DATE 04/06/2008   AUTEUR MACOCCO K.MACOCCO 
2 # -*- coding: iso-8859-1 -*-
3 #            CONFIGURATION MANAGEMENT OF EDF VERSION
4 # ======================================================================
5 # COPYRIGHT (C) 1991 - 2001  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
22 # Modules Python
23 import types
24 import string,linecache,os,traceback,re
25 import pickle
26
27 # Modules Eficas
28 import Accas
29 from Accas import ASSD
30
31
32 try:
33    import aster
34    # Si le module aster est présent, on le connecte
35    # au JDC
36    import Build.B_CODE
37    Build.B_CODE.CODE.codex=aster
38    from Utilitai.Utmess import UTMESS
39 except:
40    pass
41
42 def DEBUT(self,PAR_LOT,IMPR_MACRO,CODE,DEBUG,**args):
43    """
44        Fonction sdprod de la macro DEBUT
45    """
46    # La commande DEBUT ne peut exister qu'au niveau jdc
47    if self.jdc is not self.parent :
48       raise Accas.AsException("La commande DEBUT ne peut exister qu'au niveau jdc")
49
50    self.jdc.impr_macro=IMPR_MACRO
51    self.jdc.jxveri=0
52    if DEBUG!=None :
53       if DEBUG['JXVERI']=='OUI' : self.jdc.jxveri=1
54    self.jdc.set_par_lot(PAR_LOT)
55    if CODE!=None :
56       self.jdc.fico=CODE['NOM']
57    else:
58       self.jdc.fico=None
59
60 def build_debut(self,**args):
61    """
62    Fonction ops pour la macro DEBUT
63    """
64    self.jdc.UserError=self.codex.error
65
66    if self.jdc.par_lot == 'NON' :
67       self.jdc._Build()
68    # On execute la fonction debut pour initialiser les bases
69    # Cette execution est indispensable avant toute autre action sur ASTER
70    # op doit etre un entier car la fonction debut appelle GCECDU qui demande
71    # le numero de l'operateur associé (getoper)
72    self.definition.op=0
73    self.set_icmd(1)
74    lot,ier=self.codex.debut(self,1)
75    # On remet op a None juste apres pour eviter que la commande DEBUT
76    # ne soit executée dans la phase d'execution
77    self.definition.op=None
78    return ier
79
80 def POURSUITE(self,PAR_LOT,IMPR_MACRO,CODE,DEBUG,**args):
81    """
82        Fonction sdprod de la macro POURSUITE
83    """
84    # La commande POURSUITE ne peut exister qu'au niveau jdc
85    if self.jdc is not self.parent :
86       raise Accas.AsException("La commande POURSUITE ne peut exister qu'au niveau jdc")
87
88    self.jdc.impr_macro=IMPR_MACRO
89    self.jdc.set_par_lot(PAR_LOT)
90    self.jdc.jxveri=0
91    if DEBUG!=None :
92       if DEBUG['JXVERI']=='OUI' : self.jdc.jxveri=1
93    if CODE!=None :
94       self.jdc.fico=CODE['NOM']
95    else:
96       self.jdc.fico=None
97    if (self.codex and os.path.isfile("glob.1") or os.path.isfile("bhdf.1")):
98      # Le module d'execution est accessible et glob.1 est present
99      # Pour eviter de rappeler plusieurs fois la sequence d'initialisation
100      # on memorise avec l'attribut fichier_init que l'initialisation
101      # est réalisée
102      if hasattr(self,'fichier_init'):return
103      self.fichier_init='glob.1'
104      self.jdc.initexec()
105      # le sous programme fortran appelé par self.codex.poursu demande le numero
106      # de l'operateur (GCECDU->getoper), on lui donne la valeur 0
107      self.definition.op=0
108      lot,ier,lonuti,concepts=self.codex.poursu(self,1)
109      # Par la suite pour ne pas executer la commande pendant la phase
110      # d'execution on le remet à None
111      self.definition.op=None
112      # On demande la numerotation de la commande POURSUITE avec l'incrément
113      # lonuti pour qu'elle soit numérotée à la suite des commandes existantes.
114 ####CD     self.set_icmd(lonuti)
115      pos=0
116      d={}
117      while pos+80 < len(concepts)+1:
118        nomres=concepts[pos:pos+8]
119        concep=concepts[pos+8:pos+24]
120        nomcmd=concepts[pos+24:pos+40]
121        statut=concepts[pos+40:pos+48]
122        print nomres,concep,nomcmd,statut
123        if nomres[0] not in (' ','.','&') and statut != '&DETRUIT':
124           exec nomres+'='+string.lower(concep)+'()' in self.parent.g_context,d
125        elif statut == '&DETRUIT' : self.jdc.nsd = self.jdc.nsd+1
126        pos=pos+80
127      for k,v in d.items():
128        self.parent.NommerSdprod(v,k)
129      self.g_context=d
130
131      # Il peut exister un contexte python sauvegardé sous forme  pickled
132      # On récupère ces objets après la restauration des concepts pour que
133      # la récupération des objets pickled soit prioritaire.
134      # On vérifie que les concepts relus dans glob.1 sont bien tous
135      # presents sous le meme nom et du meme type dans pick.1
136      # Le contexte est ensuite updaté (surcharge) et donc enrichi des
137      # variables qui ne sont pas des concepts.
138      # On supprime du pickle_context les concepts valant None, ca peut 
139      # etre le cas des concepts non executés, placés après FIN.
140      pickle_context=get_pickled_context()
141      if pickle_context==None :
142         UTMESS('F','Poursuite',"Erreur a la relecture du fichier pick.1 : aucun objet sauvegardé ne sera récupéré")
143         return
144      from Cata.cata  import ASSD,entier
145      from Noyau.N_CO import CO
146      for elem in pickle_context.keys():
147          if type(pickle_context[elem])==types.InstanceType :
148             pickle_class=pickle_context[elem].__class__
149             # on rattache chaque assd au nouveau jdc courant (en poursuite)
150             if isinstance(pickle_context[elem],ASSD) : 
151                pickle_context[elem].jdc=self.jdc
152                pickle_context[elem].parent=self.jdc
153                # pour que sds_dict soit cohérent avec g_context
154                self.jdc.sds_dict[elem] = pickle_context[elem]
155                assert elem == pickle_context[elem].nom
156             if elem in self.g_context.keys():
157                poursu_class=self.g_context[elem].__class__
158                if poursu_class!=pickle_class :
159                   UTMESS('F','Poursuite',"Types incompatibles entre glob.1 et pick.1 pour concept de nom "+elem)
160                   return
161             elif isinstance(pickle_context[elem],ASSD) and pickle_class not in (CO,entier) : 
162             # on n'a pas trouvé le concept dans la base et sa classe est ASSD : ce n'est pas normal
163             # sauf dans le cas de CO : il n'a alors pas été typé et c'est normal qu'il soit absent de la base
164             # meme situation pour le type 'entier' produit uniquement par DEFI_FICHIER
165                UTMESS('F','Poursuite',"Concept de nom "+elem+" et de type "+str(pickle_class)+" introuvable dans la base globale")
166                return
167          if pickle_context[elem]==None : del pickle_context[elem]
168      self.g_context.update(pickle_context)
169      return
170
171    else:
172      # Si le module d'execution n est pas accessible ou glob.1 absent on 
173      # demande un fichier (EFICAS)
174      # Il faut éviter de réinterpréter le fichier à chaque appel de
175      # POURSUITE
176      if hasattr(self,'fichier_init'):
177         return
178      self.make_poursuite()
179
180 def get_pickled_context():
181     """
182        Cette fonction permet de réimporter dans le contexte courant du jdc (jdc.g_context)
183        les objets python qui auraient été sauvegardés, sous forme pickled, lors d'une 
184        précédente étude. Un fichier pick.1 doit etre présent dans le répertoire de travail
185     """
186     if os.path.isfile("pick.1"):
187        file="pick.1"
188     else: return None
189    
190     # Le fichier pick.1 est présent. On essaie de récupérer les objets python sauvegardés
191     context={}
192     try:
193        file=open(file,'r')
194        # Le contexte sauvegardé a été picklé en une seule fois. Il est seulement
195        # possible de le récupérer en bloc. Si cette opération echoue, on ne récupère
196        # aucun objet.
197        context=pickle.load(file)
198        file.close()
199     except:
200        # En cas d'erreur on ignore le contenu du fichier
201        # traceback.print_exc()
202        return None
203
204     return context
205
206 def POURSUITE_context(self,d):
207    """
208        Fonction op_init de la macro POURSUITE
209    """
210    # self représente la macro POURSUITE ...
211    d.update(self.g_context)
212    # Une commande POURSUITE n'est possible qu'au niveau le plus haut
213    # On ajoute directement les concepts dans le contexte du jdc
214    # XXX est ce que les concepts ne sont pas ajoutés plusieurs fois ??
215    for v in self.g_context.values():
216       if isinstance(v,ASSD) : 
217          self.jdc.sds.append(v)
218
219 def build_poursuite(self,**args):
220    """
221    Fonction ops pour la macro POURSUITE
222    """
223    # Pour POURSUITE on ne modifie pas la valeur initialisee dans ops.POURSUITE
224    # Il n y a pas besoin d executer self.codex.poursu (c'est deja fait dans
225    # la fonction sdprod de la commande (ops.POURSUITE))
226    self.set_icmd(1)
227    self.jdc.UserError=self.codex.error
228    return 0
229
230 def INCLUDE(self,UNITE,**args):
231    """ 
232        Fonction sd_prod pour la macro INCLUDE
233    """
234    if not UNITE : return
235    if hasattr(self,'unite'):return
236    self.unite=UNITE
237
238    if self.jdc and self.jdc.par_lot == 'NON':
239       # On est en mode commande par commande, on appelle la methode speciale
240       self.Execute_alone()
241
242    self.make_include(unite=UNITE)
243
244 def INCLUDE_context(self,d):
245    """ 
246        Fonction op_init pour macro INCLUDE
247    """
248    for k,v in self.g_context.items():
249       d[k]=v
250
251 def build_include(self,**args):
252    """
253    Fonction ops de la macro INCLUDE appelée lors de la phase de Build
254    """
255    # Pour presque toutes les commandes (sauf FORMULE et POURSUITE)
256    # le numero de la commande n est pas utile en phase de construction
257    # La macro INCLUDE ne sera pas numérotée (incrément=None)
258    ier=0
259    self.set_icmd(None)
260    icmd=0
261    # On n'execute pas l'ops d'include en phase BUILD car il ne sert a rien.
262    #ier=self.codex.opsexe(self,icmd,-1,1)
263    return ier
264
265 def detruire(self,d):
266    """
267        Cette fonction est la fonction op_init de la PROC DETRUIRE
268    """
269    if hasattr(self,"executed") and self.executed == 1:
270       return
271    if self["CONCEPT"]!=None:
272      sd=[]
273      for mc in self["CONCEPT"]:
274        mcs=mc["NOM"]
275        if mcs is None:continue
276        if type(mcs) == types.ListType or type(mcs) == types.TupleType:
277          for e in mcs:
278            if isinstance(e,ASSD):
279              sd.append(e)
280              e=e.nom
281        # traitement particulier pour les listes de concepts, on va mettre à None
282        # le terme de l'indice demandé dans la liste :
283        # nomconcept_i est supprimé, nomconcept[i]=None
284            indice=e[e.rfind('_')+1:]
285            concept_racine=e[:e.rfind('_')]
286            if indice!='' and d.has_key(concept_racine) and type(d[concept_racine])==types.ListType:
287               try               :
288                                   indici=int(indice)
289                                   d[concept_racine][indici]=None
290               except ValueError : pass
291        # pour tous les concepts :
292            if d.has_key(e):del d[e]
293            if self.jdc.sds_dict.has_key(e):del self.jdc.sds_dict[e]
294        else:
295          if isinstance(mcs,ASSD):
296            sd.append(mcs)
297            mcs=mcs.nom
298        # traitement particulier pour les listes de concepts, on va mettre à None
299        # le terme de l'indice demandé dans la liste :
300        # nomconcept_i est supprimé, nomconcept[i]=None
301          indice=mcs[mcs.rfind('_')+1:]
302          concept_racine=mcs[:mcs.rfind('_')]
303          if indice!='' and d.has_key(concept_racine) and type(d[concept_racine])==types.ListType:
304             try               :
305                                 indici=int(indice)
306                                 d[concept_racine][indici]=None
307             except ValueError : pass
308        # pour tous les concepts :
309          if d.has_key(mcs):del d[mcs]
310          if self.jdc.sds_dict.has_key(mcs):del self.jdc.sds_dict[mcs]
311      for s in sd:
312        # On signale au parent que le concept s n'existe plus apres l'étape self 
313        self.parent.delete_concept_after_etape(self,s)
314
315 def subst_materiau(text,NOM_MATER,EXTRACTION,UNITE_LONGUEUR):
316    """
317        Cette fonction retourne un texte obtenu à partir du texte passé en argument (text)
318        en substituant le nom du materiau par NOM_MATER 
319        et en réalisant les extractions spéciifées dans EXTRACTION
320    """
321    lines=string.split(text,'\n')
322
323 ##### traitement de UNIT : facteur multiplicatif puissance de 10
324    regmcsu=re.compile(r" *(.*) *= *([^ ,]*) *## +([^ ]*) *([^ ]*)")
325    ll_u=[]
326    for l in lines:
327        m=regmcsu.match(l)
328        if m:
329           if m.group(3) == "UNIT":
330              if   UNITE_LONGUEUR=='M'  : coef = '0'
331              elif UNITE_LONGUEUR=='MM' : coef = m.group(4)
332              ll_u.append(m.group(1)+" = "+m.group(2)+coef)
333           else : ll_u.append(l)
334        else : ll_u.append(l)
335
336 ##### traitement de EXTRACTION
337    if EXTRACTION:
338      regmcf=re.compile(r" *(.*) *= *_F\( *## +(.*) +(.*)")
339      regmcs=re.compile(r" *(.*) *= *([^ ,]*) *, *## +([^ ]*) *([^ ]*)")
340      regfin=re.compile(r" *\) *")
341      ll=[]
342      temps={};lmcf=[]
343      for e in EXTRACTION:
344        mcf=e['COMPOR']
345        lmcf.append(mcf)
346        temps[mcf]=e['TEMP_EVAL']
347      FLAG=0
348      for l in ll_u:
349        m=regmcf.match(l)
350        if m: # On a trouve un mot cle facteur "commentarise"
351          if m.group(2) == "SUBST": # il est de plus substituable
352            if temps.has_key(m.group(3)): # Il est a substituer
353              ll.append(" "+m.group(3)+"=_F(")
354              mcf=m.group(3)
355              TEMP=temps[mcf]
356              FLAG=1 # Indique que l'on est en cours de substitution
357            else: # Il n est pas a substituer car il n est pas dans la liste demandee
358              ll.append(l)
359          else: # Mot cle facteur commentarise non substituable
360            ll.append(l)
361        else:  # La ligne ne contient pas un mot cle facteur commentarise
362          if FLAG == 0: # On n est pas en cours de substitution
363            ll.append(l)
364          else: # On est en cours de substitution. On cherche les mots cles simples commentarises
365            m=regmcs.match(l)
366            if m: # On a trouve un mot cle simple commentarise
367              if m.group(3) == "EVAL":
368                ll.append("  "+m.group(1)+' = '+m.group(4)+"("+str(TEMP)+'),')
369              elif m.group(3) == "SUPPR":
370                pass
371              else:
372                ll.append(l)
373            else: # On cherche la fin du mot cle facteur en cours de substitution
374              m=regfin.match(l)
375              if m: # On l a trouve. On le supprime de la liste
376                FLAG=0
377                del temps[mcf]
378              ll.append(l)
379    else:
380      ll=ll_u
381
382    lines=ll
383    ll=[]
384    for l in lines:
385      l=re.sub(" *MAT *= *",NOM_MATER+" = ",l,1)
386      ll.append(l)
387    text=string.join(ll,'\n')
388    return text
389
390 def post_INCLUDE(self):
391   """
392       Cette fonction est executée apres toutes les commandes d'un INCLUDE (RETOUR)
393       Elle sert principalement pour les INCLUDE_MATERIAU : remise a blanc du prefixe Fortran
394   """
395   self.codex.opsexe(self,0,-1,2)
396
397 def INCLUDE_MATERIAU(self,NOM_AFNOR,TYPE_MODELE,VARIANTE,TYPE_VALE,NOM_MATER,
398                     EXTRACTION,UNITE_LONGUEUR,INFO,**args):
399   """ 
400       Fonction sd_prod pour la macro INCLUDE_MATERIAU
401   """
402   mat=string.join((NOM_AFNOR,'_',TYPE_MODELE,'_',VARIANTE,'.',TYPE_VALE),'')
403   if not hasattr(self,'mat') or self.mat != mat or self.nom_mater != NOM_MATER :
404     # On récupère le répertoire des matériaux dans les arguments 
405     # supplémentaires du JDC
406     rep_mat=self.jdc.args.get("rep_mat","NOrep_mat")
407     f=os.path.join(rep_mat,mat)
408     self.mat=mat
409     self.nom_mater=NOM_MATER
410     if not os.path.isfile(f):
411        del self.mat
412        self.make_contexte(f,"#Texte sans effet pour reinitialiser le contexte a vide\n")
413        raise "Erreur sur le fichier materiau: "+f
414     # Les materiaux sont uniquement disponibles en syntaxe Python
415     # On lit le fichier et on supprime les éventuels \r
416     text=string.replace(open(f).read(),'\r\n','\n')
417     # On effectue les substitutions necessaires
418     self.text= subst_materiau(text,NOM_MATER,EXTRACTION,UNITE_LONGUEUR)
419     if INFO == 2:
420       print "INCLUDE_MATERIAU: ", self.mat,' ',NOM_MATER,'\n'
421       print self.text
422     # on execute le texte fourni dans le contexte forme par
423     # le contexte de l etape pere (global au sens Python)
424     # et le contexte de l etape (local au sens Python)
425     # Il faut auparavant l'enregistrer aupres du module linecache (utile pour nommage.py)
426     linecache.cache[f]=0,0,string.split(self.text,'\n'),f
427
428     self.postexec=post_INCLUDE
429
430     if self.jdc.par_lot == 'NON':
431       # On est en mode commande par commande, on appelle la methode speciale
432       self.Execute_alone()
433
434     self.make_contexte(f,self.text)
435     for k,v in self.g_context.items() :
436         if isinstance(v,ASSD) and k!=v.nom : del self.g_context[k]
437
438 def build_procedure(self,**args):
439     """
440     Fonction ops de la macro PROCEDURE appelée lors de la phase de Build
441     """
442     ier=0
443     # Pour presque toutes les commandes (sauf FORMULE et POURSUITE)
444     # le numero de la commande n est pas utile en phase de construction
445     # On ne numérote pas une macro PROCEDURE (incrément=None)
446     self.set_icmd(None)
447     icmd=0
448     #ier=self.codex.opsexe(self,icmd,-1,3)
449     return ier
450
451 def build_DEFI_FICHIER(self,**args):
452     """
453     Fonction ops de la macro DEFI_FICHIER
454     """
455     ier=0
456     self.set_icmd(1)
457     icmd=0
458     ier=self.codex.opsexe(self,icmd,-1,26)
459     return ier