2016-10-28 16 views
1

ベクトルxを複数の配列に分割する次のコードがあります。サブルーチンの引数に基づいて定数を作成する

subroutine split(n, x, r, v, p, t) 
    implicit none 
    integer, intent(in) :: n 
    double precision, intent(in) :: x(n) 

    integer, parameter :: m = (n + 6)/10 
    ! problem here    1 
    double precision, intent(out) :: r(3, m - 1) 
    double precision, intent(out) :: v(3, m - 1) 
    double precision, intent(out) :: p(3, m) 
    double precision, intent(out) :: t(m) 
    ! code 
end subroutine split 

このコードは、メッセージ

Error: Parameter 'n' at (1) has not been declared or is a variable, which does not reduce to a constant expression 

私は手動で(n + 6)/10にすべてmを変更するが、私はよりエレガントなアプローチを求めている場合は、コードが正常にコンパイルしてコンパイルされません。

は別のアプローチとして、私はそれが不可能な

subroutine splitcore(n, m, x, r, v, p, t) 
    implicit none 
    integer, intent(in) :: n, m 
    double precision, intent(in) :: x(n) 
    double precision, intent(out) :: r(3, m - 1) 
    double precision, intent(out) :: v(3, m - 1) 
    double precision, intent(out) :: p(3, m) 
    double precision, intent(out) :: t(m) 
    ! code 
end subroutine splitcore 

subroutine split(n, x, r, v, p, t) 
    implicit none 
    integer, intent(in) :: n 
    double precision, intent(in) :: x(n) 

    integer :: m 
    double precision, intent(out) :: r(3, *) 
    double precision, intent(out) :: v(3, *) 
    double precision, intent(out) :: p(3, *) 
    double precision, intent(out) :: t(*) 

    m = (n + 6)/10 

    call splitcore(n, m, x, r, v, p, t) 
end subroutine split 
+0

値を使用して定数を初期化することはできません。 f変数。 – Wildcat

答えて

1

サブプログラムの配列宣言の配列指定は許可されています仕様式とする。

仕様式には、純粋な関数への参照を含めることができます。このような純粋な関数を使用して、mの効果的な計算を除外することができます。

純粋な用途のための明示的なインターフェイスにアクセス可能でなければならない。このような明示的なインタフェースを提供する最も簡単な方法は、モジュールに関数を入れることです(splitが既にそのようなモジュールにあった場合、同じモジュールにすることができます)。元のコードの面では

module m_mod 
    implicit none 
contains 
    pure function m(n) 
    integer, intent(in) :: n 
    integer :: m 
    m = (n + 6)/10 
    end function m 
end module m_mod 

subroutine split(n, x, r, v, p, t) 
    use m_mod 
    implicit none 
    integer, intent(in) :: n 
    double precision, intent(in) :: x(n) 

    double precision, intent(out) :: r(3, m(n) - 1) 
    double precision, intent(out) :: v(3, m(n) - 1) 
    double precision, intent(out) :: p(3, m(n)) 
    double precision, intent(out) :: t(m(n)) 
    ... 

- コンパイラはコンパイル時に評価できる効果的な何か - 変数、定数またはタイプパラメータの初期化子は、定数式である必要があります。定数式は、変数が定数ではないため、仕様式よりも多くの制限があります。たとえば、変数の値を参照できません。

むしろ明示的形状配列より、splitサブルーチンにおけるダミー変数は、おそらく行うことができるが(ランクに応じて、(:)又は(:,:)と宣言した。アレイの形の仕様は、次に取られる「(形状を仮定しました実際の引数の形状から形状計算を行う必要はありません

想定される形状の仮引数でサブルーチンを使用するには、プロシージャが参照されます。

1

ように、コードを書き換えました。 mの代わりに(n + 6)/10を使用するだけです。 Fortranでは、配列宣言の前に中間計算を定義することはできません。

変数だけで十分であるという定数(パラメータ)は必要ありません。しかし、それは許可されていません。

+0

また、 'associate'構造を使用すると、クラッタを減らすことができます。 – Wildcat

+0

@Wildcatであり、明示的な形状の仮引数の指定式として値が使用される質問の文脈ではありません。 @ francescalus、 – francescalus

+0

、右。 – Wildcat

1

問題は、実際にははありません。は配列の宣言と関係があります。以下の簡単なスニペット

subroutine split(n, x, r, v, p, t) 
    implicit none 

    integer, intent(in) :: n 
    double precision, intent(in) :: x(n) 
    integer :: m = (n + 6)/10 
end subroutine split 

もコンパイルされません。したがって、たとえmが変数として宣言されても、式(n + 6)/10で初期化することはできません。問題は(n + 6)/10が変数nを含んでいるので定数式ではないということです。


、変数m最初のを宣言し、後でそれに(n + 6)/10式の値を割り当てることは確かに可能である:

subroutine split(n, x, r, v, p, t) 
    implicit none 

    integer, intent(in) :: n 
    double precision, intent(in) :: x(n) 
    integer :: m 

    m = (n + 6)/10 
end subroutine split 

これはそれは、(対応する配列を割り当てるために、例えば、使用することができますもちろん割り付け可能と宣言することができます)。

subroutine split(n, x, r, v, p, t) 
    implicit none 

    integer, intent(in) :: n 
    double precision, intent(in) :: x(n) 
    integer :: m 

    double precision, dimension(:, :), allocatable, intent(out) :: r 
    double precision, dimension(:, :), allocatable, intent(out) :: v 
    double precision, dimension(:, :), allocatable, intent(out) :: p 
    double precision, dimension(:), allocatable, intent(out) :: t 

    m = (n + 6)/10 
    allocate (r(3, m-1)) 
    allocate (v(3, m - 1)) 
    allocate (p(3, m)) 
    allocate (t(m)) 
    ! code 
end subroutine split 
関連する問題