Gibt es eine Möglichkeit, implizit ein Funktionsmittelprogramm in fortran '[duplicate] zu definieren?

Nov 19 2020

Ich versuche einige Eigenwertprobleme zu lösen. Ich benutze Gfortran. Ich habe ein Modul geschrieben, das das bisection_methodUnterprogramm enthält . In meinem Programm habe ich die secular(m,x)Funktion definiert , die ein 2D-Array mund ein Float verwendet xund das charakteristische Polynom von mat ausgibt x. dh det (m - x Id). Eines der Argumente der bisection_methodUnterroutine ist eine Funktion f, die als Funktion einer realen Eingabe und einer realen Ausgabe gedacht war. Ich möchte jedoch die 'teilweise angewendete' Funktion secular(m,_)in dieses Unterprogramm eingeben. Gibt es eine Möglichkeit, dies zu tun, ohne diese Funktion in einem Modul explizit zu definieren?

Ich kann diese Funktionen nicht explizit definieren, da ich diese Prozedur für mehrere Matrizen ausführen soll m. Außerdem kann ich den Hauptteil von nicht ändern, bisection_methodda ich ihn auch für die Funktion eines echten Arguments verwende. Gibt es in Fortran einen Ausweg?

Antworten

2 mcocdawc Nov 22 2020 at 12:38

Wie @francescalus hervorhob, möchten Sie einen Abschluss für Ihr Problem haben.

Abschlüsse werden in Fortran teilweise durch die Verwendung interner Prozeduren unterstützt, da die interne Prozedur Zugriff auf alle Variablen im umgebenden Bereich hat.¹

Angenommen, Sie möchten die Eigenwerte MIhres Codes ermitteln, könnte dies folgendermaßen strukturiert sein.²

module bisection_and_linalg
    use iso_fortran_env, only: real64
    integer, parameter :: wp = real64
    implicit none(type, external)

    abstract interface
        real(wp) pure function real_function(x)
            real(wp), intent(in) :: x
        end function
    end interface

contains

    !> Find the root of f in the interval I
    real(wp) pure function bisect(f, I)
        procedure(real_function) :: f
        real(wp) :: I(2)
        ...
    end function

    !> Evaluate the characteristic polynomial of m at x
    real(wp) pure function secular(M, x)
        real(wp), intent(in) :: M(:, :), x

        ...
    end function

    !> Get eigenvalues
    real(wp) pure function eigenvalues(M)
        real(wp), intent(in) :: M(:, :)

        ...

        ! n.b. here you can use the bisection method to
        !   find your eigenvalues.
        bisect(f, ...)

    contains

        real(wp) pure function f(x)
            ! n.b. here you have your closure.
            !   M is captured from surrounding scope.
            f = secular(M, x)
        end function
    end function

end module


¹ Die einzige Einschränkung besteht darin, dass interne Verfahren nur existieren, solange der umgebende Bereich existiert. Daher ist es leider nicht möglich, eine generische Funktion zu schreiben, die eine Funktion übernimmt und mithilfe interner Prozeduren einen Funktionszeiger auf eine teilweise angewendete Version zurückgibt. Dies ist jedoch kein Problem für Ihr Problem.

² Vielleicht wäre es besser, ein tatsächliches charakteristisches Polynom zurückzugeben. Dann könnten Sie es ableiten, zB Newton-Raphson anstelle von Halbierung zu verwenden.