2012-05-25 5 views
5

Ich entwerfe einen Fortran-Code zur Lösung eines PDE-Systems.Ein gutes OOP-Design für einen Löser mit modernem Fortran

Die Art, wie es jetzt entworfen wird, ist, dass ich einen Typ Variable habe, der mehrere Attribute hat, von denen das wichtigste das Array val ist, das den Wert speichert.

Jetzt habe ich auch eine solver Klasse, die Berechnungen auf einem variable durchführen würde. Ich dachte, dass die ganze variable an den Löser und arbeiten mit variable%val jedes Mal, wenn ich es (mehrere tausend Mal während einer Ausführung) ausführen würde ineffizient sein würde, so entschied ich Zeiger Felder in der solver Klasse zu definieren, um die zu binden Löser auf die entsprechende Variable. Zum Beispiel

program example 
    use variable 
    use solvers 

    type(Variable) T 
    type(Solver) solver_temperature 

    !Contructors 
    call T%create() 
    call solver_temperature%create(T) 

    call solver_temperature%solve() 
end program example 

und die Lösungs-Modul

module solvers 
type Solver 
    real*8, pointer :: T(:,:) 

contains 
    procedure :: create 
    procedure :: solve 
end type 

contains 
    subroutine create(this,T) 
     type(Solver) :: this 
     type(Variable) :: T 

     this%T => T%val 
    end subroutine 
end module 

In meinem Programm definiere ich andere Variable für unterschiedliche physikalische Eigenschaften und verschiedenen Solvern, die mit diesen Variablen in der Art und Weise verbunden sind, die ich oben zeigte.

Ich bin neu bei OOP im Allgemeinen, also meine Frage ist, ob das ein anständiges Design ist? Vor allem aus der Sicht der Leistung. Wie vergleicht man das mit T nur ein Array und übergibt es an ein Unterprogramm solve in Bezug auf die Geschwindigkeit? Gibt es einen normalen Weg dies zu tun?

+2

Ich sehe nicht viel Punkt im Variablenzeiger. Es einfach als Dummy-Argument zu übergeben, erscheint mir natürlicher. Es ist nur ein Array-Deskriptor, nichts schlechtes für die Leistung. –

Antwort

5

Ich habe ein Jahr lang mit den OO-Funktionen von Fortran gearbeitet, hier sind einige erweiterte Kommentare, die sich als Antwort tarnen.

Wenn Sie einfach mit roher Ausführungsgeschwindigkeit beschäftigt sind, dann sind Sie wahrscheinlich im Allgemeinen (und basierend auf Argument und meiner Erfahrung statt Daten) besser, die OO-Funktionen zu vermeiden; aber dann kann in vielen Fällen das gleiche Argument angeführt werden, dass es besser ist, alles zu vermeiden, was der Sprache nach FORTRAN77 hinzugefügt wurde.

Argumente zugunsten von OO sind stärker, wenn sie auf den Problemen des Code-Designs, der Verständlichkeit, der Erweiterbarkeit und dergleichen basieren. Wenn Ihnen das wichtig ist, sollten Sie über die Verwendung der OO-Funktionen nachdenken.

Wie Vladimir bereits kommentiert hat, scheint der Variablenzeiger nicht viel Sinn zu machen. Vergessen Sie nicht, dass die meisten Fortran-Implementierungen call-by-reference aufrufen, um den Aufwand zu vermeiden, große Datenmengen zu kopieren.

Persönlich mag ich nicht die Art, wie Sie Ihre typgebundene Prozedur create definiert haben. Ich viel lieber diese Art von Operation als eine Funktion zu implementieren, so dass ich Zeilen wie diese schreiben kann:

t = solver%new() 

anstatt Ihr

call T%create() 

Hinweis: Dies ist ein Vorzug von mir, und es ist mehr eine Frage des Stils als von Effizienz oder Korrektheit. Ich bemerke, dass Sie die Absichten der Argumente für das Unterprogramm create nicht deklariert haben; Vielleicht, weil Sie nur einen Ausschnitt Ihres Codes veröffentlicht haben.

Da OO für Fortran relativ neu ist (und den meisten Menschen, die in den Bereichen arbeiten, in denen Fortran weit verbreitet ist, wohl unbekannt ist), gibt es nicht viel nützliches Material, um uns bei der Übernahme zu unterstützen.Ich würde empfehlen Scientific Software Design. Es gibt dem Thema eine gute Berichterstattung und argumentiert, warum wissenschaftliche und technische Programmierer OO einführen sollten.

+0

+1 Ich mag auch die Initialisierung als eine Funktion, wie andere Ansätze mit Konstruktoren (obwohl die Speicherzuweisung an anderer Stelle erfolgt). Manchmal ist es sogar praktisch, eine Schnittstelle zum Solwer% new mit dem Namen solver ant zu erstellen und dann 't = solver()' zu verwenden, selbst in Fällen, in denen die Initialisierung des Standard-abgeleiteten Typs nicht ausreicht. –

+0

Tanken viel für den Buch-Link, ich werde versuchen, das zu erreichen. – tiam

+0

in Ihrem 'solver% new()' Beispiel, was ist 'solver'? Ein Solver-Objekt? Oder können Sie einfach auf diese Art auf die Typ-Funktionen zugreifen? – weymouth