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