Προς το περιεχόμενο

Προτεινόμενες αναρτήσεις

Δημοσ.

Χαίρετε σε όλους....

 

Θα ήθελα να ρωτήσω κάτι σχετικό με modules σε Fortran.

 

Μου έδωσαν για τροποποίηση ένα αρχείο (30.000 γραμμές κώδικα) που ορίζει ένα module στην μορφή ::

>
module myModule

 variable_declarations_here
 
 contains

 subroutine subRout1(...) ... end subroutine subRout1
 subroutine subRout2(...) ... end subroutine subRout2
 ........................ ... .......................
 subroutine subRoutN(...) ... end subroutine subRoutN

end module myModule

 

Όπου η κάθε υπορουτίνα είναι 1000+ γραμμές κώδικα. Όπως καταλαβαίνετε κάθε φορά που κάνω αλλαγή στον κώδικα παίρνει κάτι χρόνια να κάνει compile όλο το αρχείο.

 

Η απορία μου είναι :: Πως μπορώ να δηλώσω τις υπορουτίνες στο module και να τις ορίσω σε διαφορετικά αρχεία; Ώστε κάθε φορά να κάνω compile μόνο το αρχείο το οποίο εμπεριέχει την τροποποιημένη υπορουτίνα και όχι και τις 30.000 γραμμές κώδικα;

 

Έχω βρεί ότι χρησιμοποιώντας την

>include 'subRoutineFile.f90'

μπορώ να μεταφέρω την υπορουτίνα στο αρχείο subRoutineFile.f90 και το module να γίνει της μορφής ::

 

>
module myModule

 variable_declarations_here
 
 contains

 include 'subRoutineFile1.f90' !instead of subroutine subRout1(...) ... end subroutine subRout1
 include 'subRoutineFile2.f90' !instead of subroutine subRout2(...) ... end subroutine subRout2
 ........................ ... .......................
 include 'subRoutineFileN.f90' !instead of subroutine subRoutN(...) ... end subroutine subRoutN

end module myModule

 

Αυτό όμως έχει το πρόβλημα ότι πρέπει να κάνω compile το βασικό αρχείο (30.000 γ.κ.) αντί του αρχείου που περιέχει την τροποποιημένη υπορουτίνα. Έχει κανείς καμία ιδέα για το πως θα μπορούσα να το φτιάξω;

 

Ευχαριστώ πολύ εκ των προτέρων.

Δημοσ.

Η include απλώς μεταφέρει αυτούσιο τον κώδικα από το ένα αρχείο στο άλλο

(είναι δηλ. σα να παρεμβάλεις τον κώδικα με μια συντομογραφία).

Δεν διαχωρίζει πραγματικά τα αρχεία.

Είναι πολύ χρήσιμη σε δοκιμές : μπορείς να έχεις κώδικα σε κάποιο χωριστό αρχείο και πανεύκολα

να τον προσθέτεις ή να τον αφαιρείς εκεί που θέλεις. Όταν έχει μεγάλη έκταση, αντί να τον μετατρέπεις

σε σχόλια που επιβαρύνουν την αναγνωσιμότητα του προγράμματος, τον βάζεις-βγάζεις με την include.

 

 

Στο module οι συναρτήσεις γενικά πρέπει μόνον να δηλώνονται, κι όχι να παρέχεται εκεί ο πηγαίος κώδικάς τους.

Στο απόσπασμα που παραθέτεις υπάρχει το keyword contains που υποδηλώνει - αν καταλαβαίνω καλά - ότι οι

συναρτήσεις δίνονται εκεί με τον πηγαίο κώδικά τους και δεν είναι απλώς δηλώσεις.

Γι' αυτό μάλλον σκεφτηκες την include αλλά αυτή όπως ανάφερα βάζει αθέατα τον κώδικα στο σημείο που την

καλείς, άρα δεν είναι αυτό που θέλεις.

Η λύση είναι απλούστατη : να μεταφέρεις σε άλλο αρχείο τον πηγαίο κώδικα των συναρτήσεων (έξω από το module)

και στο module να αφήσεις μόνον τις δηλώσεις τους - τουλάχιστον για τις συναρτήσεις που θέλεις να τροποποιείς.

Έτσι έχεις τις συναρτήσεις (μία-μία ή πολλές μαζί) σε χωριστά πηγαία αρχεία και κάνεις χωριστά compile το καθένα από τα αρχεία αυτά.

Έτσι παράγονται αρχεία obj, lib κλπ από το κάθε ένα πηγαίο αρχείο. Στο τέλος κάνεις build τo project και όλα αυτά τα επιμέρους συνδέονται.

Αν τροποποιήσεις κάποια συνάρτηση, δηλ. κάποιο από τα πηγαία αρχεία, απλώς το ξανακάνεις compile και κάνεις πάλι build το project.

Τα παρελκόμενα obj,lib κλπ των λοιπών πηγαίων αρχείων μένουν άθικτα και χρησιμοποιούνται στο build όπως είναι

(προσοχή όμως, όχι rebuild διότι τότε θα τα ξαναφτιάξει όλα από την αρχή).

To μόνο που ίσως δημιουργήσει προβλήματα είναι η όποια αλλεξάρτηση των συναρτήσεων μεταξύ τους.

Αυτές πρέπει να τις βάλεις μαζί, θα το βρεις με δοκιμές...

 

-

Δημοσ.

Ευχαριστώ για την απάντηση.

 

Έκανα μία αναζήτηση βάση όσων μου είπες και βρήκα πως μπορώ να δηλώσω τις συναρτήσεις (functions) ενός module αλλά δεν μπορώ να βρώ τον τρόπο για να δηλώσω τις υπορουτίνες (τις οποίες θα ορίσω σε διαφορετικό αρχείο).

 

Μήπως έχεις κάποιο παράδειγμα;

Δημοσ.

Συναρτήσεις και υπορουτίνες είναι σχεδόν το ίδιο.

 

Η δήλωση αμφότερων στο module συνίσταται στο να περιγράψεις τα ορίσματά τους ώστε να ξέρει τι θα βρει ο compiler κατά την κλήση τους.

Στην fortran δεν απαιτείται να δηλώνονται οι συναρτήσεις όπως στην C/C++. O compiler "υποθέτει" αυτόματα (implicit interface) τι ορίσματα λαμβάνουν.

Αλλά στις περισσότερες περιπτώσεις η δήλωση είναι απαραίτητη, π.χ. όταν τα ορίσματα μιας υπορουτίνας είναι πίνακες (απαιτείται explicit interface).

H δήλωσή τους στο module πρέπει να γίνει σε ένα block Ιnterface ... end interface όπου θα αναφέρονται τα ορίσματά τους.

Δεν βλέπω παραπάνω να χρησιμοποιείς την Interface, άρα δεν το κάνεις σωστά.

Διάβασε τα σχετικά με την Ιnterface και το implicit/explicit interface των συναρτήσεων και θα βρεις αμέσως πώς γίνεται...

 

-

Δημοσ.

V.I.Smirnov

 

Ευχαριστώ πάρα πολύ !!! Με βοήθησες εξαιρετικά!! Να ρωτήσω κάτι επιπλέον μήπως έχεις καμία ιδέα...

 

Έχω δημιουργήσει τα αρχεία ::

 

derivedTypes.f90

>
module derivedTypes

 type derivedType1
   integer :: c1, n1
 end type derivedType1

end module derivedTypes

 

myModule.f90

>module myModule

 use derivedTypes
 integer :: counter

 interface
   subroutine helloWorld(dt)
     type(derivedType1), intent(in) :: dt
   end subroutine helloWorld
 end interface

end module myModule 

 

myModuleSubroutines.f90

>subroutine helloWorld(dt)

 use mymodule
 
 implicit none

 type(derivedType1), intent(in) :: dt
 write ( *, * ) 'Hello World', dt%c1, dt%n1

end subroutine helloWorld 

 

main.f90

> program main

 use myModule
 integer :: num = 3

 call anotherOne(4)
 call helloWorld(num)

end program main 

 

Κατόπιν κάνω compile τον κώδικα με την ακόλουθη σειρά ::

>	
1. ifort -c derivedTypes.f90
2. ifort -c myΜodule.f90
3. ifort -c myModule_subroutines.f90
4. ifort -c main.f90
5. ifort *.o

 

Κάτι δεν κάνω όμως σωστά και ο compiler στο 2 βήμα (myΜodule.f90) μου πετάει σφάλμα ::

>
mymodule.f90(8): error #6457: This derived type name has not been declared.   [DERIVEDTYPE1]
     type(derivedType1), intent(in) :: dt
-----------^

 

Δεν καταλαβαίνω όμως τι. Από την στιγμή που έχω δηλώσει λίγες γραμμές πιο πάνω να χρησιμοποιήσει το module για τους derivedTypes δεν θα έπρεπε να το αναγνωρίζει;

Δημοσ.

Εχεις κάποιες αβλεψίες στα παραπάνω.

 

1) σε ότι αφορά την helloWorld, δηλώνεις στο module το όρισμα τύπου derivedType1 αλλά στο

κύριο πρόγραμμα την καλείς με integer (ασύμβατοι τύποι δήλωσης-κλήσης).

 

2) Στην δήλωση της συνάρτησης helloWorld (στο module) δεν έχει δηλωθεί στο εσωτερικό της ότι βλέπει τον τύπο derivedType1 .

Το ότι ο τύπος έχει δηλωθεί στο module νωρίτερα δεν σημαίνει ότι η δήλωσή του είναι ορατή στο εσωτερικό των συναρτήσεων που έπονται (εντός της interface).

Πρέπει να το θέσεις στο εσωτερικό της στην δήλωση.

 

Διορθωμένα :

>module myModule 

 use derivedTypes 
 integer :: counter 

 interface 
   subroutine helloWorld(dt) 
     use derivedTypes
     type(derivedType1), intent(in) :: dt 
   end subroutine helloWorld 
 end interface 

end module myModule 


program main 

 use myModule 
 type(derivedType1)::num

 num%c1=1
 num%n1=2

 call helloWorld(num) 

end program main

 

Δεν μπορώ να ασχοληθώ περισσότερο αλλά δεν είναι δύσκολο.

Αν καταλάβεις την εμβέλεια (scope) των δηλώσεων και την χρήση των module, interface κλπ, έληξε.

Το help της intel fortran, αν και κάπως τεχνικό, δίνει καλές εξηγήσεις σ' αυτά.

Η προσπάθεια να κατάλάβεις τι γίνεται με απλές ενδεικτικές δοκιμές είναι πολύ καλή πρακτική...

 

-

Δημοσ.

Ευχαριστώ πάρα πολύ !!! Το κατάφερα...

 

Το παλεύω 4 ημέρες τώρα για να βγάλω κάποια άκρη και τα tutorials από το internet δεν είναι πάντα τα κατάλληλα.

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα
  • Δημιουργία νέου...