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 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)
99 for fname in glob('pick.*') + glob('glob.*'):
101 UTMESS('I', 'SUPERVIS_4', valk=fname)
105 UTMESS('A', 'SUPERVIS_5', valk=fname)
107 UTMESS('I', 'SUPERVIS_6')
109 def build_debut(self,**args):
111 Fonction ops pour la macro DEBUT
113 self.jdc.UserError=self.codex.error
115 if self.jdc.par_lot == 'NON' :
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)
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
129 def POURSUITE(self, PAR_LOT, IMPR_MACRO, CODE, DEBUG, IGNORE_ALARM, LANG, INFO, **args):
131 Fonction sdprod de la macro POURSUITE
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")
137 commun_DEBUT_POURSUITE(self.jdc, PAR_LOT, IMPR_MACRO, CODE, DEBUG, IGNORE_ALARM, LANG, INFO)
139 self.jdc.set_poursuite(True)
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
153 if hasattr(self,'fichier_init'):return
154 self.fichier_init='glob.1'
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
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
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')
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)
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
194 UTMESS('I', 'SUPERVIS_65')
195 for elem, co in pickle_context.items():
196 if isinstance(co, ASSD):
198 typnam = co.__class__.__name__
199 # on rattache chaque assd au nouveau jdc courant (en poursuite)
202 # le marquer comme 'executed'
205 interrupt.append((co.nom, typnam))
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
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]
220 del pickle_context[elem]
222 UTMESS('I', 'SUPERVIS_67')
223 for nom, typnam in interrupt:
224 UTMESS('I', 'SUPERVIS_76', valk=(nom, typnam))
226 UTMESS('I', 'SUPERVIS_72')
227 if self.jdc.info_level > 1:
228 keys = pickle_context.keys()
232 value = str(pickle_context[key])
233 if len(value) > 1000:
234 value = value[:1000] + '...'
238 UTMESS('I', 'SUPERVIS_73', valk=valk)
239 self.g_context.update(pickle_context)
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
247 if hasattr(self,'fichier_init'):
249 self.make_poursuite()
251 def get_pickled_context():
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
258 if not osp.isfile(fpick):
261 # Le fichier pick.1 est présent. On essaie de récupérer les objets python sauvegardés
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
268 context = pickle.load(file)
271 # En cas d'erreur on ignore le contenu du fichier
272 traceback.print_exc()
277 def POURSUITE_context(self,d):
279 Fonction op_init de la macro POURSUITE
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
286 def build_poursuite(self,**args):
288 Fonction ops pour la macro POURSUITE
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))
294 self.jdc.UserError = self.codex.error
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'):
302 if self.jdc and self.jdc.par_lot == 'NON':
303 # On est en mode commande par commande, on appelle la methode speciale
306 fname = 'fort.%s' % UNITE
310 repdex = aster_core.get_option('repdex')
311 fname = osp.join(repdex, fname)
314 self.make_include(fname=fname)
318 self.make_include(unite=UNITE)
320 self.make_include(fname=fname)
321 except Accas.AsException:
323 UTMESS('F+', 'FICHIER_1', valk=fname)
324 UTMESS('F', 'FICHIER_2')
327 def INCLUDE_context(self,d):
328 """Fonction op_init pour macro INCLUDE"""
329 ctxt = self.g_context
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)
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)
343 def _detr_list_co(self, context):
344 """Utilitaire pour DETRUIRE"""
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
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)
368 ier = self.codex.opsexe(self, 7)
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))
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
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:
388 d[concept_racine][num] = None
389 except (ValueError, IndexError):
390 # cas : RESU_aaa ou (RESU_8 avec RESU[8] non initialisé)
392 # pour tous les concepts :
395 if self.jdc.sds_dict.has_key(nom):
396 del self.jdc.sds_dict[nom]
397 # "suppression" du concept
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é
405 def build_procedure(self,**args):
407 Fonction ops de la macro PROCEDURE appelée lors de la phase de Build
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)
414 #ier=self.codex.opsexe(self,3)
417 def build_DEFI_FICHIER(self,**args):
419 Fonction ops de la macro DEFI_FICHIER
422 ier = self.codex.opsexe(self, 26)
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))
439 texte = ''.join(VALE.splitlines())
440 elif VALE_C != None :
441 texte = ''.join(VALE_C.splitlines())
442 self.sd.setFormule(NOM_PARA, texte.strip())
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' ]
453 if TYPE == 'EXP_TRONQUEE':
454 b = self.etape['BORNE_SUP']
456 UTMESS('F', 'PROBA0_1', valr=[a, b])
457 elif moyen <= a or moyen >= b:
458 UTMESS('F', 'PROBA0_2', valr=[a, moyen, b])
460 if exp(-b * k) < 1.e-12:
461 UTMESS('F', 'PROBA0_3')
462 # résolution par point fixe
466 while abs((test - k) / k) > eps:
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':
475 UTMESS('F', 'PROBA0_4', valr=[moyen, a])
479 self.sd.valeur = a + v * x
480 elif TYPE == 'GAMMA':
481 delta = self.etape['COEF_VAR' ]
483 UTMESS('F', 'PROBA0_4', valr=[moyen, a])
485 alpha = 1. / delta**2
487 UTMESS('F', 'PROBA0_5')
490 beta = sqrt(2. * alpha - 1.)
492 f0 = 0.5 + (1. / pi) * atan2(-gamma2 / beta, 1.)
499 gamdev = beta * tan(pi * (u * c1 + c2)) + gamma2
500 unif = self.getran()[0]
502 UTMESS('F', 'PROBA0_6')
504 vref = log(1 + beta2 * ((gamdev - gamma2)**2)) \
505 + gamma2 * log(gamdev * gamm1) - gamdev + gamma2
507 UTMESS('F', 'PROBA0_7')
508 self.sd.valeur = a + v * delta**2 * gamdev