]> SALOME platform Git repositories - tools/eficas.git/blob - Aster/Cata/cataSTA11/ops.py
Salome HOME
menage
[tools/eficas.git] / Aster / Cata / cataSTA11 / ops.py
1 # coding=utf-8
2 # ======================================================================
3 # COPYRIGHT (C) 1991 - 2013  EDF R&D                  WWW.CODE-ASTER.ORG
4 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
5 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
6 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
7 # (AT YOUR OPTION) ANY LATER VERSION.
8 #
9 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
10 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
11 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
12 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.
13 #
14 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
15 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
16 #    1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
17 # ======================================================================
18 # person_in_charge: mathieu.courtois at edf.fr
19
20 # Modules Python
21 import sys
22 import os
23 import os.path as osp
24 import traceback
25 import cPickle as pickle
26 import re
27 from math import sqrt, pi, atan2, tan, log, exp
28 from glob import glob
29
30 # Modules Eficas
31 import Accas
32 from Accas import ASSD
33 from Noyau.ascheckers     import CheckLog
34 from Noyau.N_info import message, SUPERV
35 from Noyau.N_types import force_list
36
37 try:
38    import aster
39    import aster_core
40    aster_exists = True
41    # Si le module aster est présent, on le connecte
42    # au JDC
43    import Build.B_CODE
44    Build.B_CODE.CODE.codex=aster
45
46    from Utilitai.Utmess   import UTMESS, MessageLog
47 except:
48    aster_exists = False
49
50
51
52 def commun_DEBUT_POURSUITE(jdc, PAR_LOT, IMPR_MACRO, CODE, DEBUG, IGNORE_ALARM, LANG, INFO):
53    """Fonction sdprod partie commune à DEBUT et POURSUITE.
54    (on stocke un entier au lieu du logique)
55    """
56    jdc.set_par_lot(PAR_LOT, user_value=True)
57    jdc.impr_macro = int(IMPR_MACRO == 'OUI')
58    jdc.jxveri     = int(CODE != None or (DEBUG != None and DEBUG['JXVERI'] == 'OUI'))
59    jdc.sdveri     = int(DEBUG != None and DEBUG['SDVERI'] == 'OUI')
60    jdc.fico       = None
61    jdc.sd_checker = CheckLog()
62    jdc.info_level = INFO
63    jdc.hist_etape = (DEBUG != None and DEBUG['HIST_ETAPE'] == 'OUI')
64    if CODE != None:
65       jdc.fico = 'TEST'
66    if aster_exists:
67       if LANG:
68          from Execution.i18n import localization
69          localization.install(LANG)
70       # pb en cas d'erreur dans FIN : appeler reset_print_function dans traiter_fin_exec ?
71       #from functools import partial
72       #asprint = partial(aster.affiche, 'MESSAGE')
73       #message.register_print_function(asprint)
74       # ne faire qu'une fois
75       if not hasattr(jdc, 'msg_init'):
76          # messages d'alarmes désactivés
77          if IGNORE_ALARM:
78             if not type(IGNORE_ALARM) in (list, tuple):
79                IGNORE_ALARM = [IGNORE_ALARM]
80             for idmess in IGNORE_ALARM:
81                MessageLog.disable_alarm(idmess)
82       # en POURSUITE, conserver le catalogue de comportement picklé
83       if not hasattr(jdc, 'catalc'):
84          from Comportement import catalc
85          jdc.catalc = catalc
86       jdc.msg_init = True
87
88
89 def DEBUT(self, PAR_LOT, IMPR_MACRO, CODE, DEBUG, IGNORE_ALARM, LANG, INFO, **args):
90     """
91        Fonction sdprod de la macro DEBUT
92     """
93     # La commande DEBUT ne peut exister qu'au niveau jdc
94     if self.jdc is not self.parent :
95         raise Accas.AsException("La commande DEBUT ne peut exister qu'au niveau jdc")
96     commun_DEBUT_POURSUITE(self.jdc, PAR_LOT, IMPR_MACRO, CODE, DEBUG, IGNORE_ALARM, LANG, INFO)
97     suppr = False
98     for fname in glob('pick.*') + glob('glob.*'):
99         try:
100             UTMESS('I', 'SUPERVIS_4', valk=fname)
101             os.remove(fname)
102             suppr = True
103         except OSError:
104             UTMESS('A', 'SUPERVIS_5', valk=fname)
105     if suppr:
106         UTMESS('I', 'SUPERVIS_6')
107
108 def build_debut(self,**args):
109    """
110    Fonction ops pour la macro DEBUT
111    """
112    self.jdc.UserError=self.codex.error
113
114    if self.jdc.par_lot == 'NON' :
115       self.jdc._Build()
116    # On execute la fonction debut pour initialiser les bases
117    # Cette execution est indispensable avant toute autre action sur ASTER
118    # op doit être un entier car la fonction debut appelle GCECDU qui demande
119    # le numéro de l'operateur associé (getoper)
120    self.definition.op=0
121    self.set_icmd(1)
122    self.codex.debut(self)
123    # On remet op a None juste apres pour eviter que la commande DEBUT
124    # ne soit executée dans la phase d'execution
125    self.definition.op=None
126    return 0
127
128 def POURSUITE(self, PAR_LOT, IMPR_MACRO, CODE, DEBUG, IGNORE_ALARM, LANG, INFO, **args):
129    """
130        Fonction sdprod de la macro POURSUITE
131    """
132    # La commande POURSUITE ne peut exister qu'au niveau jdc
133    if self.jdc is not self.parent :
134       raise Accas.AsException("La commande POURSUITE ne peut exister qu'au niveau jdc")
135
136    commun_DEBUT_POURSUITE(self.jdc, PAR_LOT, IMPR_MACRO, CODE, DEBUG, IGNORE_ALARM, LANG, INFO)
137    if aster_exists:
138        self.jdc.set_poursuite(True)
139
140    if self.codex:
141      base = 'glob.1'
142      if aster_exists:
143         repglob = aster_core.get_option("repglob")
144         bhdf = osp.join(repglob, 'bhdf.1')
145         base = osp.join(repglob, 'glob.1')
146         if not osp.isfile(base) and not osp.isfile(bhdf):
147             UTMESS('F','SUPERVIS_89')
148      # Le module d'execution est accessible et glob.1 est present
149      # Pour eviter de rappeler plusieurs fois la sequence d'initialisation
150      # on memorise avec l'attribut fichier_init que l'initialisation
151      # est réalisée
152      if hasattr(self,'fichier_init'):return
153      self.fichier_init='glob.1'
154      self.jdc.initexec()
155      # le sous programme fortran appelé par self.codex.poursu demande le numéro
156      # de l'operateur (GCECDU->getoper), on lui donne la valeur 0
157      self.definition.op=0
158      self.codex.poursu(self)
159      # Par la suite pour ne pas executer la commande pendant la phase
160      # d'execution on le remet à None
161      self.definition.op = None
162      self.g_context = {}
163
164      # Il peut exister un contexte python sauvegardé sous forme  pickled
165      # On récupère ces objets après la restauration des concepts pour que
166      # la récupération des objets pickled soit prioritaire.
167      # On vérifie que les concepts relus dans glob.1 sont bien tous
168      # presents sous le même nom et du même type dans pick.1
169      # Le contexte est ensuite updaté (surcharge) et donc enrichi des
170      # variables qui ne sont pas des concepts.
171      # On supprime du pickle_context les concepts valant None, ca peut
172      # être le cas des concepts non executés, placés après FIN.
173      UTMESS('I', 'SUPERVIS2_1', valk='pick.1')
174      pickle_context = get_pickled_context()
175      if pickle_context == None:
176         UTMESS('F', 'SUPERVIS_86')
177         return
178      self.jdc.restore_pickled_attrs(pickle_context)
179      # vérification cohérence pick/base
180      savsign = self.jdc._sign
181      newsign = self.jdc.signature(base)
182      if args.get('FORMAT_HDF') == 'OUI':
183          UTMESS('I', 'SUPERVIS_71')
184      elif newsign != savsign:
185          UTMESS('A', 'SUPERVIS_69', valk=(savsign, newsign),
186                                     vali=self.jdc.jeveux_sysaddr)
187      else:
188          UTMESS('I', 'SUPERVIS_70', valk=newsign, vali=self.jdc.jeveux_sysaddr)
189      from Cata.cata  import entier
190      from Noyau.N_CO import CO
191      interrupt = []
192      count = 0
193      UTMESS('I', 'SUPERVIS_65')
194      for elem, co in pickle_context.items():
195          if isinstance(co, ASSD):
196             count += 1
197             typnam = co.__class__.__name__
198             # on rattache chaque assd au nouveau jdc courant (en poursuite)
199             co.jdc = self.jdc
200             co.parent = self.jdc
201             # le marquer comme 'executed'
202             i_int = ''
203             if co.executed != 1:
204                 interrupt.append((co.nom, typnam))
205                 i_int = 'exception'
206             co.executed = 1
207             UTMESS('I', 'SUPERVIS_66', valk=(co.nom, typnam.lower(), i_int))
208             # pour que sds_dict soit cohérent avec g_context
209             self.jdc.sds_dict[elem] = co
210             if elem != co.nom:
211                name = re.sub('_([0-9]+)$', '[\\1]', co.nom)
212                if self.jdc.info_level > 1:
213                   UTMESS('I', 'SUPERVIS2_3',
214                          valk=(elem, type(co).__name__.upper()))
215                UTMESS('A', 'SUPERVIS_93', valk=(elem, "del %s" % name))
216                del pickle_context[elem]
217                continue
218          if co == None:
219             del pickle_context[elem]
220      if count == 0:
221          UTMESS('I', 'SUPERVIS_67')
222      for nom, typnam in interrupt:
223          UTMESS('I', 'SUPERVIS_76', valk=(nom, typnam))
224      if not interrupt:
225          UTMESS('I', 'SUPERVIS_72')
226      if self.jdc.info_level > 1:
227          keys = pickle_context.keys()
228          keys.sort()
229          for key in keys:
230              try:
231                  value = str(pickle_context[key])
232                  if len(value) > 1000:
233                      value = value[:1000] + '...'
234                  valk = key, value
235              except:
236                  valk = key, '...'
237              UTMESS('I', 'SUPERVIS_73', valk=valk)
238      self.g_context.update(pickle_context)
239      return
240
241    else:
242      # Si le module d'execution n est pas accessible ou glob.1 absent on
243      # demande un fichier (EFICAS)
244      # Il faut éviter de réinterpréter le fichier à chaque appel de
245      # POURSUITE
246      if hasattr(self,'fichier_init'):
247         return
248      self.make_poursuite()
249
250 def get_pickled_context():
251     """
252        Cette fonction permet de réimporter dans le contexte courant du jdc (jdc.g_context)
253        les objets python qui auraient été sauvegardés, sous forme pickled, lors d'une
254        précédente étude. Un fichier pick.1 doit être présent dans le répertoire de travail
255     """
256     fpick = 'pick.1'
257     if not osp.isfile(fpick):
258        return None
259
260     # Le fichier pick.1 est présent. On essaie de récupérer les objets python sauvegardés
261     context={}
262     try:
263        file=open(fpick, 'rb')
264        # Le contexte sauvegardé a été picklé en une seule fois. Il est seulement
265        # possible de le récupérer en bloc. Si cette opération echoue, on ne récupère
266        # aucun objet.
267        context = pickle.load(file)
268        file.close()
269     except:
270        # En cas d'erreur on ignore le contenu du fichier
271        traceback.print_exc()
272        return None
273
274     return context
275
276 def POURSUITE_context(self,d):
277    """
278        Fonction op_init de la macro POURSUITE
279    """
280    # self représente la macro POURSUITE ...
281    d.update(self.g_context)
282    # Une commande POURSUITE n'est possible qu'au niveau le plus haut
283    # On ajoute directement les concepts dans le contexte du jdc
284
285 def build_poursuite(self,**args):
286    """
287    Fonction ops pour la macro POURSUITE
288    """
289    # Pour POURSUITE on ne modifie pas la valeur initialisee dans ops.POURSUITE
290    # Il n y a pas besoin d executer self.codex.poursu (c'est deja fait dans
291    # la fonction sdprod de la commande (ops.POURSUITE))
292    self.set_icmd(1)
293    self.jdc.UserError = self.codex.error
294    return 0
295
296 def INCLUDE(self, UNITE, DONNEE, **args):
297     """Fonction sd_prod pour la macro INCLUDE"""
298     if not (UNITE or DONNEE) or hasattr(self, '_mark'):
299         return
300     self._mark = 1
301     if self.jdc and self.jdc.par_lot == 'NON':
302         # On est en mode commande par commande, on appelle la methode speciale
303         self.Execute_alone()
304     if UNITE:
305         fname = 'fort.%s' % UNITE
306     else:
307         fname = DONNEE
308         if aster_exists:
309             repdex = aster_core.get_option('repdex')
310             fname = osp.join(repdex, fname)
311     try:
312         if aster_exists:
313             self.make_include(fname=fname)
314         else:
315             # dans eficas
316             if UNITE:
317                 self.make_include(unite=UNITE)
318             else:
319                 self.make_include(fname=fname)
320     except Accas.AsException:
321         if aster_exists:
322             UTMESS('F+', 'FICHIER_1', valk=fname)
323             UTMESS('F', 'FICHIER_2')
324         raise
325
326 def INCLUDE_context(self,d):
327     """Fonction op_init pour macro INCLUDE"""
328     ctxt = self.g_context
329     d.update(ctxt)
330
331 def build_include(self,**args):
332     """Fonction ops de la macro INCLUDE appelée lors de la phase de Build"""
333     # Pour presque toutes les commandes (sauf FORMULE et POURSUITE)
334     # le numéro de la commande n est pas utile en phase de construction
335     # La macro INCLUDE ne sera pas numérotée (incrément=None)
336     ier=0
337     self.set_icmd(None)
338     # On n'execute pas l'ops d'include en phase BUILD car il ne sert a rien.
339     #ier=self.codex.opsexe(self,1)
340     return ier
341
342 def _detr_list_co(self, context):
343     """Utilitaire pour DETRUIRE"""
344     list_co = set()
345     # par nom de concept (typ=assd)
346     for mc in self['CONCEPT'] or []:
347         list_co.update(force_list(mc["NOM"]))
348     # par chaine de caractères (typ='TXM')
349     for mc in self['OBJET'] or []:
350         # longueur <= 8, on cherche les concepts existants
351         for nom in force_list(mc['CHAINE']):
352             assert type(nom) in (str, unicode), 'On attend une chaine de caractères : %s' % nom
353             if len(nom.strip()) <= 8:
354                 if self.jdc.sds_dict.get(nom) != None:
355                     list_co.add(self.jdc.sds_dict[nom])
356                 elif context.get(nom) != None:
357                     list_co.add(context[nom])
358             #else uniquement destruction des objets jeveux
359     return list_co
360
361 def DETRUIRE(self, CONCEPT, OBJET, **args):
362    """Fonction OPS pour la macro DETRUIRE : exécution réelle."""
363    # pour les formules, il ne faut pas vider l'attribut "parent_context" trop tôt
364    for co in _detr_list_co(self, {}):
365        co.supprime(force=True)
366    self.set_icmd(1)
367    ier = self.codex.opsexe(self, 7)
368    return ier
369
370 def build_detruire(self, d):
371    """Fonction op_init de DETRUIRE."""
372    # d est le g_context du jdc ou d'une macro
373    #message.debug(SUPERV, "id(d) : %s", id(d))
374    for co in _detr_list_co(self, d):
375       assert isinstance(co, ASSD), 'On attend un concept : %s (type=%s)' % (co, type(co))
376       nom = co.nom
377       #message.debug(SUPERV, "refcount_1(%s) = %d", nom, sys.getrefcount(co))
378       # traitement particulier pour les listes de concepts, on va mettre à None
379       # le terme de l'indice demandé dans la liste :
380       # nomconcept_i est supprimé, nomconcept[i]=None
381       i = nom.rfind('_')
382       if i > 0 and not nom.endswith('_'):
383          concept_racine = nom[:i]
384          if d.has_key(concept_racine) and type(d[concept_racine]) is list:
385             try:
386                num = int(nom[i+1:])
387                d[concept_racine][num] = None
388             except (ValueError, IndexError):
389                # cas : RESU_aaa ou (RESU_8 avec RESU[8] non initialisé)
390                pass
391       # pour tous les concepts :
392       if d.has_key(nom):
393          del d[nom]
394       if self.jdc.sds_dict.has_key(nom):
395          del self.jdc.sds_dict[nom]
396       # "suppression" du concept
397       co.supprime()
398       # On signale au parent que le concept n'existe plus après l'étape self
399       self.parent.delete_concept_after_etape(self, co)
400       # marque comme détruit == non executé
401       co.executed = 0
402
403
404 def build_procedure(self,**args):
405     """
406     Fonction ops de la macro PROCEDURE appelée lors de la phase de Build
407     """
408     ier=0
409     # Pour presque toutes les commandes (sauf FORMULE et POURSUITE)
410     # le numéro de la commande n est pas utile en phase de construction
411     # On ne numérote pas une macro PROCEDURE (incrément=None)
412     self.set_icmd(None)
413     #ier=self.codex.opsexe(self,3)
414     return ier
415
416 def build_DEFI_FICHIER(self,**args):
417     """
418     Fonction ops de la macro DEFI_FICHIER
419     """
420     self.set_icmd(1)
421     ier = self.codex.opsexe(self, 26)
422     return ier
423
424 def build_formule(self, d):
425     """Fonction ops de FORMULE."""
426     NOM_PARA = self.etape['NOM_PARA'] or ''
427     VALE = self.etape['VALE']
428     VALE_C = self.etape['VALE_C']
429     if type(NOM_PARA) not in (list, tuple):
430         NOM_PARA = [NOM_PARA, ]
431     for para in NOM_PARA:
432         if para.strip() != para:
433             raise Accas.AsException("nom de paramètre invalide (contient des blancs)" \
434                " : %s" % repr(para))
435     if self.sd == None:
436         return
437     if VALE != None :
438         texte = ''.join(VALE.splitlines())
439     elif VALE_C != None :
440         texte = ''.join(VALE_C.splitlines())
441     self.sd.setFormule(NOM_PARA, texte.strip())
442
443 def build_gene_vari_alea(self, d):
444     """Fonction ops de la macro GENE_VARI_ALEA."""
445     from Utilitai.Utmess import UTMESS
446     a = self.etape['BORNE_INF']
447     moyen = self.etape['VALE_MOY' ]
448     TYPE = self.etape['TYPE']
449     if self['INIT_ALEA'] is not None:
450         jump = self.etape['INIT_ALEA' ]
451         self.iniran(jump)
452     if TYPE == 'EXP_TRONQUEE':
453         b = self.etape['BORNE_SUP']
454         if a >= b:
455             UTMESS('F', 'PROBA0_1', valr=[a, b])
456         elif moyen <= a or moyen >= b:
457             UTMESS('F', 'PROBA0_2', valr=[a, moyen, b])
458         k = 1. / (moyen - a)
459         if exp(-b * k) < 1.e-12:
460             UTMESS('F', 'PROBA0_3')
461         # résolution par point fixe
462         eps = 1.E-4
463         nitmax = 100000
464         test = 0.
465         while abs((test - k) / k) > eps:
466             test = k
467             k = 1. / (moyen - (a * exp(-a * k) - b * exp(-b * k)) / \
468                                (exp(-a * k) - exp(-b * k)))
469         # génération de la variable aléatoire
470         alpha = exp(-a * k) - exp(-b * k)
471         self.sd.valeur = -(log(exp(-a * k) - alpha * self.getran()[0])) / k
472     elif TYPE == 'EXPONENTIELLE':
473        if moyen <= a:
474           UTMESS('F', 'PROBA0_4', valr=[moyen, a])
475        v = moyen - a
476        u = self.getran()[0]
477        x = -log(1 - u)
478        self.sd.valeur = a + v * x
479     elif TYPE == 'GAMMA':
480        delta = self.etape['COEF_VAR' ]
481        if moyen <= a:
482           UTMESS('F', 'PROBA0_4', valr=[moyen, a])
483        v = moyen - a
484        alpha = 1. / delta**2
485        if alpha <= 1.:
486           UTMESS('F', 'PROBA0_5')
487        gamma2 = alpha - 1.
488        gamm1 = 1. / gamma2
489        beta = sqrt(2. * alpha - 1.)
490        beta2 = 1. / beta**2
491        f0 = 0.5 + (1. / pi) * atan2(-gamma2 / beta, 1.)
492        c1 = 1. - f0
493        c2 = f0 - 0.5
494        vref = 0.
495        vv     = -1.
496        while -vv > vref:
497           u = self.getran()[0]
498           gamdev = beta * tan(pi * (u * c1 + c2)) + gamma2
499           unif = self.getran()[0]
500           if unif < 0.:
501              UTMESS('F', 'PROBA0_6')
502           vv = -log(unif)
503           vref = log(1 + beta2 * ((gamdev - gamma2)**2)) \
504                + gamma2 * log(gamdev * gamm1) - gamdev + gamma2
505        if vv <= 0.:
506           UTMESS('F', 'PROBA0_7')
507        self.sd.valeur = a + v * delta**2 * gamdev