Class eq_module
In: libsrc/eq_module/eq_module.f90

eq_module

Authors:Shin-ichi Takehiro, Youhei SASAKI
Version:$Id: eq_module.f90 598 2013-08-20 03:23:44Z takepiro $
Copyright&License:See COPYRIGHT

概要

spml/eq_module モジュールは 2 次元円盤領域での流体運動を スペクトル法により数値計算を実行するための Fortran90 関数を提供する. 周期的な境界条件を扱うための方位角方向へのフーリエ変換と 境界壁を扱うための動径方向の多項式変換を用いる場合の スペクトル計算のためのさまざまな関数を提供する.

内部で ae_module, aq_module を用いている. 最下部ではフーリエ変換およびチェビシェフ変換のエンジンとして ISPACK/FTPACK の Fortran77 サブルーチンを用いている.

Matsushima and Marcus (1994) の多項式に関する説明は 動径座標のスペクトル法(spectral_radial.pdf)を 参照のこと.

関数・変数の名前と型について

命名法

  • 関数名の先頭 (eq_, rp_, r_, p_) は, 返す値の形を示している.
    eq_ :2次元スペクトルデータ
    rp_ :2 次元格子点データ
    r_ :動径方向 1 次元格子点データ
    p_ :方位角方向 1 次元格子点データ
  • 関数名の間の文字列(Dr, Dp, Lapla, LaplaInv, Jacobian)は, その関数の作用を表している.
  • 関数名の最後 (_eq_eq,_eq,_rp, _r, _p) は, 入力変数のスペクトルデータ および格子点データであることを示している.
    _eq :2次元スペクトルデータ
    _eq_eq :2 つの2次元スペクトルデータ
    _rp :2 次元格子点データ
    _r :動径方向 1 次元格子点データ
    _p :方位角方向 1 次元格子点データ

各データの種類の説明

  • rp : 2 次元格子点データ.
    • 変数の種類と次元は real(8), dimension(jm,0:im-1).
    • im, jm はそれぞれ方位角, 動径座標の格子点数であり, サブルーチン eq_initial にてあらかじめ設定しておく.
    • 第 1 次元が動径座標の格子点位置番号, 第 2 次元が方位角座標の 格子点位置番号である.
  • eq : 2 次元スペクトルデータ.
    • 変数の種類と次元は real(8), dimension(-km:km,0:lm).
    • km, lm はそれぞれ方位角, 動径方向の最大波数であり, サブルーチン eq_initial にてあらかじめ設定しておく.
    • 動径スペクトルデータの格納のされ方については aq_module.f90 を参照のこと.
  • p, r : X, Y 方向 1 次元格子点データ.
    • 変数の種類と次元はそれぞれ real(8), dimension(0:im-1) および real(8), dimension(jm).
  • e, q : 1 次元スペクトルデータ.
    • 変数の種類と次元は real(8), dimension(-km:km) および real(8), dimension(0:lm).
  • ap, ar : 1 次元格子点データの並んだ 2 次元配列.
    • 変数の種類と次元は real(8), dimension(:,0:im-1) および real(8), dimension(:,jm).
  • ae, aq : 1 次元スペクトルデータの並んだ 2 次元配列.
    • 変数の種類と次元は real(8), dimension(:,-km:km) および real(8), dimension(:,0:lm).
  • eq_ で始まる関数が返す値はスペクトルデータに同じ.
  • rp_ で始まる関数が返す値は 2 次元格子点データに同じ.
  • p_, p_ で始まる関数が返す値は 1 次元格子点データに同じ.
  • スペクトルデータに対する微分等の作用とは, 対応する格子点データに 微分などを作用させたデータをスペクトル変換したものことである.

変数・手続き群の要約

初期化

eq_Initial :スペクトル変換の格子点数, 波数, 領域の大きさの設定

座標変数

p_Phi, r_Rad :格子点座標(X,Y座標)を格納した 1 次元配列
p_Phi_Weight, r_Rad_Weight :重み座標を格納した 1 次元配列
rp_Phi, rp_Rad :格子点データの XY 座標(X,Y) (格子点データ型 2 次元配列)

基本変換

rp_eq :スペクトルデータから格子データへの変換
eq_rp :格子データからスペクトルデータへの変換
ap_ae, p_e :方位角方向のスペクトルデータから格子データへの変換
ar_aq, r_q :動径方向のスペクトルデータから格子データへの変換
ae_ap, e_p :方位角方向の格子点データからスペクトルデータへの変換
aq_ar, q_r :動径方向の格子点データからスペクトルデータへの変換

微分

eq_Lapla_eq :スペクトルデータにラプラシアンを作用させる
eq_DPhi_eq, ae_DPhi_ae, e_DPhi_e :スペクトルデータに 方位角微分を作用させる
eq_RadDRad_eq, aq_RadDRad_aq, q_RadDRad_q :スペクトルデータに 動径微分を作用させる
eq_Jacobian_eq_eq :2 つのスペクトルデータからヤコビアンを計算する

境界値問題

eq_Boundary :ディリクレ, ノイマン境界条件の適用
eq_LaplaInv_eq :スペクトルデータにラプラシアンの逆変換を作用させる
eq_Vor2Strm_eq :渦度から流線を計算する

積分・平均

IntRadPhi_rp, AvrRadPhi_rp :2 次元格子点データの全領域積分および平均
r_IntPhi_rp, r_AvrPhi_rp :2 次元格子点データの方位角方向積分および平均
IntPhi_p, AvrPhi_p :1 次元(X)格子点データの方位角方向積分および平均
p_IntRad_rp, p_AvrRad_rp :2 次元格子点データの動径方向積分および平均
IntRad_r, AvrRad_r :1 次元(Y)格子点データの動径方向積分および平均

Methods

Included Modules

dc_message lumatrix ae_module aq_module

Public Instance methods

Function :
AvrPhi_p :real(8)
: (out) 平均値
p :real(8), dimension(0:im-1)
: (in) 1 次元格子点データ

1 次元(Phi)格子点データの Phi 方向平均

実際には格子点データ各点毎に p_Phi_Weight をかけた総和を計算し, p_Phi_Weight の総和で割ることで平均している.

[Source]

    function AvrPhi_p(p)
      !
      ! 1 次元(Phi)格子点データの Phi 方向平均
      !
      ! 実際には格子点データ各点毎に p_Phi_Weight をかけた総和を計算し,
      ! p_Phi_Weight の総和で割ることで平均している.
      !
      real(8), dimension(0:im-1)   :: p          !(in)  1 次元格子点データ
      real(8)                      :: AvrPhi_p     !(out) 平均値

      AvrPhi_p = IntPhi_p(p)/sum(p_Phi_weight)
    end function AvrPhi_p
Function :
AvrRadPhi_rp :real(8)
: (out) 平均値
rp :real(8), dimension(jm,0:im-1)
: (in) 2 次元格子点データ

2 次元格子点データの全領域平均

実際には格子点データ各点毎に p_Phi_Weight, r_Rad_Weight をかけた 総和を計算し, p_Phi_Weight*r_Rad_Weight の総和で割ることで平均している.

[Source]

    function AvrRadPhi_rp(rp)
      !
      ! 2 次元格子点データの全領域平均
      !
      ! 実際には格子点データ各点毎に p_Phi_Weight, r_Rad_Weight をかけた
      ! 総和を計算し, p_Phi_Weight*r_Rad_Weight の総和で割ることで平均している.
      !
      real(8), dimension(jm,0:im-1)   :: rp
      !(in)  2 次元格子点データ

      real(8)                         :: AvrRadPhi_rp
      !(out) 平均値

      AvrRadPhi_rp = IntRadPhi_rp(rp)/(sum(p_Phi_weight)*sum(r_Rad_weight))
    end function AvrRadPhi_rp
Function :
AvrRad_r :real(8)
: (out) 平均値
r :real(8), dimension(jm)
: (in) 1 次元格子点データ

1 次元(Rad)格子点データの Rad 方向平均

実際には格子点データ各点毎に r_Rad_Weight をかけた総和を計算し, r_Rad_Weight の総和で割ることで平均している.

[Source]

    function AvrRad_r(r)
      !
      ! 1 次元(Rad)格子点データの Rad 方向平均
      !
      ! 実際には格子点データ各点毎に r_Rad_Weight をかけた総和を計算し,
      ! r_Rad_Weight の総和で割ることで平均している.
      !
      real(8), dimension(jm)   :: r            !(in)  1 次元格子点データ
      real(8)                  :: AvrRad_r     !(out) 平均値

      AvrRad_r = IntRad_r(r)/sum(r_Rad_weight)
    end function AvrRad_r
Function :
IntPhi_p :real(8)
: (out) 積分値
p :real(8), dimension(0:im-1)
: (in) 1 次元格子点データ

1 次元(Phi)格子点データの Phi 方向積分

実際には格子点データ各点毎に p_Phi_Weight をかけた総和を計算している.

[Source]

    function IntPhi_p(p)
      !
      ! 1 次元(Phi)格子点データの Phi 方向積分
      !
      ! 実際には格子点データ各点毎に p_Phi_Weight をかけた総和を計算している.
      !
      real(8), dimension(0:im-1)   :: p         !(in)  1 次元格子点データ
      real(8)                      :: IntPhi_p    !(out) 積分値

      IntPhi_p = sum(p*p_Phi_Weight)
    end function IntPhi_p
Function :
IntRadPhi_rp :real(8)
: (out) 積分値
rp :real(8), dimension(jm,0:im-1)
: (in) 2 次元格子点データ

2 次元格子点データの全領域積分および平均.

実際には格子点データ各点毎に p_Phi_Weight, r_Rad_Weight をかけた 総和を計算している.

[Source]

    function IntRadPhi_rp(rp)
      !
      ! 2 次元格子点データの全領域積分および平均.
      !
      ! 実際には格子点データ各点毎に p_Phi_Weight, r_Rad_Weight をかけた
      ! 総和を計算している.
      !
      real(8), dimension(jm,0:im-1)   :: rp
      !(in)  2 次元格子点データ

      real(8)                         :: IntRadPhi_rp
      !(out) 積分値

      integer :: i, j

      IntRadPhi_rp = 0.0d0
      do i=0,im-1
         do j=1,jm
            IntRadPhi_rp = IntRadPhi_rp + rp(j,i) * r_Rad_Weight(j) * p_Phi_Weight(i)
         enddo
      enddo
    end function IntRadPhi_rp
Function :
IntRad_r :real(8)
: (out) 積分値
r :real(8), dimension(jm)
: (in) 1 次元格子点データ

1 次元(Rad)格子点データの Rad 方向積分

実際には格子点データ各点毎に r_Rad_Weight をかけた総和を計算している.

[Source]

    function IntRad_r(r)
      !
      ! 1 次元(Rad)格子点データの Rad 方向積分
      !
      ! 実際には格子点データ各点毎に r_Rad_Weight をかけた総和を計算している.
      !
      real(8), dimension(jm)   :: r          !(in)  1 次元格子点データ
      real(8)                  :: IntRad_r     !(out) 積分値

      IntRad_r = sum(r*r_Rad_Weight)
    end function IntRad_r
ae_DPhi_ae( ae ) result(ae_Dx_ae)
Function :
ae :real(DP), dimension(:,-km:), intent(in)
: (in) 入力スペクトルデータ

入力スペクトルデータに X 微分を作用する(2 次元データ).

スペクトルデータの X 微分とは, 対応する格子点データに X 微分を 作用させたデータのスペクトル変換のことである.

Original external subprogram is ae_module#ae_Dx_ae

ae_ap( ag ) result(ae_ag)
Function :
ae_ag :real(DP), dimension(size(ag,1),-km:km)
: (out) スペクトルデータ
ag :real(DP), dimension(:,:), intent(in)
: (in) 格子点データ

格子点データからスペクトルデータへ正変換する(2 次元データ用)

スペクトル正変換の定義は以下のとおり.

  格子点データ     g_j (j=-0,...,im-1)
  スペクトルデータ e_k (k=-km,...,km)

  e_0 = (1/im)\sum_{j=0}^{im-1} g_j
  e_k = (1/im)\sum_{j=0}^{im-1} g_j \cos(2\pi jk/im)       (k=1,2,...,km)
  e_{-k} = - (1/im)\sum_{j=0}^{im-1} g_j \sin(2\pi jk/im)  (k=1,2,...,km)

Original external subprogram is ae_module#ae_ag

ap_ae( ae ) result(ag_ae)
Function :
ag_ae :real(DP), dimension(size(ae,1),0:im-1)
: (out) 格子点データ
ae :real(DP), dimension(:,-km:), intent(in)
: (in) スペクトルデータ

スペクトルデータから格子点データへ逆変換する(2 次元データ用)

スペクトル逆変換の定義は以下のとおり.

  スペクトルデータ e_k (k=-km,...,km)
  格子点データ     g_j (j=-0,...,im-1)

 g_j = e_0
     + 2\sum_{k=1}^{km}(e_k\cos(2\pi jk/im) - e_{-k}\sin(2\pi jk/im))
                                                   (j=0,1,...,im-1).

Original external subprogram is ae_module#ag_ae

aq_Boundary_D( aq_data, [value] )
Subroutine :
aq_data :real(8), dimension(:,0:),intent(inout)
: (inout) 境界条件を適用するチェビシェフデータ(jmax,0:km)
value :real(8), dimension(:), intent(in), optional
: (in) 境界値(jmax)

Dirichlet 型境界条件の適用(タウ法, 2 次元配列用)

  • 外側境界(i=im)での値を与える.

Original external subprogram is aq_module#aq_Boundary_D

aq_Boundary_D( q_data, [value] )
Subroutine :
q_data :real(8), dimension(0:km),intent(inout)
: (inout) 境界条件を適用するチェビシェフデータ(0:km)
value :real(8), intent(in), optional
: (in) 境界値

Dirichlet 型境界条件の適用(タウ法, 1 次元配列用)

  • 両境界での値を与える.

Original external subprogram is aq_module#aq_Boundary_D

aq_Boundary_N( aq_data, [value] )
Subroutine :
aq_data :real(8), dimension(:,0:),intent(inout)
: (inout) 境界条件を適用するチェビシェフデータ(m,0:km)
value :real(8), dimension(:), intent(in), optional
: (in) 境界値(m)

外側境界 Neumann 型境界条件の適用(タウ法, 2 次元配列用)

  • i=im で勾配の値を与える.

Original external subprogram is aq_module#aq_Boundary_N

aq_Boundary_N( q_data, [value] )
Subroutine :
q_data :real(8), dimension(0:km),intent(inout)
: (inout) 境界条件を適用するチェビシェフデータ(0:km)
value :real(8), intent(in), optional
: (in) 境界値

Dirichlet/Neumann 型境界条件の適用(タウ法, 1 次元配列用)

  • i=0 で勾配の値を与える.

Original external subprogram is aq_module#aq_Boundary_N

aq_RadDRad_aq( aq_data ) result(aq_rDr_aq)
Function :
aq_rDr_aq :real(8), dimension(size(aq_data,1),0:size(aq_data,2)-1)
: (out) 出力スペクトルデータ
aq_data :real(8), dimension(:,0:), intent(in)
: (in) 入力スペクトルデータ

入力スペクトルデータに対して微分 r(d/dr) のスペクトル係数 を計算する(2 次元配列用).

  a_n = aq_data/sqrt(Inm),  b_n = aq_rDr_aq/sqrt(Inm)

  b_n = (2n+gamma-1)/(2n+gamma+3)b_n+2
      + (2n+gamma-1)(n+gamma+1)/(2n+gamma+3)a_n+2 + n a_n

Original external subprogram is aq_module#aq_rDr_aq

aq_ar( ag_data ) result(aq_ag)
Function :
aq_ag :real(8), dimension(size(ag_data,1),0:km)
: (out) スペクトルデータ
ag_data :real(8), dimension(:,:), intent(in)
: (in) 格子点データ

格子データからスペクトルデータへ変換する(2 次元配列用).

Original external subprogram is aq_module#aq_ag

ar_aq( aq_data ) result(ag_aq)
Function :
ag_aq :real(8), dimension(size(aq_data,1),im)
: (out) 格子点データ
aq_data :real(8), dimension(:,0:), intent(in)
: (in) スペクトルデータ

スペクトルデータから格子データへ変換する(2 次元配列用).

Original external subprogram is aq_module#ag_aq

e_DPhi_e( e ) result(e_Dx_e)
Function :
e_Dx_e :real(DP), dimension(-km:km)
: (out) 入力スペクトルデータの X 微分
e :real(DP), dimension(-km:km), intent(in)
: (in) 入力スペクトルデータ

入力スペクトルデータに X 微分を作用する(1 次元データ).

スペクトルデータの X 微分とは, 対応する格子点データに X 微分を 作用させたデータのスペクトル変換のことである.

Original external subprogram is ae_module#e_Dx_e

e_p( g ) result(e_g)
Function :
e_g :real(DP), dimension(-km:km)
: (out) スペクトルデータ
g :real(DP), dimension(0:im-1), intent(in)
: (in) 格子点データ

格子点データからスペクトルデータへ正変換する(1 次元データ用)

スペクトル正変換の定義は以下のとおり.

  格子点データ     g_j (j=-0,...,im-1)
  スペクトルデータ e_k (k=-km,...,km)

  e_0 = (1/im)\sum_{j=0}^{im-1} g_j
  e_k = (1/im)\sum_{j=0}^{im-1} g_j \cos(2\pi jk/im)       (k=1,2,...,km)
  e_{-k} = - (1/im)\sum_{j=0}^{im-1} g_j \sin(2\pi jk/im)  (k=1,2,...,km)

Original external subprogram is ae_module#e_g

Subroutine :
eq :real(8), dimension(-km:km,0:lm),intent(inout)
: 境界条件を適用するデータ. 修正された値を返す.
value :real(8), dimension(-km:km), intent(in), optional
: 境界での 値/勾配 分布を水平スペクトル変換したものを与える. 省略時は値/勾配 0 となる.
cond :character(len=1), intent(in), optional
: 境界条件. 省略時は ‘D‘
  D : 両端ディリクレ
  N : 両端ノイマン

ディリクレ, ノイマン条件の適用. チェビシェフ空間での計算

実際には中で呼ばれている aq_module のサブルーチン aq_Boundary_D,, aq_Boundary_N を用いている. これらを直接呼ぶことも出来る.

[Source]

    subroutine eq_Boundary(eq,value,cond)
      !
      ! ディリクレ, ノイマン条件の適用. チェビシェフ空間での計算
      !
      ! 実際には中で呼ばれている aq_module のサブルーチン
      ! aq_Boundary_D,, aq_Boundary_N を用いている.
      ! これらを直接呼ぶことも出来る.
      !
      real(8), dimension(-km:km,0:lm),intent(inout)      :: eq
              ! 境界条件を適用するデータ. 修正された値を返す.

      real(8), dimension(-km:km), intent(in), optional   :: value
              ! 境界での 値/勾配 分布を水平スペクトル変換したものを与える.
              ! 省略時は値/勾配 0 となる.

      character(len=1), intent(in), optional             :: cond
              ! 境界条件. 省略時は 'D'
              !   D : 両端ディリクレ
              !   N : 両端ノイマン

      if (.not. present(cond)) then
         if (present(value)) then
            call aq_Boundary_D(eq,value)
         else
            call aq_Boundary_D(eq)
         endif
         return
      endif

      select case(cond)
      case ('N')
         if (present(value)) then
            call aq_Boundary_N(eq,value)
         else
            call aq_Boundary_N(eq)
         endif
      case ('D')
         if (present(value)) then
            call aq_Boundary_D(eq,value)
         else
            call aq_Boundary_D(eq)
         endif
      case default
         call MessageNotify('E','eq_Boundaries','B.C. not supported')
      end select

    end subroutine eq_Boundary
Function :
eq_DPhi_eq :real(8), dimension(-km:km,0:lm)
eq :real(8), dimension(-km:km,0:lm), intent(in)

入力スペクトルデータに方位角微分(∂φ)を作用する.

スペクトルデータのφ微分とは, 対応する格子点データにφ微分を 作用させたデータのスペクトル変換のことである.

実際にはスペクトルデータに X 方向波数 k をかけて sin(kx) <-> cos(kx) 成分に入れ換える計算を行っている.

[Source]

    function eq_DPhi_eq(eq)
      !
      ! 入力スペクトルデータに方位角微分(∂φ)を作用する.
      !
      ! スペクトルデータのφ微分とは, 対応する格子点データにφ微分を
      ! 作用させたデータのスペクトル変換のことである.
      !
      ! 実際にはスペクトルデータに X 方向波数 k をかけて
      ! sin(kx) <-> cos(kx) 成分に入れ換える計算を行っている.
      !
      real(8), dimension(-km:km,0:lm)                :: eq_DPhi_eq
      real(8), dimension(-km:km,0:lm), intent(in)    :: eq
      integer k

      do k=-km,km
         eq_DPhi_eq(k,:)  =  -k*eq(-k,:)
      enddo
    end function eq_DPhi_eq
Subroutine :
i :integer,intent(in)
: 格子点数(X)
j :integer,intent(in)
: 格子点数(Y)
k :integer,intent(in)
: 切断波数(X)
l :integer,intent(in)
: 切断波数(Y)
ra_in :real(8),intent(in)
: 半径

スペクトル変換の格子点数, 波数, 領域の大きさを設定する.

他の関数や変数を呼ぶ前に, 最初にこのサブルーチンを呼んで 初期設定をしなければならない.

[Source]

    subroutine eq_Initial(i,j,k,l,ra_in)
      !
      ! スペクトル変換の格子点数, 波数, 領域の大きさを設定する.
      !
      ! 他の関数や変数を呼ぶ前に, 最初にこのサブルーチンを呼んで
      ! 初期設定をしなければならない.
      !
      integer,intent(in) :: i           ! 格子点数(X)
      integer,intent(in) :: j           ! 格子点数(Y)
      integer,intent(in) :: k           ! 切断波数(X)
      integer,intent(in) :: l           ! 切断波数(Y)

      real(8),intent(in) :: ra_in       ! 半径

      integer :: kk

      im = i       
       jm = j
      km = k       
       lm = l
      ra = ra_in

      allocate(md(-km:km))

      do kk=-km,km
         md(kk) = abs(kk)
      enddo

      call ae_initial(im,km,0.0D0,2*pi)
      call aq_Initial(jm,lm,ra,alpha,beta,md)

      allocate(rp_Phi(jm,0:im-1),rp_Rad(jm,0:im-1))
      rp_Phi = spread(p_Phi,1,jm)
      rp_Rad = spread(r_Rad,2,im)

      allocate(er_Rad(-km:km,jm))
      er_Rad = spread(r_Rad,1,2*km+1)

      call MessageNotify('M','eq_initial','eq_module (2013/08/20) is initialized')
    end subroutine eq_initial
Function :
eq_Jacobian_eq_eq :real(8), dimension(-km:km,0:lm)
: (out) 2 つのスペクトルデータのヤコビアン
eq_a :real(8), dimension(-km:km,0:lm), intent(in)
: (in) 1つ目の入力スペクトルデータ
eq_b :real(8), dimension(-km:km,0:lm), intent(in)
: (in) 2つ目の入力スペクトルデータ
 2 つのスペクトルデータからヤコビアン

    J(A,B)=1/r[(∂rA)(∂φB)-(∂φA)(∂rB)]

 を計算する. 1/r のファクターがついていることに注意.

 2 つのスペクトルデータのヤコビアンとは, 対応する 2 つの
 格子点データのヤコビアンのスペクトル変換のことである.

[Source]

    function eq_Jacobian_eq_eq(eq_a,eq_b)
      !
      !  2 つのスペクトルデータからヤコビアン
      !
      !     J(A,B)=1/r[(∂rA)(∂φB)-(∂φA)(∂rB)]
      !
      !  を計算する. 1/r のファクターがついていることに注意.
      !
      !  2 つのスペクトルデータのヤコビアンとは, 対応する 2 つの
      !  格子点データのヤコビアンのスペクトル変換のことである.
      !
      real(8), dimension(-km:km,0:lm)                :: eq_Jacobian_eq_eq
      !(out) 2 つのスペクトルデータのヤコビアン

      real(8), dimension(-km:km,0:lm), intent(in)    :: eq_a
      !(in) 1つ目の入力スペクトルデータ

      real(8), dimension(-km:km,0:lm), intent(in)    :: eq_b
      !(in) 2つ目の入力スペクトルデータ

      eq_Jacobian_eq_eq = eq_rp( (  rp_eq(eq_RadDRad_eq(eq_a)) * rp_eq(eq_DPhi_eq(eq_b)) -rp_eq(eq_DPhi_eq(eq_a)) * rp_eq(eq_RadDRad_eq(eq_b)) ) /rp_Rad**2)

    end function eq_Jacobian_eq_eq
Function :
eq_LaplaInv_eq :real(8), dimension(-km:km,0:lm)
: (out) スペクトルデータの逆ラプラシアン
eq :real(8), dimension(-km:km,0:lm),intent(in)
: (in) スペクトルデータ
value :real(8), dimension(-km:km), intent(in), optional
: (in) 境界値. 省略時は 0 が設定される.

境界で値を与える条件(ディリクレ条件)下で, 入力スペクトルデータに逆ラプラシアン [(1/r)(∂r(r∂r)+ (1/r^2) ∂φφ]^{-1} を作用する.

タウ法による計算

スペクトルデータの逆ラプラシアンとは, 対応する格子点データに 逆ラプラシアンを作用させたデータのスペクトル変換のことである.

[Source]

    function eq_LaplaInv_eq(eq,value)
      !
      ! 境界で値を与える条件(ディリクレ条件)下で,
      ! 入力スペクトルデータに逆ラプラシアン
      ! [(1/r)(∂r(r∂r)+ (1/r^2) ∂φφ]^{-1} を作用する.
      !
      ! タウ法による計算
      !
      ! スペクトルデータの逆ラプラシアンとは, 対応する格子点データに
      ! 逆ラプラシアンを作用させたデータのスペクトル変換のことである.
      !
      real(8), dimension(-km:km,0:lm),intent(in)  :: eq
      !(in) スペクトルデータ

      real(8), dimension(-km:km,0:lm)             :: eq_LaplaInv_eq
      !(out) スペクトルデータの逆ラプラシアン

      real(8), dimension(-km:km), intent(in), optional :: value
      !(in) 境界値. 省略時は 0 が設定される.

      real(8), dimension(:,:,:), allocatable  :: alu
      integer, dimension(:,:), allocatable    :: kp

      real(8), dimension(-km:km,0:lm)         :: eq_work
      real(8), dimension(-km:km,jm)           :: er_work
      real(8), dimension(-km:km)              :: value1       ! 境界値

      logical :: first = .true.
      integer :: k, l
      save    :: alu, kp, first

      if (.not. present(value)) then
         value1=0
      else
         value1 = value
      endif

      if ( first ) then
         first = .false.

         allocate(alu(-km:km,0:lm,0:lm),kp(-km:km,0:lm))

         do l=0,lm
            eq_work = 0.0 
             eq_work(:,l) = 1.0
            alu(:,:,l) = eq_er(er_Lapla_eq(eq_work))
         enddo

         ! 0 成分のところを 1 で埋める.
         do k=-km,km
            do l=0,md(k)-1
               alu(k,l,l) = 1.0D0
            enddo
            do l=md(k)+1,lm,2
               alu(k,l,l) = 1.0D0
            enddo
         enddo

         ! 境界条件 r=ra で値を与える.
         do k=-km,km
            do l=0,lm
               eq_work=0 
                eq_work(k,l)=1.0
               er_work=er_eq(eq_work)
               if ( mod(md(k),2) .eq. mod(lm,2) ) then
                  alu(k,lm,l) = er_work(k,jm)
               else
                  alu(k,lm-1,l) = er_work(k,jm)
               endif
            enddo
         enddo

         call ludecomp(alu,kp)
      endif

      eq_work = eq
      do k=-km,km
         if ( mod(md(k),2) .eq. mod(lm,2) ) then
            eq_work(k,lm)   = value1(k)
         else
            eq_work(k,lm-1) = value1(k)
         endif
      enddo
      eq_LaplaInv_eq = lusolve(alu,kp,eq_work)

    end function eq_LaplaInv_eq
Function :
eq_Lapla_eq :real(8), dimension(-km:km,0:lm)
: (out) スペクトルデータのラプラシアン
eq :real(8), dimension(-km:km,0:lm), intent(in)
: (in) 入力スペクトルデータ

入力スペクトルデータにラプラシアン

 (1/r)(∂r(r∂r)+ (1/r^2) ∂φφ を作用する.

スペクトルデータのラプラシアンとは, 対応する格子点データにラプラシアンを作用させたデータの スペクトル変換のことである.

[Source]

    function eq_Lapla_eq(eq)
      !
      ! 入力スペクトルデータにラプラシアン
      !  (1/r)(∂r(r∂r)+ (1/r^2) ∂φφ を作用する.
      !
      ! スペクトルデータのラプラシアンとは,
      ! 対応する格子点データにラプラシアンを作用させたデータの
      ! スペクトル変換のことである.
      !
      real(8), dimension(-km:km,0:lm)              :: eq_Lapla_eq
      !(out) スペクトルデータのラプラシアン

      real(8), dimension(-km:km,0:lm), intent(in)  :: eq
      !(in) 入力スペクトルデータ

      eq_Lapla_eq = eq_er(er_Lapla_eq(eq))

    end function eq_Lapla_eq
Function :
eq_RadDRad_eq :real(8), dimension(-km:km,0:lm)
: (out) スペクトルデータの動径微分
eq :real(8), dimension(-km:km,0:lm), intent(in)
: (in) 入力スペクトルデータ

入力スペクトルデータに動径微分(r∂r)を作用する.

スペクトルデータの動径微分とは, 対応する格子点データに動径微分を 作用させたデータのスペクトル変換のことである.

[Source]

    function eq_RadDRad_eq(eq)
      !
      ! 入力スペクトルデータに動径微分(r∂r)を作用する.
      !
      ! スペクトルデータの動径微分とは, 対応する格子点データに動径微分を
      ! 作用させたデータのスペクトル変換のことである.
      !
      real(8), dimension(-km:km,0:lm)               :: eq_RadDRad_eq
      !(out) スペクトルデータの動径微分

      real(8), dimension(-km:km,0:lm), intent(in)   :: eq
      !(in) 入力スペクトルデータ

      eq_RadDRad_eq = aq_RadDRad_aq(eq)

    end function eq_RadDRad_eq
Function :
eq_Vor2Strm_eq :real(8), dimension(-km:km,0:lm)
: (out) 出力流線関数分布
eq :real(8), dimension(-km:km,0:lm),intent(in)
: (in) 入力渦度分布
value :real(8), intent(in), optional
: 流線境界値. 境界で一定なので波数 0 成分のみ
cond :character(len=1), intent(in), optional
: (in) 境界条件スイッチ. 省略時は ‘R‘
    R    : 上側粘着条件
    F    : 上側応力なし条件
new :logical, intent(IN), optional
: (in) true だと境界条件計算用行列を強制的に新たに作る.
    default は false.

渦度から流線を求める.

Chebyshev-tau 法による計算 渦度 zeta を与えて流線 psi を求める.

   \nabla^2 \psi = \zeta,
   \psi = const. at the boundary

粘着条件

   \DP{\psi}{r} = 0 at the boundary

応力なし条件

   r\DP{}{r}(1/r\DP{\psi}{r})  = 0 at the boundary

l=0,lm 成分の式の代わりに境界条件を与える.

[Source]

    function eq_Vor2Strm_eq(eq,value,cond,new)
      !
      ! 渦度から流線を求める.
      !
      ! Chebyshev-tau 法による計算
      ! 渦度 \zeta を与えて流線 \psi を求める.
      !    \nabla^2 \psi = \zeta,
      !    \psi = const. at the boundary
      ! 粘着条件
      !    \DP{\psi}{r} = 0 at the boundary
      ! 応力なし条件
      !    r\DP{}{r}(1/r\DP{\psi}{r})  = 0 at the boundary
      !
      ! l=0,lm 成分の式の代わりに境界条件を与える.
      !
      real(8), dimension(-km:km,0:lm),intent(in)  :: eq
              !(in) 入力渦度分布

      real(8), dimension(-km:km,0:lm)             :: eq_Vor2Strm_eq
              !(out) 出力流線関数分布

      real(8), intent(in), optional               :: value
              ! 流線境界値. 境界で一定なので波数 0 成分のみ

      character(len=1), intent(in), optional  :: cond
              !(in) 境界条件スイッチ. 省略時は 'R'
              !     R    : 上側粘着条件
              !     F    : 上側応力なし条件

      logical, intent(IN), optional :: new
              !(in) true だと境界条件計算用行列を強制的に新たに作る.
              !     default は false.

      real(8), dimension(:,:,:), allocatable  :: alu, alub
      integer, dimension(:,:), allocatable    :: kp, kpb

      real(8), dimension(-km:km,0:lm)         :: eq_work
      real(8), dimension(-km:km,jm)           :: er_work
      real(8)                                 :: value1          ! 境界値
      logical                                 :: rigid = .true.

      logical :: first = .true.
      logical :: new_matrix = .false.
      integer :: k, l
      save    :: alu, kp, first
      save    :: alub, kpb

      if (.not. present(value)) then
         value1 = 0
      else
         value1 = value
      endif

      select case (cond)
      case ('R')
        rigid = .TRUE.
      case ('F')
        rigid = .FALSE.
      case default
        call MessageNotify('E','eq_Vor2Strm_eq','B.C. not supported')
      end select

      if (.not. present(new)) then
         new_matrix=.false.
      else
         new_matrix=new
      endif

      if ( first .OR. new_matrix ) then
         first = .false.

         if ( allocated(alu) ) deallocate(alu)
         if ( allocated(kp) ) deallocate(kp)
         allocate(alu(-km:km,0:lm,0:lm),kp(-km:km,0:lm))

         if ( allocated(alub) ) deallocate(alub)
         if ( allocated(kpb) ) deallocate(kpb)
         allocate(alub(-km:km,0:lm,0:lm),kpb(-km:km,0:lm))

         ! 内部条件
         do l=0,lm
            eq_work = 0.0 
             eq_work(:,l) = 1.0
            alu(:,:,l) = eq_er(er_Lapla_eq(eq_work))
         enddo

         ! 0 成分のところを 1 で埋める.
         do k=-km,km
            do l=0,md(k)-1
               alu(k,l,l) = 1.0D0
            enddo
            do l=md(k)+1,lm,2
               alu(k,l,l) = 1.0D0
            enddo
         enddo

         ! alu(:,:,nd(k)) 列は 0 なので 1 をいれておく.
         ! l=md(k) 成分は境界条件で決める.
         do k=-km,km
            if ( mod(md(k),2) .eq. mod(lm,2) ) then
               alu(k,lm,md(k)) = 1.0D0
            else
               alu(k,lm-1,md(k)) = 1.0D0
            endif
         enddo

         call ludecomp(alu,kp)

         !---- 境界条件計算用行列 -----
         alub = 0.0
         do l=0,lm
            alub(:,l,l) = 1.0D0
         enddo

         ! 運動学的条件. 流線は境界で一定
         !     l=nd(n) 成分を境界条件で決める.
         do l=0,lm
            eq_work = 0.0 
             eq_work(:,l)=1.0D0
            er_work = er_eq(eq_work)
            do k=-km,km
               alub(k,md(k),l) = er_work(k,jm)
            enddo
         enddo

         ! 力学的条件粘着条件
         !     l=lm or lm-1 成分を境界条件で決める.
         if ( rigid ) then
            do l=0,lm
               eq_work = 0.0 
                 eq_work(:,l)=1.0D0
               er_work=er_eq(eq_RadDRad_eq(eq_work))/er_Rad
               do k=-km,km
                  if ( mod(md(k),2) .eq. mod(lm,2) ) then
                     alub(k,lm,l) = er_work(k,jm)
                  else
                     alub(k,lm-1,l) = er_work(k,jm)
                  endif
               end do
            enddo
         else
            do l=0,lm
               eq_work = 0.0 
                eq_work(:,l)=1.0D0
               er_work=er_eq(eq_RadDRad_eq(eq_RadDRad_eq(eq_work)) -2*eq_RadDRad_eq(eq_work))/er_Rad**2
               do k=-km,km
                  if ( mod(md(k),2) .eq. mod(lm,2) ) then
                     alub(k,lm,l) = er_work(k,jm)
                  else
                     alub(k,lm-1,l) = er_work(k,jm)
                  endif
               end do
            enddo
         endif

         call ludecomp(alub,kpb)

         if ( rigid ) then
            call MessageNotify('M','eq_Vor2Strm_eq', 'Matrix to apply rigid b.c. newly produced.')
         else
            call MessageNotify('M','eq_Vor2Strm_eq', 'Matrix to apply stress-free b.c. newly produced.')
         endif
      endif

      ! 内部領域計算
      eq_work = eq
      eq_work = lusolve(alu,kp,eq_work)

      ! 境界条件計算
      do k=-km,km
         eq_work(k,md(k)) = 0.0D0
         if ( mod(md(k),2) .eq. mod(lm,2) ) then
            eq_work(k,lm)   = 0.0D0
         else
            eq_work(k,lm-1) = 0.0D0
         endif
      enddo
      eq_work(0,0)   = value1*2.0D0     ! 運動学的条件. 波数 0 は重み 1/2

      eq_Vor2Strm_eq = lusolve(alub,kpb,eq_work)

    end function eq_Vor2Strm_eq
Function :
eq_er :real(8), dimension(-km:km,0:lm)
: (out) スペクトルデータ
er :real(8), dimension(-km:km,jm), intent(in)
: (in) 格子点データ

動径格子データからスペクトルデータへ変換する.

[Source]

    function eq_er(er)
      !
      ! 動径格子データからスペクトルデータへ変換する.
      !
      real(8), dimension(-km:km,0:lm)              :: eq_er
      !(out) スペクトルデータ

      real(8), dimension(-km:km,jm), intent(in)    :: er
      !(in) 格子点データ

      eq_er = aq_ar(er)

    end function eq_er
Function :
eq_rp :real(8), dimension(-km:km,0:lm)
: (out) スペクトルデータ
rp :real(8), dimension(jm,0:im-1), intent(in)
: (in) 格子点データ

格子データからスペクトルデータへ変換する.

[Source]

    function eq_rp(rp)
      !
      ! 格子データからスペクトルデータへ変換する.
      !
      real(8), dimension(-km:km,0:lm)              :: eq_rp
      !(out) スペクトルデータ

      real(8), dimension(jm,0:im-1), intent(in)    :: rp
      !(in) 格子点データ

      real(8), dimension(-km:km,jm)                :: er
      real(8), dimension(jm,-km:km)                :: re

      integer :: j, k
      
      !eq_rp = aq_ar(transpose(ae_ap(rp)))
      !
      ! 本来上の書き方でいいはずだが, gfortran で通らないので下のように書き直す
      !
      re = ae_ap(rp)
      do j=1,jm
         do k=-km,km
            er(k,j) = re(j,k)
         enddo
      enddo
      eq_rp = aq_ar(er)

    end function eq_rp
Function :
er_Lapla_eq :real(8), dimension(-km:km,jm)
: (out) スペクトルデータのラプラシアン
eq :real(8), dimension(-km:km,0:lm), intent(in)
: (in) 入力スペクトルデータ

入力スペクトルデータにラプラシアン

 (1/r)(∂r(r∂r)+ (1/r^2) ∂φφ を作用する.

[Source]

    function er_Lapla_eq(eq)
      !
      ! 入力スペクトルデータにラプラシアン
      !  (1/r)(∂r(r∂r)+ (1/r^2) ∂φφ を作用する.
      !
      real(8), dimension(-km:km,jm)                :: er_Lapla_eq
      !(out) スペクトルデータのラプラシアン

      real(8), dimension(-km:km,0:lm), intent(in)  :: eq
      !(in) 入力スペクトルデータ

      real(8), dimension(-km:km,0:lm)              :: eq_work

      integer k

      do k=-km,km
         eq_work(k,:) = -k**2 * eq(k,:)
      enddo

      er_Lapla_eq = er_eq(eq_work + eq_RadDRad_eq(eq_RadDRad_eq(eq)))/er_Rad**2

    end function er_Lapla_eq
er_Rad
Variable :
er_Rad :real(8), dimension(:,:), allocatable
Function :
er_eq :real(8), dimension(-km:km,jm)
: (out) 格子点データ
eq :real(8), dimension(-km:km,0:lm), intent(in)
: (out) スペクトルデータ

動径格子データからスペクトルデータへ変換する.

[Source]

    function er_eq(eq)
      !
      ! 動径格子データからスペクトルデータへ変換する.
      !
      real(8), dimension(-km:km,jm)                :: er_eq
      !(out) 格子点データ

      real(8), dimension(-km:km,0:lm), intent(in)  :: eq
      !(out) スペクトルデータ

      er_eq = ar_aq(eq)

    end function er_eq
Function :
er_rp :real(8), dimension(-km:km,jm)
: (out) スペクトルデータ
rp :real(8), dimension(jm,0:im-1), intent(in)
: (in) 格子点データ

格子データからスペクトルデータへ変換する.

[Source]

    function er_rp(rp)
      !
      ! 格子データからスペクトルデータへ変換する.
      !
      real(8), dimension(-km:km,jm)                :: er_rp
      !(out) スペクトルデータ

      real(8), dimension(jm,0:im-1), intent(in)    :: rp
      !(in) 格子点データ

      real(8), dimension(jm,-km:km)                :: re

      integer :: j, k

      !er_rp = transpose(ae_ap(rp))
      !
      ! 本来上の書き方でいいはずだが, gfortran で通らないので下のように書き直す
      !
      re = ae_ap(rp)
      do j=1,jm
         do k=-km,km
            er_rp(k,j) = re(j,k)
         enddo
      enddo

    end function er_rp
Function :
p_AvrRad_rp :real(8), dimension(0:im-1)
: (out) 平均された 1 次元(Phi)格子点
rp :real(8), dimension(jm,0:im-1)
: (in) 2 次元格子点データ

2 次元格子点データの Rad 方向平均

実際には格子点データ各点毎に r_Rad_Weight をかけた総和を計算し, r_Rad_Weight の総和で割ることで平均している.

[Source]

    function p_AvrRad_rp(rp)
      !
      ! 2 次元格子点データの Rad 方向平均
      !
      ! 実際には格子点データ各点毎に r_Rad_Weight をかけた総和を計算し,
      ! r_Rad_Weight の総和で割ることで平均している.
      !
      real(8), dimension(jm,0:im-1)   :: rp
      !(in) 2 次元格子点データ

      real(8), dimension(0:im-1)      :: p_AvrRad_rp
      !(out) 平均された 1 次元(Phi)格子点

      p_AvrRad_rp = p_IntRad_rp(rp)/sum(r_Rad_weight)
    end function p_AvrRad_rp
Function :
p_IntRad_rp :real(8), dimension(0:im-1)
: (out) 積分された 1 次元(Phi)格子点データ
rp :real(8), dimension(jm,0:im-1)
: (in) 2 次元格子点データ

2 次元格子点データの Rad 方向積分

実際には格子点データ各点毎に r_Rad_Weight をかけた総和を計算している.

[Source]

    function p_IntRad_rp(rp)
      !
      ! 2 次元格子点データの Rad 方向積分
      !
      ! 実際には格子点データ各点毎に r_Rad_Weight をかけた総和を計算している.
      !
      real(8), dimension(jm,0:im-1)   :: rp
      !(in)  2 次元格子点データ

      real(8), dimension(0:im-1)      :: p_IntRad_rp
      !(out) 積分された 1 次元(Phi)格子点データ

      integer :: j
      ! 作業変数

      p_IntRad_rp = 0.0d0
      do j=1,jm
         p_IntRad_rp(:) = p_IntRad_rp(:) + rp(j,:) * r_Rad_Weight(j)
      enddo
    end function p_IntRad_rp
p_Phi
Variable :
g_x(:) :real(DP), allocatable
: 格子点座標(X)を格納した 1 次元配列.

Original external subprogram is ae_module#g_x

p_Phi_weight
Variable :
g_x_weight(:) :real(DP), allocatable
: 重み座標を格納した 1 次元配列. X 方向の格子点の間隔が格納してある.

Original external subprogram is ae_module#g_x_weight

p_e( e ) result(g_e)
Function :
g_e :real(DP), dimension(0:im-1)
: (out) 格子点データ
e :real(DP), dimension(-km:km), intent(in)
: (in) スペクトルデータ

スペクトルデータから格子点データへ逆変換する(1 次元データ用)

スペクトル逆変換の定義は以下のとおり.

  スペクトルデータ e_k (k=-km,...,km)
  格子点データ     g_j (j=-0,...,im-1)

 g_j = e_0
     + 2\sum_{k=1}^{km}(e_k\cos(2\pi jk/im) - e_{-k}\sin(2\pi jk/im))
                                                   (j=0,1,...,im-1).

Original external subprogram is ae_module#g_e

q_RadDRad_q( q_data ) result(q_rDr_q)
Function :
q_rDr_q :real(8), dimension(0:km)
: (out) チェビシェフデータの R 微分
q_data :real(8), dimension(:), intent(in)
: (in) 入力チェビシェフデータ

入力スペクトルデータに r(d/dR) 微分を作用する(1 次元配列用).

スペクトルデータの r(d/dR) 微分とは, 対応する格子点データに R 微分を 作用させたデータのスペクトル変換のことである.

Original external subprogram is aq_module#q_rDr_q

q_r( g_data ) result(q_g)
Function :
q_g :real(8), dimension(0:km)
: (out) スペクトルデータ
g_data :real(8), dimension(:), intent(in)
: (in) 格子点データ

格子データからスペクトルデータへ変換する(1 次元配列用).

Original external subprogram is aq_module#q_g

Function :
r_AvrPhi_rp :real(8), dimension(jm)
: (out) 平均された 1 次元(Rad)格子点
rp :real(8), dimension(jm,0:im-1)
: (in) 2 次元格子点データ

2 次元格子点データの Phi 方向平均

実際には格子点データ各点毎に p_Phi_Weight をかけた総和を計算し, p_Phi_Weight の総和で割ることで平均している.

[Source]

    function r_AvrPhi_rp(rp)
      !
      ! 2 次元格子点データの Phi 方向平均
      !
      ! 実際には格子点データ各点毎に p_Phi_Weight をかけた総和を計算し,
      ! p_Phi_Weight の総和で割ることで平均している.
      !
      real(8), dimension(jm,0:im-1)   :: rp
      !(in) 2 次元格子点データ

      real(8), dimension(jm)          :: r_AvrPhi_rp
      !(out) 平均された 1 次元(Rad)格子点

      r_AvrPhi_rp = r_IntPhi_rp(rp)/sum(p_Phi_weight)
    end function r_AvrPhi_rp
Function :
r_IntPhi_rp :real(8), dimension(jm)
: (out) 積分された 1 次元(Rad)格子点データ
rp :real(8), dimension(jm,0:im-1)
: (in) 2 次元格子点データ

2 次元格子点データの Phi 方向積分

実際には格子点データ各点毎に p_Phi_Weight をかけた総和を計算している.

[Source]

    function r_IntPhi_rp(rp)
      !
      ! 2 次元格子点データの Phi 方向積分
      !
      ! 実際には格子点データ各点毎に p_Phi_Weight をかけた総和を計算している.
      !
      real(8), dimension(jm,0:im-1)   :: rp
      !(in) 2 次元格子点データ

      real(8), dimension(jm)          :: r_IntPhi_rp
      !(out) 積分された 1 次元(Rad)格子点データ

      integer :: i
      ! 作業変数

      r_IntPhi_rp = 0.0d0
      do i=0,im-1
         r_IntPhi_rp(:) = r_IntPhi_rp(:) + rp(:,i) * p_Phi_Weight(i)
      enddo
    end function r_IntPhi_rp
r_Rad
Variable :
g_R(:) :real(8), allocatable
: ガウス—ラダウ格子点

Original external subprogram is aq_module#g_R

r_Rad_Weight
Variable :
g_R_Weight(:) :real(8), allocatable
: ガウス重み

Original external subprogram is aq_module#g_R_Weight

r_q( q_data ) result(g_q)
Function :
g_q :real(8), dimension(im)
: (out) 格子点データ
q_data :real(8), dimension(:), intent(in)
: (in) スペクトルデータ

スペクトルデータから格子データへ変換する(1 次元配列用).

Original external subprogram is aq_module#g_q

rp_Phi
Variable :
rp_Phi :real(8), dimension(:,:), allocatable
rp_Rad
Variable :
rp_Rad :real(8), dimension(:,:), allocatable
Function :
rp_eq :real(8), dimension(jm,0:im-1)
: (out) 格子点データ
eq :real(8), dimension(-km:km,0:lm), intent(in)
: (in) スペクトルデータ

スペクトルデータから格子データへ変換する.

[Source]

    function rp_eq(eq)
      !
      ! スペクトルデータから格子データへ変換する.
      !
      real(8), dimension(jm,0:im-1)                :: rp_eq
      !(out) 格子点データ

      real(8), dimension(-km:km,0:lm), intent(in)  :: eq
      !(in) スペクトルデータ

      real(8), dimension(-km:km,jm)                :: er
      real(8), dimension(jm,-km:km)                :: re

      integer :: j, k
      
      !rp_eq = ap_ae(transpose(ar_aq(eq)))
      !
      ! 本来上の書き方でいいはずだが, gfortran で通らないので下のように書き直す
      !
      er = ar_aq(eq)
      do j=1,jm
         do k=-km,km
            re(j,k) = er(k,j)
         enddo
      enddo
      rp_eq = ap_ae(re)

    end function rp_eq
Function :
rp_er :real(8), dimension(jm,0:im-1)
: (out) 格子点データ
er :real(8), dimension(-km:km,jm), intent(in)
: (in) スペクトルデータ

スペクトルデータから格子データへ変換する.

[Source]

    function rp_er(er)
      !
      ! スペクトルデータから格子データへ変換する.
      !
      real(8), dimension(jm,0:im-1)              :: rp_er
      !(out) 格子点データ

      real(8), dimension(-km:km,jm), intent(in)  :: er
      !(in) スペクトルデータ

      real(8), dimension(jm,-km:km)              :: re

      integer :: j, k

      !rp_er = ap_ae(transpose(er))
      !
      ! 本来上の書き方でいいはずだが, gfortran で通らないので下のように書き直す
      !
      do j=1,jm
         do k=-km,km
            re(j,k) = er(k,j)
         enddo
      enddo
      rp_er = ap_ae(re)

    end function rp_er