8. Utilitaires de levée d’exception#
En cours d’écriture
Les utilitaires UTEXCP et UTEXCM permettent de lever une exception python depuis le fortran et de la transmettre au jeu de commande. Cette exception peut être récupérée dans le fichier de commande (ou une macro-commande) par un bloc try/except.
Les exceptions étant des cas particuliers d’erreur <F>, si elles ne sont pas récupérées, le superviseur termine le calcul comme après une erreur <F> ordinaire (fermeture et recopie de la base). Seule l’exception FatalError échappe à la règle puisqu’elle équivaut à une erreur <F> (et encore on verra un peu plus loin que ce comportement est modifiable).
Le mécanisme d’exception permet d’essayer une commande puis de reprendre la main si celle-ci échoue en levant une exception particulière.
Ce fonctionnement est particulièrement utilisé dans les macro-commandes, soit pour se comporter différemment selon le contexte, soit pour émettre un message plus parlant à l’utilisateur que celui qui aurait été émis par une commande fille.
Remarque:
L’utilisation des exceptions et surtout des blocs try / except n’a de sens qu’en mode PAR_LOT=’NON’
8.1. Mise en œuvre dans le source#
On présente ici la mise en œuvre du mécanisme des exceptions dans le source fortran et python du point de vue du développeur. On abordera un peu plus bas les exceptions avec la vision “utilisateur” (§ 8.4 ).
Pour la description de ce qu’est une exception, les mécanismes de levée (raise) et d’interception (except), on se reportera à la Description des exceptions du Tutorial Python.
“Lever une exception” signifie émettre un signal avec (souvent) des éléments de contexte pour permettre au programme appelant de réagir ainsi :
je comprends le signal et je prends telle décision en conséquence
je ne comprends pas le signal et je m’arrête (en émettant un autre signal au programme appelant du niveau supérieur)
j’ignore le signal et je laisse le programme appelant du niveau supérieur traiter le signal
Et ainsi de suite, sachant qu’au plus haut, c’est l’interpréteur Python lui-même qui prendra la décision d’interrompre l’exécution.
Syntaxiquement et schématiquement, le fonctionnement est le suivant :
try:
...
Instructions à exécuter qui peuvent par exemple lever 3 exceptions
différentes : UneExceptionParticulière, UneAutreException, EncoreUneAutre
...
except UneExceptionParticulière, arguments:
...
On exécutera ces instructions si l'exception "UneExceptionParticulière" est levée. On peut utiliser les "arguments" utilisés lors de la levée de l'exception.
Dans le cas le plus simple (et fréquent), "arguments" est un message qui peut être imprimé avec "print" ou utilisé comme chaîne de caractères avec "str(arguments)".
...
except UneAutreException, arguments2:
...
Instructions à exécuter si l'exception UneAutreException est levée.
...
Supposons que le bloc d’instructions sous le try lève l’exception EncoreUneAutre (qui n’est pas interceptée par un bloc except), l’exécution s’arrête avec un message du type :
Traceback (most recent call last):
File ".......", line 3, in <.......> <<< permet de dire où s'est produite l'exception
EncoreUneAutre: ...... <<< éléments de contexte (arguments) fournissant
des détails sur les raisons de la levée d’exception
Pour les autres mécanismes, try/finally ou try/except/else, on se reportera à la documentation Python.
8.1.1. Levée d’exception dans Code_Aster#
Le plus simple : en Python, c’est-à-dire dans le fichier de commandes ou dans une macro-commande, il suffit de faire :
if nbre_iterations > nbre_maxi_autorise:
raise aster.NonConvergenceError, "Absence de convergence avec le nombre d'itérations autorisé"
Dans le source fortran (exemple dans nmerro.f qui traite les erreurs dans STAT_NON_LINE) :
...
ELSE IF (ITEMAX) THEN
CALL UTEXCP(22,'MECANONLINE_83')
...
où
22 est le numéro de l’exception
‘MECANONLINE_83’ est l’identifiant du message à imprimer
En effet, les exceptions propres à Code_Aster sont numérotées pour être accessibles facilement depuis le fortran :
numéro de l’exception |
Description |
Nom de l’exception dans le module aster |
Type erreur |
20 |
Erreur fatale |
FatalError |
F |
21 |
Erreur non fatale |
error |
F |
22 |
Non convergence |
NonConvergenceError |
F |
23 |
Echec intégration du comportement |
EchecComportementError |
F |
24 |
Bande de fréquence vide |
BandeFrequenceVideError |
F |
25 |
Matrice singulière |
MatriceSinguliereError |
F |
26 |
Echec de traitement du contact |
TraitementContactError |
F |
27 |
Matrice de contact non inversible |
MatriceContactSinguliereError |
F |
28 |
Manque de temps CPU |
ArretCPUError |
F |
29 |
Echec du pilotage |
PilotageError |
F |
Remarques
Les exceptions sont définies dans le module aster (astermodule.c). Ainsi, on y accède par aster.error.
A part FatalError, toutes les exceptions dérivent de errorqui représente donc l’enveloppe des erreurs <F>.
Le comportement en cas d’erreur fatale (FatalError ) est modifiable par l’utilisateur [U1.03.01], ce choix est déterminé dans les commande DEBUT/POURSUITE [U4.11.01],[U4.11.03] mot-clé facteur ERREUR_F. Dans les macro-commandes, on utilisera la fonction aster.onFatalError(arg)pour modifier ce comportement.
8.2. Levée d’une exception avec impression d’un message#
CALL UTEXCP( CODE, IDMESS )
CODE |
IN |
Numéro de l’exception |
IDMESS |
IN |
Identificateur du message |
Exemple :
CALL UTEXCP(23,”CHATON_7”)
8.3. Levée d’exception avec impression de messages et de valeurs de type caractères, entières et réelles#
CALL UTEXCM( CODE, IDMESS, NK, VALK, NI, VALI, NR, VALR)
CODE |
IN |
numéro de l’exception |
IDMESS |
IN |
Identificateur du message |
NK |
IN |
Nombre de paramètres de type caractère |
VALK |
IN |
Valeurs des paramètres de type caractère |
NI |
IN |
Nombre de paramètres de type entier |
VALI |
IN |
Valeurs des paramètres de type entier |
NR |
IN |
Nombre de paramètres de type réel |
VALR |
IN |
Valeurs des paramètres de type réel |
Exemple :
VALI (1) = NDIM1
VALI (2) = NDIM2
VALR = 5.D0
CALL UTEXCM(24,'CHATON_12', 0,' ',2, VALI,1,VALR)
8.4. Exemple d’utilisation#
Dans cet exemple, on souhaite :
en cas de non-convergence de STAT_NON_LINE, relancer les calculs en augmentant le nombre d’itérations,
arrêter les calculs si une autre erreur se produit.
Cette utilisation est illustrée dans le cas-test ssnp125a.
Programmation
On lève l’exception NonConvergenceError qui porte le numéro 22 :
...
ELSE IF ((.NOT.CONVER) .AND. ITEMAX .AND. (.NOT.ARRET)) THEN
ITAB(1) = NUMORD
ITAB(2) = ITERAT
CALL UTEXCM(22,'MECANONLINE_85', 0, K8B, 2, ITAB, 0, RTAB)
END IF
Fichier de commande
try :
STATNL=STAT_NON_LINE(...)
except aster.NonConvergenceError, message:
# non convergence
print "on continue en augmentant le nombre d'itérations"
STATNL=STAT_NON_LINE(reuse=STATNL,
...
CONVERGENCE=_F(ITER_GLOB_MAXI=400,)
…)
Fichier message : mecanonline.py
85 : _(u"""
Arret : absence de convergence au numéro d'instant : %(i1)d
lors de l'itération : %(i2)d
"""),
Message imprimé
!-----------------------------------------------------------------------!
! <EXCEPTION> <MECANONLINE_85> !
! !
! !
! Arret : absence de convergence au numéro d'instant : 123 !
! lors de l'itération : 51 !
! !
! !
!-----------------------------------------------------------------------!