0

このスレッドを開始して、関数インターフェイスの間違った仕様に起因する可能性のある問題を解決するための支援を求めていますが、修正方法がわかりません。

私が遭遇したエラーメッセージは短く、「lnsrch への引数の数または型が不正です - fmin と func の引数が一致しません。」という短いものです。

、 、およびの定義はLNSRCH、以下の内容で明確になります。FMINFUNC

以下に示すように、元のプログラム コードは、私の意図を説明するためにトリミングされています。MAINこれは、 というメイン プログラム ユニット、 という名前のモジュールMODEL、および という名前のモジュールの 3 つの部分で構成されますNEWTON。次の .f90 形式のファイルを 1 つ使用するだけで、エラー メッセージを再現できるはずです

モジュールMODELは単純な方程式系を 2 つの変数で定義するだけです ---y(1)=x(1); y(2)=x(2) --- サブプログラム内FUNC_SYSTEM1。モジュールには、将来の拡張用の抽象インターフェイスも含まれているため、現在の例の方程式システムと同じ種類の他の方程式システムを参照MODELするポインターを簡単に作成できますが、方程式システムの変数の数だけが例外です。FUNCVFUNC_SYSTEM1

MODULE model                                                             
    IMPLICIT NONE                            
    REAL, DIMENSION(:), POINTER :: fmin_fvecp
    ABSTRACT INTERFACE                              
        FUNCTION function_system_template(x) RESULT(y)     
        REAL, DIMENSION(:), INTENT(IN) :: x     
        REAL, DIMENSION(SIZE(x)) :: y           
        END FUNCTION                                
    END INTERFACE                                   
    PROCEDURE(function_system_template), POINTER :: funcv  
CONTAINS                                                          
    FUNCTION func_system1(x) Result(y)              
    IMPLICIT NONE                             
    REAL, DIMENSION(:), INTENT(IN) :: x   
    REAL, DIMENSION(size(x)) :: y                            
    y(1)=x(1)      
    y(2)=x(2)      
    END FUNCTION func_system1                           
END MODULE model

モジュールNEWTONは、プログラムの計算の鍵となる 3 つのサブプログラム間の関係を定義しBROYDENますFMIN。同時に、 ではFMIN、x(1) と x(2) のベクトルが という配列ポインターに割り当てられますFMIN_FVECP。この配列ポインタは、関数内で副次的な計算を行うために使用されますLNSRCH

MODULE newton 
    USE model
    IMPLICIT NONE
    REAL, DIMENSION(:), POINTER :: fmin_fvecp
CONTAINS
    SUBROUTINE broyden(x,fmin_fvecp,funcv)           
        IMPLICIT NONE
        REAL, DIMENSION(:), INTENT(IN) :: x
        REAL, DIMENSION(size(x)), TARGET :: y
        REAL, DIMENSION(:), POINTER :: fmin_fvecp
        PROCEDURE(function_system_template), POINTER :: funcv
        fmin_fvecp=>y
        print*,fmin(x,fmin_fvecp,funcv)        ! Get the sum of squares
        print*,fmin_fvecp                      ! Show the vector x(1) and x(2)
        print*,lnsrch(x,fmin,fmin_fvecp,funcv) ! Show the figure calculated in LNSRCH
    END SUBROUTINE broyden

    FUNCTION fmin(x,fmin_fvecp,funcv) RESULT(y)
        IMPLICIT NONE
        REAL, DIMENSION(:), INTENT(IN) :: x
        REAL, DIMENSION(:), POINTER :: fmin_fvecp
        PROCEDURE(function_system_template), POINTER :: funcv
        REAL :: y
        fmin_fvecp=funcv(x)                    ! The value of FMIN_FVECP is assigend
        fmin=dot_product(fmin_fvecp,fmin_fvecp)! when FMIN is called by BROYDEN
    END FUNCTION fmin    

    FUNCTION lnsrch(x,func,a_fvecp,b_funcv) RESULT(y)
        IMPLICIT NONE
        REAL, DIMENSION(:), INTENT(IN) :: x
        REAL, DIMENSION(:), POINTER :: a_fvecp 
        PROCEDURE(function_system_template), POINTER :: b_funcv 
        INTERFACE                              
            FUNCTION func(x,fvecp,funcp) 
            IMPORT :: function_system_template  
            IMPLICIT NONE
            REAL, DIMENSION(:), INTENT(IN) :: x
            REAL :: func
            REAL, DIMENSION(:), POINTER :: fvecp 
            PROCEDURE(function_system_template), POINTER :: funcp 
            END FUNCTION                                
        END INTERFACE
        REAL, DIMENSION(SIZE(x)) :: y
        y=x+a_fvecp+b_funcv(x)+1000.
        END FUNCTION lnsrch
    END MODULE newton

主プログラム単位は次のように定義されます。

PROGRAM main
    USE model                            
    USE newton                           
    IMPLICIT NONE  
    REAL, DIMENSION(:), allocatable :: x
    allocate(x(2))
    x=[1.,2.]                         ! The input arguments to be passed into 
    funcv=>func_system1               ! the equation system, FUNC_SYSTEM1.
    call broyden(x,fmin_fvecp,funcv)  ! Call BROYDEN to do the subsequent calcualtion
    deallocate(x)    
END PROGRAM main

長い投稿で申し訳ありません。私の質問を読んでくれてありがとう。エラーメッセージを回避するための入力を楽しみにしています。ありがとう。

リー

4

2 に答える 2

0

以下のコンテンツに示されているコードは、私が最終的に得た回避策です。追加の抽象インターフェイスを作成し、すべてのサブプログラムを 1 つのモジュールにプールします。サブルーチンBROYDENFMIN、およびは、 、 、およびLNSRCHに名前が変更されました。メインプログラムユニットでは、3 つの実験が行われ、その結果が表示されます。各実験の背後にある共通の機構は次のように機能します。方程式系が選択され、 に渡されます。その間、配列ポインターが想定されます。参照するサブプログラム ポインタと共に配列ポインタ が関数に渡され、入力引数の要素の二乗和が計算されます。最後に、指定された入力ベクトルに対して戻りますMajorSolverMiddleFunctionAssistantSolverMajorSolverMiddleFunctionAssistantSolverxMajorSolverx、二乗和におけるそれぞれのエントリの二乗の割合。

MODULE model                                                             
IMPLICIT NONE                            
REAL, DIMENSION(:), POINTER :: fvec1p, fvec2p           ! <<Note1>>           
ABSTRACT INTERFACE                                      ! <<Note1>> !
    FUNCTION functions_system(x) RESULT(y)              !           !
    IMPLICIT NONE                                       !           !
    REAL, DIMENSION(:), INTENT(IN) :: x                 !           !
    REAL, DIMENSION(SIZE(x)) :: y                       !           !
    END FUNCTION                                        !           !
END INTERFACE                                           !           !

ABSTRACT INTERFACE                                      ! <<Note2>> 
    FUNCTION middle_function_template(x,fvec_p,proc_p) RESULT(y)  
    IMPLICIT NONE                                       !
    REAL, DIMENSION(:), INTENT(IN) :: x                 !
    REAL, DIMENSION(:), POINTER :: fvec_p               !
    PROCEDURE(functions_system), POINTER :: proc_p      !
    REAL :: y                                           !
    END FUNCTION                                        !
END INTERFACE                                           !

PROCEDURE(functions_system), POINTER :: proc1p, proc2p  ! <<Note1>>   
CONTAINS                                                          
FUNCTION func_system1(x) RESULT(y)                      ! Equation system             
    IMPLICIT NONE                                       ! in two variables     
    REAL, DIMENSION(:), INTENT(IN) :: x   
    REAL, DIMENSION(size(x)) :: y                            
    y(1)=x(1)                                        
    y(2)=x(2)                                  
END FUNCTION func_system1

FUNCTION func_system2(x) RESULT(y)                      ! Equation system
    IMPLICIT NONE                                       ! in three variables  
    REAL, DIMENSION(:), INTENT(IN) :: x
    REAL, DIMENSION(size(x)) :: y
    y(1)=x(1)*10.
    y(2)=x(2)*10.
    y(3)=x(3)*10.
END FUNCTION func_system2

FUNCTION func_system3(x) RESULT(y)
    IMPLICIT NONE
    REAL, DIMENSION(:), INTENT(IN) :: x 
    REAL, DIMENSION(SIZE(x)) :: y
    REAL, DIMENSION(:), POINTER :: ans2
    proc2p=>func_system1                                ! 
    allocate(ans2(2))                                   ! <<Note2>>
    call MajorSolver(ans2,x(1:2),fvec2p,proc2p)         !
    y(1)=ans2(1)
    y(2)=ans2(2)
    y(3)=0.
    deallocate(ans2)
END FUNCTION func_system3

SUBROUTINE MajorSolver(ans,x,fvec_p,proc_p)
    IMPLICIT NONE
    REAL, DIMENSION(:), POINTER :: ans
    REAL, DIMENSION(:), INTENT(IN) :: x
    REAL, DIMENSION(:), POINTER :: fvec_p
    PROCEDURE(functions_system), POINTER :: proc_p
    PROCEDURE(middle_function_template), POINTER :: proc3p
    REAL, DIMENSION(SIZE(x)), TARGET :: y
    REAL :: z
    fvec_p=>y                                           ! pointer initialization <<Note1>>
    proc3p=>MiddleFunction                              ! <<Note2>>
    z=AssistantSolver(x,proc3p,fvec_p,proc_p) 
    ans=fvec_p**2/z          
END SUBROUTINE MajorSolver

FUNCTION MiddleFunction(x,fvec_p,proc_p)                ! <<Note2>> This function returns something
    IMPLICIT NONE                                       ! back to MajorSolver. In this    
    REAL, DIMENSION(:), INTENT(IN) :: x                 ! case, it computes the inner product.
    REAL, DIMENSION(:), POINTER :: fvec_p               ! 
    PROCEDURE(functions_system), POINTER :: proc_p
    REAL :: MiddleFunction
    fvec_p=proc_p(x)
    MiddleFunction=dot_product(fvec_p,fvec_p)
END FUNCTION

FUNCTION AssistantSolver(x,func,fvec_p,proc_p)          ! <<Note2>> 
    IMPLICIT NONE                                       ! 
    REAL, DIMENSION(:), INTENT(IN) :: x                 ! 
    procedure(middle_function_template), pointer :: func! 
    REAL, DIMENSION(:), POINTER :: fvec_p               !  
    PROCEDURE(functions_system), POINTER :: proc_p      ! 
    REAL :: AssistantSolver                             ! 
    AssistantSolver=func(x,fvec_p,proc_p)               ! 
END FUNCTION AssistantSolver                            ! 
END MODULE model

PROGRAM main
USE model
IMPLICIT NONE
REAL, DIMENSION(:), POINTER :: ans
REAL :: data2(2), data3(3)
data2=[1.,2.]
proc1p=>func_system1
allocate(ans(size(data2)))
call MajorSolver(ans,data2,fvec1p,proc1p)
write(*,'(a,2(f7.3))'),'Equations system 1: Ans= ',ans
nullify(ans)

data3=[1.,2.,3.]
proc1p=>func_system2
allocate(ans(size(data3)))
call MajorSolver(ans,data3,fvec1p,proc1p)
write(*,'(a,3(f7.3))'),'Equations system 2: Ans= ',ans
nullify(ans,proc1p)

data3=[1.,2.,3.]
proc1p=>func_system3
allocate(ans(size(data3)))                              ! 
call MajorSolver(ans,data3,fvec1p,proc1p)               ! <<Note1>>
write(*,'(a,3(f7.3))'),'Equations system 3: Ans= ',ans  ! 
! The answer is 0.059 0.941 0.000
! Because in system 3 we calculate system 1 first, the 3rd entry of 
! data3 will be ignored before passed into system 1. The result is
! [0.200 0.800] as we already know in system 1.
! Then this vector will be passed into MajorSolver again. So, 
! the answer is [0.059 0.941] = [0.2**2/(0.2**2+0.8**2) 0.8**2/(0.2**2+0.8**2)]

END PROGRAM main

結果は

Equations system 1: Ans=   0.200  0.800
Equations system 2: Ans=   0.071  0.286  0.643
Equations system 3: Ans=   0.059  0.941  0.000
Press any key to continue . . .
于 2013-04-30T03:38:13.837 に答える