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.
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.
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
25 import cPickle as pickle
27 from math import sqrt, pi, atan2, tan, log, exp
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
41 # Si le module aster est présent, on le connecte
44 Build.B_CODE.CODE.codex=aster
46 from Utilitai.Utmess import UTMESS, MessageLog
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)
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')
61 jdc.sd_checker = CheckLog()
63 jdc.hist_etape = (DEBUG != None and DEBUG['HIST_ETAPE'] == 'OUI')
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
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
89 def DEBUT(self, PAR_LOT, IMPR_MACRO, CODE, DEBUG, IGNORE_ALARM, LANG, INFO, **args):
91 Fonction sdprod de la macro DEBUT
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)
98 for fname in glob('pick.*') + glob('glob.*'):
100 UTMESS('I', 'SUPERVIS_4', valk=fname)
104 UTMESS('A', 'SUPERVIS_5', valk=fname)
106 UTMESS('I', 'SUPERVIS_6')
108 def build_debut(self,**args):
110 Fonction ops pour la macro DEBUT
112 self.jdc.UserError=self.codex.error
114 if self.jdc.par_lot == 'NON' :
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)
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
128 def POURSUITE(self, PAR_LOT, IMPR_MACRO, CODE, DEBUG, IGNORE_ALARM, LANG, INFO, **args):
130 Fonction sdprod de la macro POURSUITE
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")
136 commun_DEBUT_POURSUITE(self.jdc, PAR_LOT, IMPR_MACRO, CODE, DEBUG, IGNORE_ALARM, LANG, INFO)
138 self.jdc.set_poursuite(True)
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
152 if hasattr(self,'fichier_init'):return
153 self.fichier_init='glob.1'
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
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
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')
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)
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
193 UTMESS('I', 'SUPERVIS_65')
194 for elem, co in pickle_context.items():
195 if isinstance(co, ASSD):
197 typnam = co.__class__.__name__
198 # on rattache chaque assd au nouveau jdc courant (en poursuite)
201 # le marquer comme 'executed'
204 interrupt.append((co.nom, typnam))
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
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]
219 del pickle_context[elem]
221 UTMESS('I', 'SUPERVIS_67')
222 for nom, typnam in interrupt:
223 UTMESS('I', 'SUPERVIS_76', valk=(nom, typnam))
225 UTMESS('I', 'SUPERVIS_72')
226 if self.jdc.info_level > 1:
227 keys = pickle_context.keys()
231 value = str(pickle_context[key])
232 if len(value) > 1000:
233 value = value[:1000] + '...'
237 UTMESS('I', 'SUPERVIS_73', valk=valk)
238 self.g_context.update(pickle_context)
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
246 if hasattr(self,'fichier_init'):
248 self.make_poursuite()
250 def get_pickled_context():
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
257 if not osp.isfile(fpick):
260 # Le fichier pick.1 est présent. On essaie de récupérer les objets python sauvegardés
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
267 context = pickle.load(file)
270 # En cas d'erreur on ignore le contenu du fichier
271 traceback.print_exc()
276 def POURSUITE_context(self,d):
278 Fonction op_init de la macro POURSUITE
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
285 def build_poursuite(self,**args):
287 Fonction ops pour la macro POURSUITE
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))
293 self.jdc.UserError = self.codex.error
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'):
301 if self.jdc and self.jdc.par_lot == 'NON':
302 # On est en mode commande par commande, on appelle la methode speciale
305 fname = 'fort.%s' % UNITE
309 repdex = aster_core.get_option('repdex')
310 fname = osp.join(repdex, fname)
313 self.make_include(fname=fname)
317 self.make_include(unite=UNITE)
319 self.make_include(fname=fname)
320 except Accas.AsException:
322 UTMESS('F+', 'FICHIER_1', valk=fname)
323 UTMESS('F', 'FICHIER_2')
326 def INCLUDE_context(self,d):
327 """Fonction op_init pour macro INCLUDE"""
328 ctxt = self.g_context
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)
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)
342 def _detr_list_co(self, context):
343 """Utilitaire pour DETRUIRE"""
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
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)
367 ier = self.codex.opsexe(self, 7)
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))
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
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:
387 d[concept_racine][num] = None
388 except (ValueError, IndexError):
389 # cas : RESU_aaa ou (RESU_8 avec RESU[8] non initialisé)
391 # pour tous les concepts :
394 if self.jdc.sds_dict.has_key(nom):
395 del self.jdc.sds_dict[nom]
396 # "suppression" du concept
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é
404 def build_procedure(self,**args):
406 Fonction ops de la macro PROCEDURE appelée lors de la phase de Build
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)
413 #ier=self.codex.opsexe(self,3)
416 def build_DEFI_FICHIER(self,**args):
418 Fonction ops de la macro DEFI_FICHIER
421 ier = self.codex.opsexe(self, 26)
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))
438 texte = ''.join(VALE.splitlines())
439 elif VALE_C != None :
440 texte = ''.join(VALE_C.splitlines())
441 self.sd.setFormule(NOM_PARA, texte.strip())
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' ]
452 if TYPE == 'EXP_TRONQUEE':
453 b = self.etape['BORNE_SUP']
455 UTMESS('F', 'PROBA0_1', valr=[a, b])
456 elif moyen <= a or moyen >= b:
457 UTMESS('F', 'PROBA0_2', valr=[a, moyen, b])
459 if exp(-b * k) < 1.e-12:
460 UTMESS('F', 'PROBA0_3')
461 # résolution par point fixe
465 while abs((test - k) / k) > eps:
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':
474 UTMESS('F', 'PROBA0_4', valr=[moyen, a])
478 self.sd.valeur = a + v * x
479 elif TYPE == 'GAMMA':
480 delta = self.etape['COEF_VAR' ]
482 UTMESS('F', 'PROBA0_4', valr=[moyen, a])
484 alpha = 1. / delta**2
486 UTMESS('F', 'PROBA0_5')
489 beta = sqrt(2. * alpha - 1.)
491 f0 = 0.5 + (1. / pi) * atan2(-gamma2 / beta, 1.)
498 gamdev = beta * tan(pi * (u * c1 + c2)) + gamma2
499 unif = self.getran()[0]
501 UTMESS('F', 'PROBA0_6')
503 vref = log(1 + beta2 * ((gamdev - gamma2)**2)) \
504 + gamma2 * log(gamdev * gamm1) - gamdev + gamma2
506 UTMESS('F', 'PROBA0_7')
507 self.sd.valeur = a + v * delta**2 * gamdev