Fortran est un langage compilé disponible sur les ordinateurs de Calcul Canada où sont installés les compilateurs gfortran et ifort. En général, les langages compilés offrent une meilleure performance; nous vous encourageons donc à écrire vos programmes en Fortran, C ou C++. == Options utiles de compilation == La plupart des compilateurs Fortran modernes offrent des options utiles pour le débogage. * -fcheck=all pour le compilateur gfortran et -check pour le compilateur ifort vérifient les limites des tableaux et signalent les pointeurs sans cible et les variables non initialisées; * -fpe0 (ifort) interrompt l'application dans des cas de virgule flottante (division par zéro ou racine carrée d'un nombre négatif) plutôt que de simplement générer NaN (''not a number'') et laisser l'application se poursuivre; * pendant les tests, utilisez -O0 pour désactiver les optimisations et -g pour ajouter les symboles de débogage. ==Algèbre linéaire numérique== À partir de Fortran 90, de nouvelles fonctions sont disponibles pour le traitement des opérations de base : matmul et dot_product pour les multiplications avec matrices et vecteurs; transpose pour la transposition de matrices. Utilisez toujours ces fonctions ou les librairies BLAS/LAPACK fournies et n'essayez jamais de créer vos propres méthodes, à moins que ce ne soit pour des motifs d'apprentissage. La routine BLAS pour la multiplication de matrices peut s'avérer 100 fois plus rapide que l'algorithme primaire avec trois boucles imbriquées. ==Erreurs de segmentation== Une erreur fréquemment observée avec un exécutable Fortran provient de problèmes d'interface. Ces problèmes surviennent lorsque l'on transmet comme argument d'une sous-routine un pointeur, un tableau alloué dynamiquement ou encore un pointeur de fonctions. À la compilation il n'y a pas de problème, cependant à l'exécution vous obtiendrez par exemple le message suivant : ; '''forrtl: severe (174): SIGSEGV, segmentation fault occurred''' Pour corriger le problème, il faut s'assurer que l'interface de la sous-routine est définie explicitement. Ceci peut se faire en Fortran avec la commande INTERFACE. Ainsi, le compilateur arrivera à construire l'interface et les erreurs de segmentation seront réglées. Dans le cas où l'argument est un tableau allouable, il s'agit de remplacer le code suivant {{ File |name=error_allocate.f90 |lang="fortran" |contents= Program Eigenvalue implicit none integer :: ierr integer :: ntot real, dimension(:,:), pointer :: matrix read(5,*) ntot ierr = genmat( ntot, matrix ) call Compute_Eigenvalue( ntot, matrix ) deallocate( matrix ) end }} par le code {{ File |name=interface_allocate.f90 |lang="fortran" |contents= Program Eigenvalue implicit none integer :: ierr integer :: ntot real, dimension(:,:), pointer :: matrix interface function genmat( ntot, matrix ) implicit none integer :: genmat integer, intent(in) :: ntot real, dimension(:,:), pointer :: matrix end function genmat end interface read(5,*) ntot ierr = genmat( ntot, matrix ) call Compute_Eigenvalue( ntot, matrix ) deallocate( matrix ) end }} Le principe est le même dans le cas où l'argument est un pointeur de fonction. Considérons, par exemple, le code suivant : {{ File |name=error_=pointer.f90 |lang="fortran" |contents= Program AreaUnderTheCurve implicit none real,parameter :: boundInf = 0. real,parameter :: boundSup = 1. real :: area real, external :: computeIntegral real, external :: FunctionToIntegrate area = computeIntegral( FunctionToIntegrate, boundInf, boundSup ) end function FunctionToIntegrate( x ) implicit none real :: FunctionToIntegrate real, intent(in) :: x FunctionToIntegrate = x end function FunctionToIntegrate function computeIntegral( func, boundInf, boundSup ) implicit none real, external :: func real, intent(in) :: boundInf, boundSup ... }} Pour ne pas obtenir d'erreur de segmentation, il faut remplacer le code précédent par ce qui suit : {{ File |name=interface_pointer.f90 |lang="fortran" |contents= Program Eigenvalue implicit none real,parameter :: boundInf = 0. real,parameter :: boundSup = 1. real :: area real, external :: computeIntegral interface function FunctionToIntegrate( x ) implicit none real :: FunctionToIntegrate real, intent(in) :: x end function FunctionToIntegrate end interface area = computeIntegral( FunctionToIntegrate, boundInf, boundSup ) end function FunctionToIntegrate( x ) implicit none real :: FunctionToIntegrate real, intent(in) :: x FunctionToIntegrate = x end function FunctionToIntegrate function computeIntegral( func, boundInf, boundSup ) implicit none real, intent(in) :: boundInf, boundSup interface function func( x ) implicit none real :: func real, intent(in) :: x end function func end interface ... }}