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