IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Fortran Discussion :

Demande d'aide : Erreur de compilation programme fortran 90


Sujet :

Fortran

  1. #1
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2013
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2013
    Messages : 5
    Points : 4
    Points
    4
    Par défaut Demande d'aide : Erreur de compilation programme fortran 90
    Bonjour,

    Je suis étudiant en école d'ingénieur. J'ai pour projet de créer un programme me permettant d'inverser une matrice.
    Cependant je suis coincé, c'est pourquoi je vous demande votre aide. En effet, a priori je crois avoir finis mon programme mais j'ai trois erreurs de compilation que je n'arrive pas à résoudre. Peux être que ce ne sont que de petites erreurs mais je débute en fortran.

    Je vous remercie par avance de votre aide et vous joins en pièce jointe :
    - mon fichier contenant mes procédures externes intitulé : tools.f90
    - mon fichier contenant mon programme principale : main.f90
    - ainsi qu'une capture écran de mes erreurs au terminal

    En vous remerciant de votre aide
    Fichiers attachés Fichiers attachés

  2. #2
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2013
    Messages
    388
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2013
    Messages : 388
    Points : 692
    Points
    692
    Par défaut
    Salut,
    En FORTRAN, on faut déclarer les variables dans l'en-tête et pas dans le corps du programme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    program inversion_de_matrice
        implicit none
        integer :: choix, nbrlignecollone
        real, allocatable :: A(:,:)
        real :: det
        real, allocatable :: inv(:,:)
        ...

  3. #3
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2013
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2013
    Messages : 5
    Points : 4
    Points
    4
    Par défaut
    Merci beaucoup.

    Je n'ai plus d'erreur de compilation c'est déjà bien
    Malheureusement quand je choisit les deux premiers cas de mon programme j'ai une erreur de segmentation (cf capture écran terminal en pièce jointe).
    Avez vous une idée de la cause de ce problème?
    Peux être que c'est un problème d'allouement de la mémoire mais je ne comprend pas encore bien cette notion.

    Merci d'avance
    Images attachées Images attachées  

  4. #4
    Membre du Club
    Homme Profil pro
    Inscrit en
    Mai 2013
    Messages
    35
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2013
    Messages : 35
    Points : 65
    Points
    65
    Par défaut
    Bonjour

    L'interface de la subroutine Saisir déclarée dans le main n'est pas la même que celle déclarée dans le fichier tools.f90. D'autre part, j'ai rajouté les intentions des arguments dans les deux fichiers.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
     
    main.f90
     
    interface
    ....
    subroutine saisir(A, nbrlignecollone)
       integer, intent(in) :: nbrlignecollone
       real,dimension(:,:), allocatable, intent(out) :: A
     end subroutine saisir
    ...
    end interface
     
    tools.f90
    ....
    subroutine saisir(A, nbrlignecollone)
     
      integer, intent(in) :: nbrlignecollone
      real,dimension(:,:), allocatable, intent(out) :: A
     
      integer :: i, j, pballocation
     
      ....
    end subroutine saisir
    Néanmoins, cette seule correction ne suffit pas pour que votre code fonctionne correctement. En effet, l'utilisation d'un tableau dynamique se justifie pour la subroutine Saisir dans la mesure où elle sert à initialiser une matrice dont la dimension n'est connue qu'au moment de l'éxécution.

    Mais, la mémoire ayant été allouée à la matrice A dans la subroutine Saisir, le fait de la réallouer dans la function Déterminant provoque une erreur d'éxécution. L'argument de la fonction déterminant devrait être un tableau de profil générique plutôt qu'un tableau dynamique.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
      real function determinant(A, nbrlignecollone)
     
       integer, intent(in) :: nbrlignecollone
       real, dimension(:,:), intent(in) :: A
    ....
    Cette erreur doit être corrigée dans la plupart de vos subroutines et fonctions.

    Cordialement.

  5. #5
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2013
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2013
    Messages : 5
    Points : 4
    Points
    4
    Par défaut
    Merci beaucoup!

    J'ai déjà résolu quelques erreurs et l’exécution de mon programme commence à fonctionner.
    En effet j'arrive à saisir la matrice et à l'afficher cependant j'ai des erreurs de segmentation par la suite dans les fonctions determinant et inverse.

    En executant, je constate que la fonction determinant fonctionne avec une matrice triangulaire (pas de permutation de ligne à effectuer). De plus en utilisant l'instruction write en exécutant, j'en déduis que le problème doit surement venir de ma subroutine "permutation_ligne".

    Effectivement, je constate que dans ma boucle lors de la première itération il n'y a pas de problème pour la subroutine "permutation_ligne" en revanche par la suite : "erreur de segmentation". Je pense que cela doit être un problème d'allocation de la mémoire.

    Savez vous comment je peux résoudre ce problème? LittleOwl m'a parlé de tableaux de profil générique mais je n'ai jamais entendu parler de cela... (Est-ce des tableaux "simple", non dynamiques?)

    Je joins en pièce jointe une archive contenant :
    - mon fichier tools.f90 et main.f90
    - des captures d'écran des fonctions determinant et inverse, de ma subroutine permutation_ligne ainsi que du terminal.

    Je vous remercie par avance de l'aide que vous pourrai m'apporter.

    Cordialement
    Fichiers attachés Fichiers attachés

  6. #6
    Membre du Club
    Homme Profil pro
    Inscrit en
    Mai 2013
    Messages
    35
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2013
    Messages : 35
    Points : 65
    Points
    65
    Par défaut Tableau de profil implicite
    Bonjour

    LittleOwl m'a parlé de tableaux de profil générique mais je n'ai jamais entendu parler de cela... (Est-ce des tableaux "simple", non dynamiques?)
    Désolé, je pense que l'appellation exacte n'est pas "tableau de profil générique" mais "tableau de profil implicite". Brièvement, ce type de déclaration est utile lorsqu'on passe en argument d'une subroutine ou d'une fonction un tableau de rang fixe, mais dont la taille peut varier d'un appel à l'autre de la fonction. La primitive size permet de connaitre la taille du tableau passé en argument selon ses différentes dimensions. Ce ne sont pas des tableaux dynamiques. Les tableaux passés en argument doivent avoir été alloué en mémoire avant l'appel, soit au moment de leur déclaration (tableau statique), soit à travers la primitive allocate (tableau dynamique).

    Il existe néanmoins une autre méthode permettant de gérer cette situation, qui consiste à passer en argument, à la fois le nom du tableau et sa taille dans ses différentes dimensions. C'est la méthode que vous avez adoptée dans la dernière version de votre programme. Par conséquent, ce n'est pas l'utilisation de tableau de profil implicite qui résoudra les problèmes de gestion de mémoire que vous rencontrez.

    A titre d'exemple, vous trouverez ci-dessous une fonction qui calcul la trace d'une matrice carré nXn dont l'argument est déclaré comme un tableau implicite.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
     
    program trace
     
    implicit none
     
    real, dimension(9), parameter :: values = (/ 1, 2, 3, 1, 4, 9, 1, 8, 27 /)
    integer, dimension(2), parameter :: profil2 = (/2, 2/)
    integer, dimension(2), parameter :: profil3 = (/3, 3/)
     
    real, dimension(2,2) :: A = reshape(values(1:4), profil2)
    real, dimension(3,3) :: B = reshape(values, profil3)
     
    integer :: i
     
    call mprint(A)
    print '("Tr(A) = ", g15.6)',tr(A)
     
    print *
     
    call mprint(B)
    print '("Tr(B) = ", g15.6)',tr(B)
     
    contains
     
    real function tr(m)
     
    real, dimension(:,:), intent(in) :: m ! Tableau de rang 2, de profil implicite
     
    real :: s = 0
    integer :: i, n
     
    n = size(m,1)	! Taille de la matrice m selon la dimension 1
     
    do i = 1, n
      s = s + m(i,i)
    end do
     
    tr = s
     
    end function tr
     
    subroutine mprint(m)
     
    real, dimension(:,:), intent(in) :: m ! Tableau de rang 2, de profil implicite
     
    integer :: n
     
    n = size(m,1)	! Taille de la matrice m selon la dimension 1 (m est supposee carree)
    do i = 1, n
     print *,m(i,:)
    end do
     
    end subroutine mprint
     
    end program trace
    Si vous souhaitez plus d'information sur les tableaux de profil implicite, vous pouvez consulter par exemple le Chapitre 7 de la référence "Delannoy, Programmer en F90", notamment les pp 161-165

    Cordialement.

  7. #7
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2013
    Messages
    388
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2013
    Messages : 388
    Points : 692
    Points
    692
    Par défaut
    Bonjour,
    Je complète juste en rappelant que depuis la norme 2003 il est possible de passer en argument d'une procédure un tableau allouable non alloué.
    Un exemple tiré du cours de l'IDRIS F95-2 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    program alloca
        implicit none
        real , dimension (:) , ALLOCATABLE :: vec_x , vec_y
     
        allocate ( vec_y ( -2:100) )
        call sp( vec_x , vec_y )
        print *, vec_x ( (/ lbound ( vec_x ), ubound ( vec_x ) /) ), &
                 vec_y ( (/ -2, 100 /) )
        deallocate ( vec_x ); deallocate ( vec_y )
     
    CONTAINS
     
        subroutine sp( v_x , v_y )
            real , dimension (:) , ALLOCATABLE , intent ( inout ) :: v_x , v_y
     
            ALLOCATE ( v_x (256))
            call random_number ( v_x ); call random_number ( v_y )
            print *, " Bornes inf / sup( v_y ) : ", lbound ( v_y ), ubound ( v_y )
        end subroutine sp
     
    end program alloca
    Mais je ne pense pas que c'était l'intention du développeur.

  8. #8
    Membre du Club
    Homme Profil pro
    Inscrit en
    Mai 2013
    Messages
    35
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2013
    Messages : 35
    Points : 65
    Points
    65
    Par défaut Calcul du déterminant
    Bonjour,

    1. Le type de la fonction rech_ligne_pivot n'est pas déclarée dans l'interface du main. Cette erreur est probablement à l'origine du problème de segmentation car la valeur de retour de cette fonction devient aléatoire dans ce cas. J'ai rajouté également dans le fichier main.f90 et tools.f90 les vocations des paramètres (intent(in)) (pas indispensable, mais plus lisible et plus sur)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    main.f90
    ...
    interface
    ...
    integer function rech_ligne_pivot(A, nbrlignecollone, num_collone_rech)
      integer, intent(in) :: nbrlignecollone, num_collone_rech
      real,dimension(nbrlignecollone,nbrlignecollone), intent(in) :: A
    end function rech_ligne_pivot
    ...
    end interface
    ....
    2. Le corps de la fonction rech_ligne_pivot fait appel à une variable non déclarée num_piv, probablement due à une coquille (l.17). Je l'ai remplacé par num_pivot et j'ai ajouté une clause implicit none au début de la fonction afin que ce type d'erreur soit détectée à la compilation.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
     
    ...
    integer function rech_ligne_pivot(A, nbrlignecollone, num_collone_rech)
     
      implicit none
     
      integer, intent(in) :: nbrlignecollone, num_collone_rech
      real, intent(in)    :: A(nbrlignecollone,nbrlignecollone)
     
      integer :: num_pivot
     
      num_pivot = num_collone_rech
     
      do while ((num_pivot.LE.nbrlignecollone).AND.(A(num_pivot,num_collone_rech).EQ.0))
         num_pivot = num_pivot + 1
      end do
     
      if(num_pivot.GT.nbrlignecollone) then
         num_pivot = 0
      end if
     
      rech_ligne_pivot = num_pivot
      return
     
    end function rech_ligne_pivot
    Après ces 2 corrections, le programme ne produit plus d'erreur de segmentation mais le calcul du déterminant reste faux.

    3. La subroutine pivot fait appel à une variable non déclarée "étape_piv", là aussi probablement du à une coquille (l.15). Je l'ai remplacé par etape_pivot et j'ai ajouté une clause implicit none au début de la subroutine.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
    subroutine pivot(etape_pivot, A, nbrlignecollone, B, nbrcolloneB)    
     
      implicit none
     
      integer :: i, j,  nbrlignecollone, nbrcolloneB, etape_pivot
      real :: piv, k
      real :: A(nbrlignecollone,nbrlignecollone)
      real :: B(nbrlignecollone,nbrlignecollone)
     
      piv = A(etape_pivot,etape_pivot)
      do i=etape_pivot+1, nbrlignecollone
         k=A(i, etape_pivot)
         A(i, etape_pivot) = 0
         do j=etape_pivot+1, nbrlignecollone
            A(i,j) = A(i,j) - ((A(etape_pivot, j)*k)/etape_pivot)
         end do
         do j=1, nbrcolloneB
            B(i,j) = B(i,j) - ((B(etape_pivot, j)*k)/piv)
         end do
      end do
     
    end subroutine pivot
    Après ces 3 corrections, le calcul du déterminant sur une matrice carré semble donner le résultat correct, mais des tests supplémentaires doivent être fait avant de valider cette fonction.

    Cordialement

  9. #9
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2013
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2013
    Messages : 5
    Points : 4
    Points
    4
    Par défaut
    Merci énormément à vous deux LittleOwl et dardanos. Vous m'avez été d'une grande aide.

    Grâce à vous j'ai pu effacer mes erreurs de segmentation, le programme tourne correctement.
    Cependant la valeur qui m'ai retourné pour ma matrice inverse est fausse, je dois avoir une erreur dans mon algorithme, je vais essayer de la trouver

    Merci encore à vous deux et je met donc le sujet comme résolu.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. aide sur une erreur apres compilation d'un programme
    Par oscarus dans le forum Dev-C++
    Réponses: 0
    Dernier message: 04/02/2014, 20h08
  2. Demande d'aide pour mon premier programme
    Par ne2sbeal dans le forum Windows Forms
    Réponses: 6
    Dernier message: 21/01/2009, 21h53
  3. Réponses: 2
    Dernier message: 15/10/2008, 10h18
  4. demande d'aide pour la compilation d'un programme
    Par rioux dans le forum Autres éditeurs
    Réponses: 2
    Dernier message: 07/12/2006, 13h35
  5. [TPW][cours]Demande d'aide pour finir un programme
    Par jf dans le forum Turbo Pascal
    Réponses: 21
    Dernier message: 16/06/2003, 18h10

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo