Class | eq_module |
In: |
libsrc/eq_module/eq_module.f90
|
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_ : | 2次元スペクトルデータ |
rp_ : | 2 次元格子点データ |
r_ : | 動径方向 1 次元格子点データ |
p_ : | 方位角方向 1 次元格子点データ |
_eq : | 2次元スペクトルデータ |
_eq_eq : | 2 つの2次元スペクトルデータ |
_rp : | 2 次元格子点データ |
_r : | 動径方向 1 次元格子点データ |
_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)格子点データの動径方向積分および平均 |
Function : | |||
AvrPhi_p : | real(8)
| ||
p : | real(8), dimension(0:im-1)
|
1 次元(Phi)格子点データの Phi 方向平均
実際には格子点データ各点毎に p_Phi_Weight をかけた総和を計算し, p_Phi_Weight の総和で割ることで平均している.
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)
| ||
rp : | real(8), dimension(jm,0:im-1)
|
2 次元格子点データの全領域平均
実際には格子点データ各点毎に p_Phi_Weight, r_Rad_Weight をかけた 総和を計算し, p_Phi_Weight*r_Rad_Weight の総和で割ることで平均している.
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)
| ||
r : | real(8), dimension(jm)
|
1 次元(Rad)格子点データの Rad 方向平均
実際には格子点データ各点毎に r_Rad_Weight をかけた総和を計算し, r_Rad_Weight の総和で割ることで平均している.
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)
| ||
p : | real(8), dimension(0:im-1)
|
1 次元(Phi)格子点データの Phi 方向積分
実際には格子点データ各点毎に p_Phi_Weight をかけた総和を計算している.
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)
| ||
rp : | real(8), dimension(jm,0:im-1)
|
2 次元格子点データの全領域積分および平均.
実際には格子点データ各点毎に p_Phi_Weight, r_Rad_Weight をかけた 総和を計算している.
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)
| ||
r : | real(8), dimension(jm)
|
1 次元(Rad)格子点データの Rad 方向積分
実際には格子点データ各点毎に r_Rad_Weight をかけた総和を計算している.
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
Function : | |||
ae : | real(DP), dimension(:,-km:), intent(in)
|
入力スペクトルデータに X 微分を作用する(2 次元データ).
スペクトルデータの X 微分とは, 対応する格子点データに X 微分を 作用させたデータのスペクトル変換のことである.
Original external subprogram is ae_module#ae_Dx_ae
Function : | |||
ae_ag : | real(DP), dimension(size(ag,1),-km:km)
| ||
ag : | real(DP), dimension(:,:), intent(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
Function : | |||
ag_ae : | real(DP), dimension(size(ae,1),0:im-1)
| ||
ae : | real(DP), dimension(:,-km:), intent(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
Subroutine : | |||
aq_data : | real(8), dimension(:,0:),intent(inout)
| ||
value : | real(8), dimension(:), intent(in), optional
|
Dirichlet 型境界条件の適用(タウ法, 2 次元配列用)
Original external subprogram is aq_module#aq_Boundary_D
Subroutine : | |||
q_data : | real(8), dimension(0:km),intent(inout)
| ||
value : | real(8), intent(in), optional
|
Dirichlet 型境界条件の適用(タウ法, 1 次元配列用)
Original external subprogram is aq_module#aq_Boundary_D
Subroutine : | |||
aq_data : | real(8), dimension(:,0:),intent(inout)
| ||
value : | real(8), dimension(:), intent(in), optional
|
外側境界 Neumann 型境界条件の適用(タウ法, 2 次元配列用)
Original external subprogram is aq_module#aq_Boundary_N
Subroutine : | |||
q_data : | real(8), dimension(0:km),intent(inout)
| ||
value : | real(8), intent(in), optional
|
Dirichlet/Neumann 型境界条件の適用(タウ法, 1 次元配列用)
Original external subprogram is aq_module#aq_Boundary_N
Function : | |||
aq_rDr_aq : | real(8), dimension(size(aq_data,1),0:size(aq_data,2)-1)
| ||
aq_data : | real(8), dimension(:,0:), intent(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
Function : | |||
aq_ag : | real(8), dimension(size(ag_data,1),0:km)
| ||
ag_data : | real(8), dimension(:,:), intent(in)
|
格子データからスペクトルデータへ変換する(2 次元配列用).
Original external subprogram is aq_module#aq_ag
Function : | |||
ag_aq : | real(8), dimension(size(aq_data,1),im)
| ||
aq_data : | real(8), dimension(:,0:), intent(in)
|
スペクトルデータから格子データへ変換する(2 次元配列用).
Original external subprogram is aq_module#ag_aq
Function : | |||
e_Dx_e : | real(DP), dimension(-km:km)
| ||
e : | real(DP), dimension(-km:km), intent(in)
|
入力スペクトルデータに X 微分を作用する(1 次元データ).
スペクトルデータの X 微分とは, 対応する格子点データに X 微分を 作用させたデータのスペクトル変換のことである.
Original external subprogram is ae_module#e_Dx_e
Function : | |||
e_g : | real(DP), dimension(-km:km)
| ||
g : | real(DP), dimension(0:im-1), intent(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
| ||
cond : | character(len=1), intent(in), optional
|
ディリクレ, ノイマン条件の適用. チェビシェフ空間での計算
実際には中で呼ばれている aq_module のサブルーチン aq_Boundary_D,, aq_Boundary_N を用いている. これらを直接呼ぶことも出来る.
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) 成分に入れ換える計算を行っている.
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)
| ||
j : | integer,intent(in)
| ||
k : | integer,intent(in)
| ||
l : | integer,intent(in)
| ||
ra_in : | real(8),intent(in)
|
スペクトル変換の格子点数, 波数, 領域の大きさを設定する.
他の関数や変数を呼ぶ前に, 最初にこのサブルーチンを呼んで 初期設定をしなければならない.
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)
| ||
eq_a : | real(8), dimension(-km:km,0:lm), intent(in)
| ||
eq_b : | real(8), dimension(-km:km,0:lm), intent(in)
|
2 つのスペクトルデータからヤコビアン J(A,B)=1/r[(∂rA)(∂φB)-(∂φA)(∂rB)] を計算する. 1/r のファクターがついていることに注意. 2 つのスペクトルデータのヤコビアンとは, 対応する 2 つの 格子点データのヤコビアンのスペクトル変換のことである.
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)
| ||
eq : | real(8), dimension(-km:km,0:lm),intent(in)
| ||
value : | real(8), dimension(-km:km), intent(in), optional
|
境界で値を与える条件(ディリクレ条件)下で, 入力スペクトルデータに逆ラプラシアン [(1/r)(∂r(r∂r)+ (1/r^2) ∂φφ]^{-1} を作用する.
タウ法による計算
スペクトルデータの逆ラプラシアンとは, 対応する格子点データに 逆ラプラシアンを作用させたデータのスペクトル変換のことである.
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)
| ||
eq : | real(8), dimension(-km:km,0:lm), intent(in)
|
入力スペクトルデータにラプラシアン
(1/r)(∂r(r∂r)+ (1/r^2) ∂φφ を作用する.
スペクトルデータのラプラシアンとは, 対応する格子点データにラプラシアンを作用させたデータの スペクトル変換のことである.
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)
| ||
eq : | real(8), dimension(-km:km,0:lm), intent(in)
|
入力スペクトルデータに動径微分(r∂r)を作用する.
スペクトルデータの動径微分とは, 対応する格子点データに動径微分を 作用させたデータのスペクトル変換のことである.
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)
| ||
eq : | real(8), dimension(-km:km,0:lm),intent(in)
| ||
value : | real(8), intent(in), optional
| ||
cond : | character(len=1), intent(in), optional
| ||
new : | logical, intent(IN), optional
|
渦度から流線を求める.
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 成分の式の代わりに境界条件を与える.
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)
| ||
er : | real(8), dimension(-km:km,jm), intent(in)
|
動径格子データからスペクトルデータへ変換する.
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)
| ||
rp : | real(8), dimension(jm,0:im-1), intent(in)
|
格子データからスペクトルデータへ変換する.
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)
| ||
eq : | real(8), dimension(-km:km,0:lm), intent(in)
|
入力スペクトルデータにラプラシアン
(1/r)(∂r(r∂r)+ (1/r^2) ∂φφ を作用する.
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
Function : | |||
er_eq : | real(8), dimension(-km:km,jm)
| ||
eq : | real(8), dimension(-km:km,0:lm), intent(in)
|
動径格子データからスペクトルデータへ変換する.
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)
| ||
rp : | real(8), dimension(jm,0:im-1), intent(in)
|
格子データからスペクトルデータへ変換する.
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)
| ||
rp : | real(8), dimension(jm,0:im-1)
|
2 次元格子点データの Rad 方向平均
実際には格子点データ各点毎に r_Rad_Weight をかけた総和を計算し, r_Rad_Weight の総和で割ることで平均している.
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)
| ||
rp : | real(8), dimension(jm,0:im-1)
|
2 次元格子点データの Rad 方向積分
実際には格子点データ各点毎に r_Rad_Weight をかけた総和を計算している.
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
Variable : | |||
g_x(:) : | real(DP), allocatable
|
Original external subprogram is ae_module#g_x
Variable : | |||
g_x_weight(:) : | real(DP), allocatable
|
Original external subprogram is ae_module#g_x_weight
Function : | |||
g_e : | real(DP), dimension(0:im-1)
| ||
e : | real(DP), dimension(-km:km), intent(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
Function : | |||
q_rDr_q : | real(8), dimension(0:km)
| ||
q_data : | real(8), dimension(:), intent(in)
|
入力スペクトルデータに r(d/dR) 微分を作用する(1 次元配列用).
スペクトルデータの r(d/dR) 微分とは, 対応する格子点データに R 微分を 作用させたデータのスペクトル変換のことである.
Original external subprogram is aq_module#q_rDr_q
Function : | |||
q_g : | real(8), dimension(0:km)
| ||
g_data : | real(8), dimension(:), intent(in)
|
格子データからスペクトルデータへ変換する(1 次元配列用).
Original external subprogram is aq_module#q_g
Function : | |||
r_AvrPhi_rp : | real(8), dimension(jm)
| ||
rp : | real(8), dimension(jm,0:im-1)
|
2 次元格子点データの Phi 方向平均
実際には格子点データ各点毎に p_Phi_Weight をかけた総和を計算し, p_Phi_Weight の総和で割ることで平均している.
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)
| ||
rp : | real(8), dimension(jm,0:im-1)
|
2 次元格子点データの Phi 方向積分
実際には格子点データ各点毎に p_Phi_Weight をかけた総和を計算している.
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
Variable : | |||
g_R(:) : | real(8), allocatable
|
Original external subprogram is aq_module#g_R
Variable : | |||
g_R_Weight(:) : | real(8), allocatable
|
Original external subprogram is aq_module#g_R_Weight
Function : | |||
g_q : | real(8), dimension(im)
| ||
q_data : | real(8), dimension(:), intent(in)
|
スペクトルデータから格子データへ変換する(1 次元配列用).
Original external subprogram is aq_module#g_q
Function : | |||
rp_eq : | real(8), dimension(jm,0:im-1)
| ||
eq : | real(8), dimension(-km:km,0:lm), intent(in)
|
スペクトルデータから格子データへ変換する.
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)
| ||
er : | real(8), dimension(-km:km,jm), intent(in)
|
スペクトルデータから格子データへ変換する.
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