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 :

tableaux dynamiques dans arguments d'appels


Sujet :

Fortran

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    31
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2010
    Messages : 31
    Points : 14
    Points
    14
    Par défaut tableaux dynamiques dans arguments d'appels
    bonsoir,

    j'ai un petit problème dans mon code fortran

    j'ai une subroutine générant un tableau dynamique. J'aimerai exporter ce tableau dans mon programme principal.

    j'ai utilisé la même commande dans la subroutine et le main, à savoir :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    integer, dimension(:), allocatable :: machin
    j'ai une erreur de segmentation.

    j'ai trouvé une autre méthode avec les pointeurs.
    j'ai donc inscrit dans la subroutine :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    integer, dimension(:), pointer :: machin
    puis dans le main
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    integer, dimension(:), target :: machin
    mais toujours pareil, erreur de segmentation...

    je ne sais pas quoi faire d'autres, je me tourne alors vers votre savoir.

    Merci d'avance,
    Thomas

  2. #2
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    152
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 152
    Points : 191
    Points
    191
    Par défaut
    Bonjour,

    Le plus simple restes d'utiliser un module dans lequel tu déclares ton tableau en tableau dynamique puis d'allouer ton tableau dans la subroutine.

    Exemple:

    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
     
    MODULE DIVERS_VAR
    implicit none
    integer,allocatable,dimension(:) :: MON_TAB
    end module MON_TAB
     
    program MON_PROG
    USE DIVERS_VAR
    [...]
    CONTAINS
     
    SUBROUTINE MA_SUB
    USE DIVERS_VAR
    IMPLICIT NONE
     
    ALLOCATE(MON_TAB(VALEURS))
     
    [...]
     
    END SUBROUTINE MA_SUB
     
    [...]
    END PROGRAM MON_PROG
    Tu peux sinon faire une allocation comme tu l'a faite, mais cela nécessite une syntaxe comme :


    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 MON_PROG
    implicit none
    integer,allocatable,dimension (:) :: MON_TAB !déclaration dans le prog principal
    integer :: TAILLE = 12
     
    call ALLOCATION(MON_TAB,TAILLE)
     
    [...]
    CONTAINS
     
    SUBROUTINE ALLOCATION(MON_TAB,TAILLE)
    IMPLICIT NONE
    integer,allocatable dimension(:),intent(out) :: MON_TAB
    integer,intent(in) :: TAILLE
    allocate(MON_TAB(TAILLE))
     
    MON_TAB=0 !autant initialiser
     
    end subroutine ALLOCATION
     
    end program MON_PROG
    Bonne journée,

    Marlan

  3. #3
    Modérateur

    Profil pro
    Inscrit en
    Août 2006
    Messages
    974
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Août 2006
    Messages : 974
    Points : 1 346
    Points
    1 346
    Par défaut
    Citation Envoyé par Infra_Red Voir le message
    ...j'ai utilisé la même commande dans la subroutine et le main, à savoir :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    integer, dimension(:), allocatable :: machin
    j'ai une erreur de segmentation.
    Cette stratégie devrait fonctionner, mais elle requiert une interface explicite. L'erreur de segmentation vient possiblement du fait que tu utilises une interface implicite. Si tu fais une recherche "interface explicite" sur le forum, tu trouveras plus d'info.

  4. #4
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    31
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2010
    Messages : 31
    Points : 14
    Points
    14
    Par défaut
    merci de vos réponses.

    j'ai essayé la deuxième méthode de Marlan mais j'ai toujours un message d'erreur, que voici :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    error : dummy argument 'nbre_noeuds' with 'intent(in)' in variable definition context (affectation)
    nbre_noeuds est la taille de mon tableau dynamique...

    pour les explications de Sylvain Bergeron, je n'ai malheureusement que quelques notions de fortran, j'ai beau chercher interface explicite dans le forum, je trouve rien que je puisse exploiter !!

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    31
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2010
    Messages : 31
    Points : 14
    Points
    14
    Par défaut
    re,

    en fait je viens de comprendre : dans le code de Marlan, la taille du vecteur est connue dès la compilation dans le main.

    or dans mon cas (que je n'ai pas précisé, mea culpa) la taille est inconnue à la compilation : depuis une subroutine, je lis un fichier, je compte le nombre de noeuds, j'affecte la taille du vecteur en fonction de ce nombre et j'exporte ce vecteur dans le main....

  6. #6
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    31
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2010
    Messages : 31
    Points : 14
    Points
    14
    Par défaut
    pour faciliter nos echanges, voici dans l'ordre : le main, la subroutine et le fichier source.txt

    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
    program MEF
     
    implicit none
    integer :: i,j
    integer :: nbre_noeuds, nbre_elements, type_calcul, degre_gauss
    integer, dimension(:), allocatable :: num_glob_noeuds
     
    nbre_noeuds = 9
     
    ! lecture fichier maillage
    ! ------------------------
    call lecture_maillage(nbre_noeuds, nbre_elements, num_glob_noeuds)
    print*,size(num_glob_noeuds)
    ! calcul nombre de ddls du systeme
    ! ------------------------
     
    ! lecture fichier option
    !-----------------------
    call lecture_options(type_calcul,degre_gauss)
     
     
    do i=1,nbre_elements
     
    	! caracteristiques element en cours de traitement
    	!---------------------------
    	!type_element = elements(i,2)	
    	!materiau_elem = materiaux(elements(i,3))
     
    	! construction matrice materiau
    	!-------------------------------
    	!call matrice_materiau(materiau_elem, type_element, C)
     
    	! parametres quadrature de Gauss
    	!call parametre_gauss(type_element, degre_gauss, nbre_points_gauss, poids, x_gauss)
     
    	!construction matrice elementaire
    	!call choix_element(ename,nbre_points_gauss,x_g,poids,noeuds_element,C,epaisseur_elem,section_elem)
     
     
    enddo
     
     
     
     
    end program MEF
    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
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    subroutine lecture_maillage(nbre_noeuds, nbre_elements, num_glob_noeuds)
     
    implicit none
    character(50), dimension(:), allocatable :: maillage_brut
    character(20) :: filename
    integer :: i, j, nbre_lignes, fileid, temp
    integer :: indice_noeud, indice_element, indice_materiau, indice_section, indice_epaisseur, indice_cld, indice_clf, indice_fin
    integer :: nbre_elements, nbre_materiaux, nbre_sections, nbre_epaisseurs, nbre_clds, nbre_clfs
    integer, intent(in) :: nbre_noeuds
    integer, dimension(:), allocatable, intent(out) :: num_glob_noeuds
    integer, dimension(:,:), allocatable :: coord_glob_elements
    real, dimension(:,:), allocatable :: coord_glob_noeuds
    real, dimension(:,:), allocatable :: noeuds, elements, sections, materiaux, epaisseurs, clds, clfs
     
    fileid=10
    filename='maillage.txt'
     
    ! calcul nbre de lignes
    call calcul_nbre_lignes(fileid,filename,nbre_lignes)
     
    ! lecture fichier maillage
    ! ------------------------
    open(10,file='maillage.txt')
    rewind(10)
     
    allocate(maillage_brut(nbre_lignes))
     
    do i=1,nbre_lignes
    	read(10,'(a50)')maillage_brut(i)
    	if (maillage_brut(i) == '.NODE') then
    		indice_noeud=i
    	elseif (maillage_brut(i) == '.ELEM') then
    		indice_element=i
    	elseif (maillage_brut(i) == '.MAT') then
    		indice_materiau=i
    	elseif (maillage_brut(i) == '.SEC') then
    		indice_section=i
    	elseif (maillage_brut(i) == '.EP') then
    		indice_epaisseur=i
    	elseif (maillage_brut(i) == '.CLD') then
    		indice_cld=i
    	elseif (maillage_brut(i) == '.CLF') then
    		indice_clf=i
    	elseif (maillage_brut(i) == '.FIN') then
    		indice_fin=i
    	endif
    enddo
     
    !nbre_noeuds = indice_element - indice_noeud - 1
    nbre_elements = indice_materiau - indice_element - 1
    nbre_materiaux = indice_section - indice_materiau - 1
    nbre_sections = indice_epaisseur - indice_section - 1
    nbre_epaisseurs = indice_cld - indice_epaisseur - 1
    nbre_clds = indice_clf - indice_cld - 1
    nbre_clfs = indice_fin - indice_clf - 1
     
    allocate(noeuds(nbre_noeuds,4), elements(nbre_elements,9), materiaux(nbre_materiaux,3), sections(nbre_sections,5))
    allocate(epaisseurs(nbre_epaisseurs,2), clds(nbre_clds,7), clfs(nbre_clfs,7))
     
     
    !lecture et formatage des noeuds
    j=1
    do i=indice_noeud+1,indice_element-1
    	read(maillage_brut(i),*)noeuds(j,:)
    	j=j+1
    enddo
     
    !lecture et formatage des elements
    j=1
    do i=indice_element+1,indice_materiau-1
    	read(maillage_brut(i),*)elements(j,:)
    	j=j+1
    enddo
     
    !lecture et formatage des materiaux
    j=1
    do i=indice_materiau+1,indice_section-1
    	read(maillage_brut(i),*)materiaux(j,:)
    	j=j+1
    enddo
     
    !lecture et formatage des sections
    j=1
    do i=indice_section+1,indice_epaisseur-1
    	read(maillage_brut(i),*)sections(j,:)
    	j=j+1
    enddo
     
    !lecture et formatage des epaisseurs
    j=1
    do i=indice_epaisseur+1,indice_cld-1
    	read(maillage_brut(i),*)epaisseurs(j,:)
    	j=j+1
    enddo
     
    !lecture et formatage des cld
    j=1
    do i=indice_cld+1,indice_clf-1
    	read(maillage_brut(i),*)clds(j,:)
    	j=j+1
    enddo
     
    !lecture et formatage des clf
    j=1
    do i=indice_clf+1,indice_fin-1
    	read(maillage_brut(i),*)clfs(j,:)
    	j=j+1
    enddo
     
    !organisation des noeuds
    allocate(num_glob_noeuds(nbre_noeuds))
     
    do i=1,nbre_noeuds
    	num_glob_noeuds(i) = noeuds(i,1)
    	!coord_glob_noeuds(i,:) = noeuds(i,2:4)
    enddo
     
    !organisation des elements
    !allocate(num_glob_elements(nbre_elements), coord_glob_elements(nbre_elements,4))
    !do i=1,nbre_elements
    !	num_glob_elements(i) = elements(i,1)
    !	coord_glob_elements(i,:) = elements(i,6:9)
    !	print*,num_glob_elements(i),coord_glob_elements(i,:)
    !enddo
     
    close(10)
     
    end subroutine lecture_maillage

    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
    .NODE
    1	0.32	0	0
    2	2.45	0	0
    3	2	2	0
    4	0	1	0
    5	1	0	0
    6	2	1	0
    7	1	2	0
    8	0	1	0
    10	1	1	0
    .ELEM
    1	24	1	1	1	1 5 5 6
    2	24	1	1	1	5 2 6 9
    3	24	1	1	1	9 6 3 7
    4	24	1	1	1	8 9 7 4
    .MAT
    1	75100	0
    .SEC
    1	78.5	981.25	489.86	489.86
    .EP
    1	1
    .CLD
    1	0	0	0	0	0	0
    4	0	0	0	0	0	0
    .CLF
    6	100	0	0	0	0	0
    .FIN

  7. #7
    Modérateur

    Profil pro
    Inscrit en
    Août 2006
    Messages
    974
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Août 2006
    Messages : 974
    Points : 1 346
    Points
    1 346
    Par défaut
    À propos des interfaces explicites :

    Le problème vient du fait qu'en Fortran, le compilateur n'a pas de vue globale. Lorsqu'il compile MEF, il ne voit pas lecture_maillage. Quand il compile "call lecture_maillage(nbre_noeuds, nbre_elements, num_glob_noeuds)" et qu'il doit passer num_glob_noeuds, il ne sait pas que la routine supporte un allocatable : il passe donc (par défaut puisqu'interface implicite) le vecteur d'entier contenu dans num_glob_noeuds (lequel est probablement null parce que non alloué) et non un pointeur au descripteur de num_glob_noeuds.

    Grosse parenthèse

    L'implantation des allocatables, des pointeurs et des tableaux assumed-shape se fait via une structure (descripteur) contenant le nombre de dimension, la taille de chacune, ..., et un pointeur à la zone (tableau) contenant le data lui-même.

    Lors d'un appel de fonction, le compilateur va passer une référence à la structure si la fonction supporte un type dynamique, sinon, une référence au tableau contenu (le pointeur au data).

    Fin de la grosse parenthèse

    Pour corriger, tu dois faire en sorte que le compilateur, quand il compile MEF, sache que lecture_maillage supporte un tableau allocatable comme dernier argument. Et ça se fait par une interface explicite.

    Il y a 3 méthodes :
    • Par un module comme t'a suggéré Marlan
    • Par une encapsulation de lecture_maillage dans MEF
    • Par un bloc interface

    Module

    Tu dois placer lecture_maillage dans un module qu'on appellera disons ModuleLecture et dans MEF, tu commence par faire use ModuleLecture. Concrètement, tu ajoute les lignes suivantes au début et à la fin de ta routine
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    module ModuleLecture 
    implicit none
    contains
    subroutine lecture_maillage(nbre_noeuds, nbre_elements, num_glob_noeuds)
    ...
    end subroutine lecture_maillage
    end module ModuleLecture
    Si tu as d'autres routines ou fonctions, tu peux aussi les placer entre contains et end module.

    Tu ajoute ensuite la ligne use ModuleLecture au début de MEF, entre la ligne program et le implicit none.

    Pour compiler, tu dois compiler le module AVANT le programme. S'ils sont dans des fichiers distincts, tu dois utiliser l'option -c et compiler chacun séparément dans l'ordre, puis linker. S'ils sont dans le même fichier, tu dois placer le module physiquement au début du fichier.

    encapsulation

    Juste avant le "end program MEF", tu insère la ligne "contains", puis ta routine. Donc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    program MEF
    ...
    enddo
     
    contains
     
    subroutine lecture_maillage(nbre_noeuds, nbre_elements, num_glob_noeuds)
    ...
    end subroutine lecture_maillage
     
    end program MEF
    Bloc interface

    Disons que c'est une solution réservée à des utilisateurs avancés !

  8. #8
    Modérateur

    Profil pro
    Inscrit en
    Août 2006
    Messages
    974
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Août 2006
    Messages : 974
    Points : 1 346
    Points
    1 346
    Par défaut
    J'avais oublié un commentaire de style. Le bloc if dans lecture_maillage serait beaucoup plus joli si tu le réécrivais avec un select case. Au lieu de :

    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
     
    ...
    	if (maillage_brut(i) == '.NODE') then
    		indice_noeud=i
    	elseif (maillage_brut(i) == '.ELEM') then
    		indice_element=i
    	elseif (maillage_brut(i) == '.MAT') then
    		indice_materiau=i
    	elseif (maillage_brut(i) == '.SEC') then
    		indice_section=i
    	elseif (maillage_brut(i) == '.EP') then
    		indice_epaisseur=i
    	elseif (maillage_brut(i) == '.CLD') then
    		indice_cld=i
    	elseif (maillage_brut(i) == '.CLF') then
    		indice_clf=i
    	elseif (maillage_brut(i) == '.FIN') then
    		indice_fin=i
    	endif
    ...
    Tu aurais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    ...
    	select case(maillage_brut(i))
    	case('.NODE'); indice_noeud=i
    	case('.ELEM'); indice_element=i
    	case('.MAT' ); indice_materiau=i
    	case('.SEC' ); indice_section=i
    	case('.EP'  ); indice_epaisseur=i
    	case('.CLD' ); indice_cld=i
    	case('.CLF' ); indice_clf=i
    	case('.FIN' ); indice_fin=i
    	end select
    ...

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    31
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2010
    Messages : 31
    Points : 14
    Points
    14
    Par défaut
    merci beaucoup Sylvain

    j'ai utilisé les modules, ca marche impecc
    j'ai également créé un script sh pour la compilation, pour l'instant j'ai 2 fichiers mais j'en aurais une bonne trentaine.

    et merci pour les select case

    bonne soirée

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

Discussions similaires

  1. Tableaux dynamiques dans un record
    Par Eric Beaumard dans le forum Delphi
    Réponses: 8
    Dernier message: 10/12/2006, 20h51
  2. Réponses: 9
    Dernier message: 15/09/2006, 19h08
  3. Réponses: 1
    Dernier message: 23/06/2006, 11h19
  4. organisation de tableaux dynamiques dans une page HTML
    Par fallered dans le forum Balisage (X)HTML et validation W3C
    Réponses: 5
    Dernier message: 24/10/2005, 16h04
  5. [D7] Tableaux dynamiques dans un record
    Par bobby-b dans le forum Langage
    Réponses: 2
    Dernier message: 30/06/2004, 23h23

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