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