Αbominable Δημοσ. 4 Δεκεμβρίου 2011 Δημοσ. 4 Δεκεμβρίου 2011 Χαίρετε σε όλους.... Θα ήθελα να ρωτήσω κάτι σχετικό με 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 γ.κ.) αντί του αρχείου που περιέχει την τροποποιημένη υπορουτίνα. Έχει κανείς καμία ιδέα για το πως θα μπορούσα να το φτιάξω; Ευχαριστώ πολύ εκ των προτέρων.
V.I.Smirnov Δημοσ. 5 Δεκεμβρίου 2011 Δημοσ. 5 Δεκεμβρίου 2011 Η include απλώς μεταφέρει αυτούσιο τον κώδικα από το ένα αρχείο στο άλλο (είναι δηλ. σα να παρεμβάλεις τον κώδικα με μια συντομογραφία). Δεν διαχωρίζει πραγματικά τα αρχεία. Είναι πολύ χρήσιμη σε δοκιμές : μπορείς να έχεις κώδικα σε κάποιο χωριστό αρχείο και πανεύκολα να τον προσθέτεις ή να τον αφαιρείς εκεί που θέλεις. Όταν έχει μεγάλη έκταση, αντί να τον μετατρέπεις σε σχόλια που επιβαρύνουν την αναγνωσιμότητα του προγράμματος, τον βάζεις-βγάζεις με την include. Στο module οι συναρτήσεις γενικά πρέπει μόνον να δηλώνονται, κι όχι να παρέχεται εκεί ο πηγαίος κώδικάς τους. Στο απόσπασμα που παραθέτεις υπάρχει το keyword contains που υποδηλώνει - αν καταλαβαίνω καλά - ότι οι συναρτήσεις δίνονται εκεί με τον πηγαίο κώδικά τους και δεν είναι απλώς δηλώσεις. Γι' αυτό μάλλον σκεφτηκες την include αλλά αυτή όπως ανάφερα βάζει αθέατα τον κώδικα στο σημείο που την καλείς, άρα δεν είναι αυτό που θέλεις. Η λύση είναι απλούστατη : να μεταφέρεις σε άλλο αρχείο τον πηγαίο κώδικα των συναρτήσεων (έξω από το module) και στο module να αφήσεις μόνον τις δηλώσεις τους - τουλάχιστον για τις συναρτήσεις που θέλεις να τροποποιείς. Έτσι έχεις τις συναρτήσεις (μία-μία ή πολλές μαζί) σε χωριστά πηγαία αρχεία και κάνεις χωριστά compile το καθένα από τα αρχεία αυτά. Έτσι παράγονται αρχεία obj, lib κλπ από το κάθε ένα πηγαίο αρχείο. Στο τέλος κάνεις build τo project και όλα αυτά τα επιμέρους συνδέονται. Αν τροποποιήσεις κάποια συνάρτηση, δηλ. κάποιο από τα πηγαία αρχεία, απλώς το ξανακάνεις compile και κάνεις πάλι build το project. Τα παρελκόμενα obj,lib κλπ των λοιπών πηγαίων αρχείων μένουν άθικτα και χρησιμοποιούνται στο build όπως είναι (προσοχή όμως, όχι rebuild διότι τότε θα τα ξαναφτιάξει όλα από την αρχή). To μόνο που ίσως δημιουργήσει προβλήματα είναι η όποια αλλεξάρτηση των συναρτήσεων μεταξύ τους. Αυτές πρέπει να τις βάλεις μαζί, θα το βρεις με δοκιμές... -
Αbominable Δημοσ. 5 Δεκεμβρίου 2011 Μέλος Δημοσ. 5 Δεκεμβρίου 2011 Ευχαριστώ για την απάντηση. Έκανα μία αναζήτηση βάση όσων μου είπες και βρήκα πως μπορώ να δηλώσω τις συναρτήσεις (functions) ενός module αλλά δεν μπορώ να βρώ τον τρόπο για να δηλώσω τις υπορουτίνες (τις οποίες θα ορίσω σε διαφορετικό αρχείο). Μήπως έχεις κάποιο παράδειγμα;
V.I.Smirnov Δημοσ. 5 Δεκεμβρίου 2011 Δημοσ. 5 Δεκεμβρίου 2011 Συναρτήσεις και υπορουτίνες είναι σχεδόν το ίδιο. Η δήλωση αμφότερων στο module συνίσταται στο να περιγράψεις τα ορίσματά τους ώστε να ξέρει τι θα βρει ο compiler κατά την κλήση τους. Στην fortran δεν απαιτείται να δηλώνονται οι συναρτήσεις όπως στην C/C++. O compiler "υποθέτει" αυτόματα (implicit interface) τι ορίσματα λαμβάνουν. Αλλά στις περισσότερες περιπτώσεις η δήλωση είναι απαραίτητη, π.χ. όταν τα ορίσματα μιας υπορουτίνας είναι πίνακες (απαιτείται explicit interface). H δήλωσή τους στο module πρέπει να γίνει σε ένα block Ιnterface ... end interface όπου θα αναφέρονται τα ορίσματά τους. Δεν βλέπω παραπάνω να χρησιμοποιείς την Interface, άρα δεν το κάνεις σωστά. Διάβασε τα σχετικά με την Ιnterface και το implicit/explicit interface των συναρτήσεων και θα βρεις αμέσως πώς γίνεται... -
Αbominable Δημοσ. 5 Δεκεμβρίου 2011 Μέλος Δημοσ. 5 Δεκεμβρίου 2011 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 δεν θα έπρεπε να το αναγνωρίζει;
V.I.Smirnov Δημοσ. 5 Δεκεμβρίου 2011 Δημοσ. 5 Δεκεμβρίου 2011 Εχεις κάποιες αβλεψίες στα παραπάνω. 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, αν και κάπως τεχνικό, δίνει καλές εξηγήσεις σ' αυτά. Η προσπάθεια να κατάλάβεις τι γίνεται με απλές ενδεικτικές δοκιμές είναι πολύ καλή πρακτική... -
Αbominable Δημοσ. 5 Δεκεμβρίου 2011 Μέλος Δημοσ. 5 Δεκεμβρίου 2011 Ευχαριστώ πάρα πολύ !!! Το κατάφερα... Το παλεύω 4 ημέρες τώρα για να βγάλω κάποια άκρη και τα tutorials από το internet δεν είναι πάντα τα κατάλληλα.
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα