4. Autres outils#

Dans cette partie, on décrit quelques outils qui permettent aussi de trouver des bugs ou de débusquer des comportements anormaux:

  • Option “-Checkbounds” des compilateurs

  • Comparaison de 2 versions différentes de Code_Aster

4.1. Dépassement de tableaux ( -CheckBounds)#

Les compilateurs disposent d’outils permettant d’instrumenter le code pour détecter des dépassements de tableaux statiques (un des types de bugs difficiles à trouver en Fortran).

Pour utiliser ces fonctionnalités, il faut recompiler les routines suspectes avec ces options (il faut pour cela modifier le config.txt et le mettre en Donnée dans l’onglet Surcharge) puis exécuter le code. Si un dépassement survient, une erreur fatale avec un message se produira.

Syntaxe :Gcc (g77) : -fbounds-check Intel (ifort) : -CB

Remarques :

Les routines utilisant les COMMONJEVEUX (ZI, ZR, …)ne peuvent pas être compilées avec -CBcar alors l’exécution s’arrête rapidement du fait du débordement du tableau ZI(1).

Du coup, l’utilisation de -CBest un peu compliquée : il faut jongler avec 2 fichiers config.txtet conserver les fichiers .o.

L’intérêt de -CBn’est pas énorme car ce mécanisme ne détecte pas tous les écrasements de tableaux. Pour que l’écrasement soit détecté, il faut que le tableau soit local (donc dimensionné en “dur”), ou bien que ce soit un tableau argument déclaré avec sa longueur exacte (et nom pas TAB()). L’autre intérêt de -CBest la détection des écrasements des chaines de caractères car en fortran la longueur d’une chaine est attachée à la chaine. C’est pour cela que l’on peut faire len(chaine)sur une chaine que l’on a reçue en argument (alors que l’on ne peut pas faire len(TAB)).*

Gcc (g77) : -fbounds-check


-fbounds-check
-ffortran-bounds-check

Enable generation of run-time checks for array subscripts and substring start and end points against the (locally) declared minimum and maximum values.

The current implementation uses the « libf2c » library routine « s_rnge » to print the diagnostic.

However, whereas f2c generates a single check per reference for a multi-dimensional array, of the computed offset against the valid offset range (0 through the size of the array), g77 generates a single check per sub‐ script expression. This catches some cases of potential bugs that f2c does not, such as references to below the beginning of an assumed-size array.

g77 also generates checks for « CHARACTER » substring references, something f2c currently does not do.

Use the new -ffortran-bounds-check option to specify bounds-checking for only the Fortran code you are compiling, not necessarily for code written in other languages.

Note: To provide more detailed information on the offending subscript, g77 provides the « libg2c » run-time library routine « s_rnge » with somewhat differently-formatted information. Here’s a sample diagnostic:

Subscript out of range on file line 4, procedure rnge.F90/bf.

Attempt to access the -6-th element of variable b[subscript-2-of-2].

Aborted

The above message indicates that the offending source line is line 4 of the file rnge.F90, within the program unit (or statement function) named bf. The offended array is named b. The offended array dimension is the second for a two-dimensional array, and the offending, computed subscript expression was -6.

For a « CHARACTER » substring reference, the second line has this appearance:Attempt to access the 11-th element of variable a[start-substring].

This indicates that the offended « CHARACTER » variable or array is named a, the offended substring position is the starting (leftmost) position, and the offending substring expression is 11.

(Though the verbage of « s_rnge » is not ideal for the purpose of the g77 compiler, the above information should provide adequate diagnostic abilities to it users.)

Some of these do not work when compiling programs written in Fortran:

Intel (ifort) : -CB

-CB Performs run-time checks on whether array subscript and

substring references are within declared bounds

(same as the -check bounds option).

Exemple de détection d’erreur :

forrtl: severe (408): fort: (2): Subscript #1 of the array RESU

has value 4 which is greater than the upper bound of 3


Image PC Routine Line Source

asteru_jpl 0000000001F9E956 Unknown Unknown Unknown

asteru_jpl 0000000001F9DB56 Unknown Unknown Unknown

asteru_jpl 0000000001F11232 Unknown Unknown Unknown

asteru_jpl 0000000001EDA0E2 Unknown Unknown Unknown

asteru_jpl 0000000001ED9068 Unknown Unknown Unknown

asteru_jpl 00000000004933AE mkkvec_ 52 mkkvec.F90

asteru_jpl 0000000000493AD0 mmmab2_ 40 mmmab2_jpl.F90

asteru_jpl 0000000000E6A639 te0364_ 370 te0364.F90

asteru_jpl 0000000000910304 te0000_ 1261 te0000.F90

asteru_jpl 0000000000613998 calcul_ 472 calcul.F90

asteru_jpl 0000000000EE74A0 mmcmat_ 149 mmcmat.F90

asteru_jpl 0000000000D9F12F mmcmem_ 69 mmcmem.F90

asteru_jpl 00000000009D308F nmdepl_ 300 nmdepl.F90

asteru_jpl 00000000007A4EA8 op0070_ 304 op0070.F90

asteru_jpl 0000000000599772 ex0000_ 258 ex0000.F90

asteru_jpl 00000000004E6750 execop_ 90 execop.F90

asteru_jpl 00000000004D26EE expass_ 82 expass.F90

asteru_jpl 0000000000499BD7 aster_oper 2635 astermodule.c

4.2. Comparaison de 2 versions différentes de Code_Aster#

Il arrive parfois que deux exécutions différentes de Code_Aster conduisent à des résultats différents.

Cela peut se produire :

  • Avec la même version du code sur deux plateformes différentes.

  • Avec deux versions différentes (N et N+1) sur la même plateforme

  • Avec la même version mais avec les deux exécutables “debug” et “nodebug”

  • …

Le problème à résoudre est alors d’identifier le morceau de code qui a un comportement différent pour les deux exécutions. Pour localiser le problème, on peut déclencher des impressions intermédiaires à quelques endroits “stratégiques” du code :

  • lors de chaque appel aux calculs élémentaires (routine calcul.F90)

  • lors de chaque appel à la routine de résolution de système linéaire (routine resoud.F90)

En faisant un diff (ou un tkdiff) sur les 2 fichiers message produits, on peut localiser l’endroit où les 2 versions divergent.


Mise en œuvre

Pour déclencher ces impressions, il faut surcharger la routine calcul.F90 et/ou resoud.F90.On modifie alors le source en forçant la variable : DBG=.TRUE..

Cela entraine alors des impressions supplémentaires dans le fichier message.


routine calcul.F90

Par exemple, les impressions de la routine calcul.F90 lors du calcul de l’option AMOR_ACOU sont :

1 &&CALCUL|IN |PGEOMER | MAIL .COORDO .VALE | LONMAX= ...| SOMMR= 0.58898033E+03

2 &&CALCUL|IN |PIMPEDC | IMPEACOU.CHAC.IMPED.VALE | LONMAX= ...| SOMMR= 0.13370000E+04

3 &&CALCUL|IN |PMATERC | CHAMPMAT.MATE_CODE .VALE | LONMAX= ...| SOMMI= 743107436

4 &&CALCUL OPTION=AMOR_ACOU ACOU_FACE8 182

5 &&CALCUL|OUTG|PMATTTC | _9000024.ME001 .RESL | LONMAX= ...| SOMMR= 0.74828831E-04

6 &&CALCUL|OUTF|PMATTTC | _9000024.ME001 .RESL | LONMAX= ...| SOMMR= 0.74828831E-04

Les lignes 1,2,3 correspondent aux 3 paramètres “in” de cette option. Pour chaque paramètre, on imprime des informations sur le champ associé à ce paramètre : nom du champ, LONMAX de l’objet contenant les valeurs du champ, … et “résumé” (colonne SOMMR ou SOMMI) des valeurs du champ.

La ligne 4 indique que le ligrel sur lequel est fait le calcul contient un grel d’éléments de type ACOU_FACE8 et que la routine te00ij.F90 appelée est le te0182.F90.

La ligne 5 renseigne sur le champ “out” PMATTTC après les calculs élémentaires du grel ACOU_FACE8 (donc du te0182.F90).

Les lignes 4 et 5 peuvent être répétées s’il y a plusieurs grel dans le ligrel.

La ligne 6 renseigne sur le champ “out” après le calcul de tous les grel.

Il peut arriver que les impressions montrent que bien que les champs “in” d’un calcul élémentaire soient identiques, les champs “out” diffèrent. On sait alors que le problème concerne un calcul élémentaire précis : OPTION type_element et numéro de la routine te00ij.F90.


Remarques:

Lorsqu’un champ est de type entier, réel ou complexe, le nombre résumant le champ ( SOMMI ou SOMMR ) est un nombre obtenu en “sommant” les valeurs du champ. En réalité, un léger “biais” est introduit pour permettre la détection d’une permutation des valeurs : le vecteur (1 2 3 4) conduira en général à un SOMMI différent de (2 3 1 4).

Pour les champs de type CHARACTER, on fait une somme entière (SOMMI) en transformant chaque caractère en entier (fonction ICHAR).

Attention: un champ “in” est presque toujours différent entre deux exécutions, c’est le champ de “matériau codé” (‘PMATERC’) : il contient des adresses JEVEUXqui n’ont aucune raison d’être identiques. D’autres objets JEVEUXont également presque toujours un contenu différent à chaque exécution, ce sont les objets .TITRqui contiennent en général la date de l’exécution.

Détail : Pour chaque objet JEVEUX“résumé”, on imprime : son nom, sa “somme” (SOMMIou SOMMR) son LONMAX, son LONUTI, son TYPE (R/C/I/K8/…), un code_retour IRET (si iret /= 0, l’objet JEVEUXest dans un état douteux) ainsi qu’un nombre IGNORE qui compte les valeurs “ignorées” dans la somme (SOMMIou SOMMR). Les valeurs ignorées sont les valeurs ‘Nan’ ou invalides (pour faire la somme) : R8MAEM(), R8VIDE(), ISMAEM(), …

routine resoud.F90

Les impressions de la routine resoud.F90 sont :

1 &&RESOUD 2ND MEMBRE | &&MESTAT.2NDMBR_ASS.VALE | LONMAX= ... | SOMMR= -0.20000000000E+06

2 &&RESOUD CHCINE | &&ASCAVC.VCI .VALE | LONMAX= ... | SOMMR= 0.00000000000E+00

3 &&RESOUD MATR.VALM | &&MESTAT_MATR_ASSEM.VALM | LONMAX= ... | SOMMR= 0.13926619473E+13

4 &&RESOUD MATR.VALF | &&MESTAT_MATR_ASSEM.VALF | LONMAX= ... | SOMMR= 0.12301036782E+13

5 &&RESOUD MATR.CONL | &&MESTAT_MATR_ASSEM.CONL | LONMAX= ... | SOMMR= 0.55076923235E+12

6 &&RESOUD SOLU | &&MERESO_SOLUTION .VALE | LONMAX= ... | SOMMR= -0.37488024534E+06

Ligne 1 : second membre du système linéaire

Ligne 2 : valeurs des degrés de liberté imposés éliminés (char_cine)

Ligne 3 : valeurs de la matrice initiale (avant factorisation)

Ligne 4 : valeurs de la matrice factorisée

Ligne 5 : valeur du coefficient de conditionnement des Lagranges (ddls imposés dualisés)

Ligne 6 : valeurs de la solution

Si la ligne 1 diffère, le problème provient de la fabrication du second membre du système.

Si la seule ligne 4 diffère, cela traduit un problème de factorisation (routine preres.F90)

Si la seule ligne 6 diffère, le problème vient de la résolution (routine resoud.F90).