| Class | au_module |
| In: |
libsrc/au_module/au_module.f90
|
| Authors: | Shin-ichi Takehiro, Youhei SASAKI |
| Version: | $Id: au_module.f90 590 2013-08-19 08:48:21Z uwabami $ |
| Copyright&License: | See COPYRIGHT |
spml/au_module モジュールは 1 次元有限領域の下での流体運動を 2 次の引数のシフトされたチェビシェフ関数 T_k(2r^2/a^2-1)で 展開するスペクトル数値計算ための Fortran90 関数を提供する. このルーチンは離散化にチェビシェフ—ガウス—ラダウ格子点を適用 しており, 主に 2 次元極座標, 円筒座標, 球座標の原点の 特異性を回避しながらスペクトル計算を行うために用いることを 念頭においている.
2 次元データの 1 次元に関して同時にスペクトル計算を実行するための 関数も提供しており, 2, 3 次元領域での計算のベースも提供する.
具体的な展開の仕方は
f(r)=Σf_k r^n T_k(2r^2/a^2-1)
である. 1 次元チェビシェフデータが複数並んだ 2 次元データを 扱う際には重みの指数 n を各データ毎に設定できる.
| u_ : | チェビシェフデータ |
| g_ : | 1 次元格子点データ |
| au_ : | 1 次元チェビシェフデータが複数並んだ 2 次元データ |
| ag_ : | 1 次元格子点データが複数並んだ 2 次元データ. |
複数並んだ 2 次元データの第 1 次元の大きさは au_Initial で 設定する重みの指数の配列 nd の大きさと同じでなければならない.
_u :: チェビシェフデータ _g :: 1 次元格子点データ _au :: 1 次元チェビシェフデータが複数並んだ 2 次元データ _ag :: 1 次元格子点データが複数並んだ 2 次元データ
| au_Initial : | チェビシェフ変換の格子点数, 波数, 領域の大きさの設定 |
| g_R : | 格子点座標(R)を格納した 1 次元配列 |
| g_R_Weight : | 重み座標を格納した 1 次元配列 |
| g_u, ag_au : | チェビシェフデータから格子データへの変換 |
| u_g, au_ag : | 格子データからチェビシェフデータへの変換 |
| g_Dr_u, ag_Dr_au : | チェビシェフデータに R 微分を作用させる |
| g_Dr2_u, ag_Dr2_au : | チェビシェフデータに 2 階 R 微分を作用させる |
| a_Int_ag, a_Avr_ag : | 1 次元格子点データの並んだ 2 次元配列の積分および平均 |
| Int_g, Avr_g : | 1 次元格子点データの積分および平均 |
| au_Boundary_D, au_Boundary_N : | ディリクレ,ノイマン外側境界条件 |
| au_BoundaryTau_D, au_BoundaryTau_N : | ディリクレ,ノイマン外側境界条件 |
| au_BoundaryGrid_D, au_BoundaryGrid_N : | ディリクレ,ノイマン外側境界条件 |
| Function : | |||
| a_Avr_ag : | real(8), dimension(size(ag,1))
| ||
| ag : | real(8), dimension(:,0:), intent(in)
|
1 次元格子点データが並んだ 2 次元配列の平均
function a_Avr_ag(ag)
!
! 1 次元格子点データが並んだ 2 次元配列の平均
!
real(8), dimension(:,0:), intent(in) :: ag
!(in)入力格子点データ
real(8), dimension(size(ag,1)) :: a_Avr_ag
!(out) 平均したデータ
a_Avr_ag = a_Int_ag(ag)/sum(g_R_Weight)
end function a_Avr_ag
| Function : | |||
| a_Int_ag : | real(8), dimension(size(ag,1))
| ||
| ag : | real(8), dimension(:,0:), intent(in)
|
1 次元格子点データが並んだ 2 次元配列の積分
function a_Int_ag(ag)
!
! 1 次元格子点データが並んだ 2 次元配列の積分
!
real(8), dimension(:,0:), intent(in) :: ag
!(in)入力格子点データ
real(8), dimension(size(ag,1)) :: a_Int_ag
!(out) 積分したデータ
integer :: i
if ( size(ag,2) < im+1 ) then
call MessageNotify('E','a_Int_ag', 'The Grid points of input data too small.')
elseif ( size(ag,2) > im+1 ) then
call MessageNotify('W','a_Int_ag', 'The Grid points of input data too large.')
endif
a_Int_ag = 0.0d0
do i=0,im
a_Int_ag(:) = a_Int_ag(:) + ag(:,i)*g_R_Weight(i)
enddo
end function a_Int_ag
| Function : | |||
| ag_Dr2_au : | real(8), dimension(size(au_data,1),0:im)
| ||
| au_data : | real(8), dimension(:,0:), intent(in)
|
入力チェビシェフデータに 2 階 R 微分を作用する(2 次元配列用).
チェビシェフデータの 2 階 R 微分とは, 対応する格子点データに 2 階 R 微分を作用させたデータのチェビシェフ変換のことである.
function ag_Dr2_au(au_data)
!
! 入力チェビシェフデータに 2 階 R 微分を作用する(2 次元配列用).
!
! チェビシェフデータの 2 階 R 微分とは, 対応する格子点データに
! 2 階 R 微分を作用させたデータのチェビシェフ変換のことである.
!
!
real(8), dimension(:,0:), intent(in) :: au_data
!(in) 入力チェビシェフデータ
real(8), dimension(size(au_data,1),0:im) :: ag_Dr2_au
!(out) チェビシェフデータの 2 階 R 微分
real(8), dimension(size(au_data,1),0:size(au_data,2)-1) :: au_g
real(8), dimension(size(au_data,1),0:size(au_data,2)-1) :: au_h
! 作業配列
integer :: nm
nm=size(au_data,1)
au_g = au_Dx_au(au_data)
au_h = au_Dx_au(au_g)
ag_Dr2_au = 16*spread(g_R,1,nm)**2/ra**4 * ag_au(au_h) + 4*spread(2*nd+1,2,im+1)/ra**2 * ag_au(au_g) + spread(nd*(nd-1),2,im+1)/spread(g_R**2,1,nm) * ag_au(au_data)
end function ag_Dr2_au
| Function : | |||
| ag_Dr_au : | real(8), dimension(size(au_data,1),0:im)
| ||
| au_data : | real(8), dimension(:,0:), intent(in)
|
入力チェビシェフデータに R 微分を作用する(2 次元配列用).
チェビシェフデータの R 微分とは, 対応する格子点データに R 微分を 作用させたデータのチェビシェフ変換のことである.
function ag_Dr_au(au_data)
!
! 入力チェビシェフデータに R 微分を作用する(2 次元配列用).
!
! チェビシェフデータの R 微分とは, 対応する格子点データに R 微分を
! 作用させたデータのチェビシェフ変換のことである.
!
!
real(8), dimension(:,0:), intent(in) :: au_data
!(in) 入力チェビシェフデータ
real(8), dimension(size(au_data,1),0:im) :: ag_Dr_au
!(out) チェビシェフデータの R 微分
integer :: nm
nm=size(au_data,1)
ag_Dr_au = ag_au(au_Dx_au(au_data)) * 4*spread(g_R,1,nm)/ra**2 + spread(nd,2,im+1)/spread(g_R,1,nm) * ag_au(au_data)
end function ag_Dr_au
| Function : | |||
| ag_au : | double precision, dimension(size(au_data,1),0:im)
| ||
| au_data : | double precision, dimension(:,:), intent(in)
|
チェビシェフデータから格子データへ変換する(2 次元配列用).
function ag_au(au_data)
!
! チェビシェフデータから格子データへ変換する(2 次元配列用).
!
double precision, dimension(:,:), intent(in) :: au_data
!(in) チェビシェフデータ
double precision, dimension(size(au_data,1),0:im) :: ag_au
!(out) 格子点データ
double precision, dimension(size(au_data,1),0:im) :: au_work
! 作業用配列
integer :: m, mm, i
mm = size(au_data,1)
if ( mm /= size(nd) ) then
call MessageNotify('E','ag_au', '1st dim. of the Chebyshev data should be same as dim. of ND.')
end if
if ( size(au_data,2)-1 < km ) then
call MessageNotify('E','ag_au', 'The Chebyshev dimension of input data too small.')
elseif ( size(au_data,2)-1 > km ) then
call MessageNotify('W','ag_au', 'The Chebyshev dimension of input data too large.')
endif
au_work = 0.0
au_work(:,0:km) = au_data
do m=1,mm
do i=0,im
ag_au(m,i) = sum(CB(i,:)*au_work(m,:))*g_R(i)**nd(m)
enddo
enddo
end function ag_au
| Subroutine : | |||
| au_data : | real(8), dimension(:,0:),intent(inout)
| ||
| value : | real(8), dimension(:), intent(in), optional
|
Dirichlet 型境界条件の適用(実空間での評価, 2 次元配列用) 外側境界での値を与える.
subroutine au_BoundaryGrid_D_2d(au_data,value)
!
! Dirichlet 型境界条件の適用(実空間での評価, 2 次元配列用)
! 外側境界での値を与える.
!
real(8), dimension(:,0:),intent(inout) :: au_data
!(inout) 境界条件を適用するチェビシェフデータ(m,0:km)
real(8), dimension(:), intent(in), optional :: value
!(in) 境界値(m)
real(8), dimension(:,:,:), allocatable :: alu
integer, dimension(:,:), allocatable :: kp
real(8), dimension(size(au_data,1),0:im) :: ag_data
real(8), dimension(size(nd),0:km) :: au_work
real(8), dimension(size(au_data,1)) :: value0 ! 境界値
logical :: first = .true.
integer :: k
save :: alu, kp, first
if ( im /= km ) then
call MessageNotify('E','au_BoundaryGrid_DD', 'Chebyshev truncation and number of grid points should be same.')
endif
if ( size(au_data,2)-1 < km ) then
call MessageNotify('E','au_BoundaryGrid_DD', 'The Chebyshev dimension of input data too small.')
elseif ( size(au_data,2)-1 > km ) then
call MessageNotify('W','au_BoundaryGrid_DD', 'The Chebyshev dimension of input data too large.')
endif
if (.not. present(value)) then
value0=0
else
value0=value
endif
if ( first ) then
first = .false.
allocate(alu(size(nd),0:im,0:km),kp(size(nd),0:im))
do k=0,km
au_work = 0
au_work(:,k)=1.0
alu(:,:,k) = ag_au(au_work)
enddo
call ludecomp(alu,kp)
endif
ag_data = ag_au(au_data)
ag_data(:,0) = value0
au_data = lusolve(alu,kp,ag_data)
end subroutine au_BoundaryGrid_D_2d
| Subroutine : | |||
| u_data : | real(8), dimension(0:km),intent(inout)
| ||
| value : | real(8), intent(in), optional
|
Dirichlet 型境界条件の適用(実空間での評価, 1 次元配列用) 外側境界での値を与える.
subroutine au_BoundaryGrid_D_1d(u_data,value)
!
! Dirichlet 型境界条件の適用(実空間での評価, 1 次元配列用)
! 外側境界での値を与える.
!
real(8), dimension(0:km),intent(inout) :: u_data
!(inout) 境界条件を適用するチェビシェフデータ(0:km)
real(8), intent(in), optional :: value
!(in) 境界値
real(8), dimension(1,0:km) :: au_work
real(8), dimension(1) :: vwork ! 境界値
if (.not. present(value)) then
vwork(1)=0
else
vwork(1) = value
endif
au_work(1,:)=u_data
call au_BoundaryGrid_D_2d(au_work,vwork)
u_data=au_work(1,:)
end subroutine au_BoundaryGrid_D_1d
| Subroutine : | |||
| au_data : | real(8), dimension(:,0:),intent(inout)
| ||
| value : | real(8), dimension(:), intent(in), optional
|
外側境界 Neumann 型境界条件の適用(実空間での評価, 2 次元配列用) i=0 で勾配の値を与える.
subroutine au_BoundaryGrid_N_2d(au_data,value)
!
! 外側境界 Neumann 型境界条件の適用(実空間での評価, 2 次元配列用)
! i=0 で勾配の値を与える.
!
real(8), dimension(:,0:),intent(inout) :: au_data
!(inout) 境界条件を適用するチェビシェフデータ(m,0:km)
real(8), dimension(:), intent(in), optional :: value
!(in) 境界値(m)
real(8), dimension(:,:,:), allocatable :: alu
integer, dimension(:,:), allocatable :: kp
real(8), dimension(size(au_data,1),0:im) :: ag_data
real(8), dimension(size(nd),0:km) :: au_work
real(8), dimension(size(nd),0:im) :: ag_work
real(8), dimension(size(au_data,1)) :: value0 ! 境界値
logical :: first = .true.
integer :: k
save :: alu, kp, first
if ( im /= km ) then
call MessageNotify('E','au_BoundaryGrid_N', 'Chebyshev truncation and number of grid points should be same.')
endif
if ( size(au_data,2)-1 < km ) then
call MessageNotify('E','au_BoundaryGrid_N', 'The Chebyshev dimension of input data too small.')
elseif ( size(au_data,2)-1 > km ) then
call MessageNotify('W','au_BoundaryGrid_DN', 'The Chebyshev dimension of input data too large.')
endif
if (.not. present(value)) then
value0=0
else
value0 = value
endif
if ( first ) then
first = .false.
allocate(alu(size(nd),0:im,0:km),kp(size(nd),0:im))
do k=0,km
au_work = 0
au_work(:,k)=1.0
ag_work = ag_au(au_work)
alu(:,:,k) = ag_work
enddo
do k=0,km
au_work = 0
au_work(:,k)=1.0
ag_work = ag_Dr_au(au_work)
alu(:,0,k) = ag_work(:,0)
enddo
call ludecomp(alu,kp)
endif
ag_data = ag_au(au_data)
ag_data(:,0) = value0
au_data = lusolve(alu,kp,ag_data)
end subroutine au_BoundaryGrid_N_2d
| Subroutine : | |||
| u_data : | real(8), dimension(0:km),intent(inout)
| ||
| value : | real(8), intent(in), optional
|
外側境界 Neumann 型境界条件の適用(実空間での評価, 1 次元配列用) i=0 で勾配の値を与える.
subroutine au_BoundaryGrid_N_1d(u_data,value)
!
! 外側境界 Neumann 型境界条件の適用(実空間での評価, 1 次元配列用)
! i=0 で勾配の値を与える.
!
real(8), dimension(0:km),intent(inout) :: u_data
!(inout) 境界条件を適用するチェビシェフデータ(0:km)
real(8), intent(in), optional :: value
!(in) 境界値
real(8), dimension(1,0:km) :: au_work
real(8), dimension(1) :: vwork ! 境界値
if (.not. present(value)) then
vwork(1)=0
else
vwork(1) = value
endif
au_work(1,:)=u_data
call au_BoundaryGrid_N_2d(au_work,vwork)
u_data=au_work(1,:)
end subroutine au_BoundaryGrid_N_1d
| Subroutine : | |||
| au_data : | real(8), dimension(:,0:),intent(inout)
| ||
| value : | real(8), dimension(:), intent(in), optional
|
Dirichlet 型境界条件の適用(タウ法, 2 次元配列用) 外側境界(i=0)での値を与える.
subroutine au_BoundaryTau_D_2d(au_data,value)
!
! Dirichlet 型境界条件の適用(タウ法, 2 次元配列用)
! 外側境界(i=0)での値を与える.
!
real(8), dimension(:,0:),intent(inout) :: au_data ! データ(m,0:km)
!(inout) 境界条件を適用するチェビシェフデータ(m,0:km)
real(8), dimension(:), intent(in), optional :: value
!(in) 境界値(m)
real(8), dimension(:,:,:), allocatable :: alu
integer, dimension(:,:), allocatable :: kp
real(8), dimension(size(nd),0:km) :: au_work
real(8), dimension(size(nd),0:im) :: ag_work
real(8), dimension(size(au_data,1)) :: value0 ! 境界値
logical :: first = .true.
integer :: k
save :: alu, kp, first
if ( size(au_data,2)-1 < km ) then
call MessageNotify('E','au_BoundaryTau_D', 'The Chebyshev dimension of input data too small.')
elseif ( size(au_data,2)-1 > km ) then
call MessageNotify('W','au_BoundaryTau_D', 'The Chebyshev dimension of input data too large.')
endif
if (.not. present(value)) then
value0=0
else
value0 = value
endif
if ( first ) then
first = .false.
allocate(alu(size(nd),0:km,0:km),kp(size(nd),0:km))
alu=0.0D0
do k=0,km
alu(:,k,k) = 1.0D0
enddo
do k=0,km
au_work = 0.0
au_work(:,k) = 1.0
ag_work = ag_au(au_work)
alu(:,km,k) = ag_work(:,0)
enddo
call ludecomp(alu,kp)
endif
au_data(:,km) = value0
au_data = lusolve(alu,kp,au_data)
end subroutine au_BoundaryTau_D_2d
| Subroutine : | |||
| u_data : | real(8), dimension(0:km),intent(inout)
| ||
| value : | real(8), intent(in), optional
|
Dirichlet 型境界条件の適用(タウ法, 1 次元配列用) 両境界での値を与える.
subroutine au_BoundaryTau_D_1d(u_data,value)
!
! Dirichlet 型境界条件の適用(タウ法, 1 次元配列用)
! 両境界での値を与える.
!
real(8), dimension(0:km),intent(inout) :: u_data
!(inout) 境界条件を適用するチェビシェフデータ(0:km)
real(8), intent(in), optional :: value
!(in) 境界値
real(8), dimension(1,0:km) :: au_work
real(8), dimension(1) :: vwork ! 境界値
if (.not. present(value)) then
vwork(1)=0
else
vwork(1) = value
endif
au_work(1,:)=u_data
call au_BoundaryTau_D_2d(au_work,vwork)
u_data=au_work(1,:)
end subroutine au_BoundaryTau_D_1d
| Subroutine : | |||
| au_data : | real(8), dimension(:,0:),intent(inout)
| ||
| value : | real(8), dimension(:), intent(in), optional
|
外側境界 Neumann 型境界条件の適用(タウ法, 2 次元配列用) i=0 で勾配の値を与える.
subroutine au_BoundaryTau_N_2d(au_data,value)
!
! 外側境界 Neumann 型境界条件の適用(タウ法, 2 次元配列用)
! i=0 で勾配の値を与える.
!
real(8), dimension(:,0:),intent(inout) :: au_data
!(inout) 境界条件を適用するチェビシェフデータ(m,0:km)
real(8), dimension(:), intent(in), optional :: value
!(in) 境界値(m)
real(8), dimension(:,:,:), allocatable :: alu
integer, dimension(:,:), allocatable :: kp
real(8), dimension(size(nd),0:km) :: au_work
real(8), dimension(size(nd),0:im) :: ag_work
real(8), dimension(size(au_data,1)) :: value0 ! 境界値
logical :: first = .true.
integer :: k
save :: alu, kp, first
if ( size(au_data,2)-1 < km ) then
call MessageNotify('E','au_BoundaryTau_DN', 'The Chebyshev dimension of input data too small.')
elseif ( size(au_data,2)-1 > km ) then
call MessageNotify('W','au_BoundaryTau_DN', 'The Chebyshev dimension of input data too large.')
endif
if (.not. present(value)) then
value0=0
else
value0 = value
endif
if ( first ) then
first = .false.
allocate(alu(size(nd),0:km,0:km),kp(size(nd),0:km))
alu=0.0D0
do k=0,km
alu(:,k,k) = 1.0D0
enddo
do k=0,km
au_work = 0.0
au_work(:,k) = 1.0
ag_work = ag_Dr_au(au_work)
alu(:,km,k) = ag_work(:,0)
enddo
call ludecomp(alu,kp)
endif
au_data(:,km) = value0
au_data = lusolve(alu,kp,au_data)
end subroutine au_BoundaryTau_N_2d
| Subroutine : | |||
| u_data : | real(8), dimension(0:km),intent(inout)
| ||
| value : | real(8), intent(in), optional
|
Dirichlet/Neumann 型境界条件の適用(タウ法, 1 次元配列用) i=0 で勾配の値を与える.
subroutine au_BoundaryTau_N_1d(u_data,value)
!
! Dirichlet/Neumann 型境界条件の適用(タウ法, 1 次元配列用)
! i=0 で勾配の値を与える.
!
real(8), dimension(0:km),intent(inout) :: u_data
!(inout) 境界条件を適用するチェビシェフデータ(0:km)
real(8), intent(in), optional :: value
!(in) 境界値
real(8), dimension(1,0:km) :: au_work
real(8), dimension(1) :: vwork ! 境界値
if (.not. present(value)) then
vwork(1)=0
else
vwork(1) = value
endif
au_work(1,:)=u_data
call au_BoundaryTau_N_2d(au_work,vwork)
u_data=au_work(1,:)
end subroutine au_BoundaryTau_N_1d
| Subroutine : | |||
| au_data : | real(8), dimension(:,0:),intent(inout)
| ||
| value : | real(8), dimension(:), intent(in), optional
|
Dirichlet 型境界条件の適用(タウ法, 2 次元配列用) 外側境界(i=0)での値を与える.
subroutine au_BoundaryTau_D_2d(au_data,value)
!
! Dirichlet 型境界条件の適用(タウ法, 2 次元配列用)
! 外側境界(i=0)での値を与える.
!
real(8), dimension(:,0:),intent(inout) :: au_data ! データ(m,0:km)
!(inout) 境界条件を適用するチェビシェフデータ(m,0:km)
real(8), dimension(:), intent(in), optional :: value
!(in) 境界値(m)
real(8), dimension(:,:,:), allocatable :: alu
integer, dimension(:,:), allocatable :: kp
real(8), dimension(size(nd),0:km) :: au_work
real(8), dimension(size(nd),0:im) :: ag_work
real(8), dimension(size(au_data,1)) :: value0 ! 境界値
logical :: first = .true.
integer :: k
save :: alu, kp, first
if ( size(au_data,2)-1 < km ) then
call MessageNotify('E','au_BoundaryTau_D', 'The Chebyshev dimension of input data too small.')
elseif ( size(au_data,2)-1 > km ) then
call MessageNotify('W','au_BoundaryTau_D', 'The Chebyshev dimension of input data too large.')
endif
if (.not. present(value)) then
value0=0
else
value0 = value
endif
if ( first ) then
first = .false.
allocate(alu(size(nd),0:km,0:km),kp(size(nd),0:km))
alu=0.0D0
do k=0,km
alu(:,k,k) = 1.0D0
enddo
do k=0,km
au_work = 0.0
au_work(:,k) = 1.0
ag_work = ag_au(au_work)
alu(:,km,k) = ag_work(:,0)
enddo
call ludecomp(alu,kp)
endif
au_data(:,km) = value0
au_data = lusolve(alu,kp,au_data)
end subroutine au_BoundaryTau_D_2d
| Subroutine : | |||
| u_data : | real(8), dimension(0:km),intent(inout)
| ||
| value : | real(8), intent(in), optional
|
Dirichlet 型境界条件の適用(タウ法, 1 次元配列用) 両境界での値を与える.
subroutine au_BoundaryTau_D_1d(u_data,value)
!
! Dirichlet 型境界条件の適用(タウ法, 1 次元配列用)
! 両境界での値を与える.
!
real(8), dimension(0:km),intent(inout) :: u_data
!(inout) 境界条件を適用するチェビシェフデータ(0:km)
real(8), intent(in), optional :: value
!(in) 境界値
real(8), dimension(1,0:km) :: au_work
real(8), dimension(1) :: vwork ! 境界値
if (.not. present(value)) then
vwork(1)=0
else
vwork(1) = value
endif
au_work(1,:)=u_data
call au_BoundaryTau_D_2d(au_work,vwork)
u_data=au_work(1,:)
end subroutine au_BoundaryTau_D_1d
| Subroutine : | |||
| au_data : | real(8), dimension(:,0:),intent(inout)
| ||
| value : | real(8), dimension(:), intent(in), optional
|
外側境界 Neumann 型境界条件の適用(タウ法, 2 次元配列用) i=0 で勾配の値を与える.
subroutine au_BoundaryTau_N_2d(au_data,value)
!
! 外側境界 Neumann 型境界条件の適用(タウ法, 2 次元配列用)
! i=0 で勾配の値を与える.
!
real(8), dimension(:,0:),intent(inout) :: au_data
!(inout) 境界条件を適用するチェビシェフデータ(m,0:km)
real(8), dimension(:), intent(in), optional :: value
!(in) 境界値(m)
real(8), dimension(:,:,:), allocatable :: alu
integer, dimension(:,:), allocatable :: kp
real(8), dimension(size(nd),0:km) :: au_work
real(8), dimension(size(nd),0:im) :: ag_work
real(8), dimension(size(au_data,1)) :: value0 ! 境界値
logical :: first = .true.
integer :: k
save :: alu, kp, first
if ( size(au_data,2)-1 < km ) then
call MessageNotify('E','au_BoundaryTau_DN', 'The Chebyshev dimension of input data too small.')
elseif ( size(au_data,2)-1 > km ) then
call MessageNotify('W','au_BoundaryTau_DN', 'The Chebyshev dimension of input data too large.')
endif
if (.not. present(value)) then
value0=0
else
value0 = value
endif
if ( first ) then
first = .false.
allocate(alu(size(nd),0:km,0:km),kp(size(nd),0:km))
alu=0.0D0
do k=0,km
alu(:,k,k) = 1.0D0
enddo
do k=0,km
au_work = 0.0
au_work(:,k) = 1.0
ag_work = ag_Dr_au(au_work)
alu(:,km,k) = ag_work(:,0)
enddo
call ludecomp(alu,kp)
endif
au_data(:,km) = value0
au_data = lusolve(alu,kp,au_data)
end subroutine au_BoundaryTau_N_2d
| Subroutine : | |||
| u_data : | real(8), dimension(0:km),intent(inout)
| ||
| value : | real(8), intent(in), optional
|
Dirichlet/Neumann 型境界条件の適用(タウ法, 1 次元配列用) i=0 で勾配の値を与える.
subroutine au_BoundaryTau_N_1d(u_data,value)
!
! Dirichlet/Neumann 型境界条件の適用(タウ法, 1 次元配列用)
! i=0 で勾配の値を与える.
!
real(8), dimension(0:km),intent(inout) :: u_data
!(inout) 境界条件を適用するチェビシェフデータ(0:km)
real(8), intent(in), optional :: value
!(in) 境界値
real(8), dimension(1,0:km) :: au_work
real(8), dimension(1) :: vwork ! 境界値
if (.not. present(value)) then
vwork(1)=0
else
vwork(1) = value
endif
au_work(1,:)=u_data
call au_BoundaryTau_N_2d(au_work,vwork)
u_data=au_work(1,:)
end subroutine au_BoundaryTau_N_1d
| Subroutine : | |||
| i_in : | integer,intent(in)
| ||
| k_in : | integer,intent(in)
| ||
| r_in : | real(8),intent(in)
| ||
| nd_in(:) : | integer,intent(in)
|
チェビシェフ変換の格子点数, 波数, 領域の大きさ, 重みを設定する.
他の関数や変数を呼ぶ前に, 最初にこのサブルーチンを呼んで 初期設定をしなければならない.
subroutine au_Initial(i_in,k_in,r_in,nd_in)
!
! チェビシェフ変換の格子点数, 波数, 領域の大きさ, 重みを設定する.
!
! 他の関数や変数を呼ぶ前に, 最初にこのサブルーチンを呼んで
! 初期設定をしなければならない.
!
integer,intent(in) :: i_in !(in) 格子点数
integer,intent(in) :: k_in !(in) 切断波数
real(8),intent(in) :: r_in !(in) 外側境界の座標(半径)
integer,intent(in) :: nd_in(:) !(in) 重み r^n の指数
real(8), allocatable :: c(:), w(:) ! 重み関数
real(8) :: t
integer :: ii,kk
im=i_in
km=k_in
ra = r_in
if ( km .gt. im ) then
call MessageNotify('E','au_initial','KM shoud be less equal to IM')
endif
if ( allocated(nd) ) deallocate(nd)
allocate(nd(size(nd_in)))
nd = nd_in
if ( allocated(CF) ) deallocate(CF)
if ( allocated(CB) ) deallocate(CB)
allocate(CF(0:im,0:im),CB(0:im,0:im))
if ( allocated(C) ) deallocate(W)
if ( allocated(W) ) deallocate(W)
allocate(c(0:im),w(0:im))
c = 1.0D0
c(0) = 2.0D0
w = 2*pi/(2*im+1)
w(0) = pi/(2*im+1)
do ii=0,im
do kk=0,im
CF(kk,ii)=2.0D0/(pi*c(kk))*cos(2*pi*ii*kk/(2*im+1))*w(ii)
enddo
enddo
do kk=0,im
do ii=0,im
CB(ii,kk)=cos(2*pi*ii*kk/(2*im+1))
enddo
enddo
if ( allocated(g_R) ) deallocate(g_R)
allocate(g_R(0:im))
do ii=0,im
t = 2*pi*ii/(2*im+1)
g_R(ii) = ra*sqrt((1+cos(t))/2) ! cos(t) = 2(r/a)^2 - 1
enddo
if ( allocated(g_R_Weight) ) deallocate(g_R_Weight)
allocate(g_R_Weight(0:im))
do ii=0,im
g_R_Weight(ii) = 0.0
do kk=0,km
g_R_Weight(ii) = g_R_Weight(ii) + 1.0D0/(1.0D0/4.0D0-kk**2) * cos(2*kk*ii*pi/(2*im+1))/c(kk)
enddo
g_R_Weight(ii) = ra/(2*pi) * g_R_Weight(ii)* w(ii)
enddo
deallocate(c,w)
call MessageNotify('M','au_initial','au_module (2009/01/09) is initialized')
end subroutine au_Initial
| Function : | |||
| au_ag : | double precision, dimension(size(ag_data,1),0:km)
| ||
| ag_data : | double precision, dimension(:,:), intent(in)
|
格子データからチェビシェフデータへ変換する(2 次元配列用).
function au_ag(ag_data)
!
! 格子データからチェビシェフデータへ変換する(2 次元配列用).
!
double precision, dimension(:,:), intent(in) :: ag_data
!(in) 格子点データ
double precision, dimension(size(ag_data,1),0:km) :: au_ag
!(out) チェビシェフデータ
double precision, dimension(size(ag_data,1),0:im) :: au_work
!作業用配列
integer :: m, mm, k
mm = size(ag_data,1)
if ( mm /= size(nd) ) then
call MessageNotify('E','ag_au', '1st dim. of the Chebyshev data should be same as dim. of ND.')
end if
if ( size(ag_data,2)-1 < im ) then
call MessageNotify('E','au_ag', 'The Grid points of input data too small.')
elseif ( size(ag_data,2)-1 > im ) then
call MessageNotify('W','au_ag', 'The Grid points of input data too large.')
endif
do m=1,mm
do k=0,im
au_work(m,k) = sum(CF(k,:)*ag_data(m,:)/g_R**nd(m))
enddo
enddo
au_ag = au_work(:,0:km)
end function au_ag
| Function : | |||
| g_Dr2_u : | real(8), dimension(0:im)
| ||
| u_data : | real(8), dimension(:), intent(in)
|
入力チェビシェフデータに 2 階 R 微分を作用する(1 次元配列用).
チェビシェフデータの 2 階 R 微分とは, 対応する格子点データに 2 階 R 微分を作用させたデータのチェビシェフ変換のことである.
function g_Dr2_u(u_data)
!
! 入力チェビシェフデータに 2 階 R 微分を作用する(1 次元配列用).
!
! チェビシェフデータの 2 階 R 微分とは, 対応する格子点データに
! 2 階 R 微分を作用させたデータのチェビシェフ変換のことである.
!
!
real(8), dimension(:), intent(in) :: u_data
!(in) 入力チェビシェフデータ
real(8), dimension(0:im) :: g_Dr2_u
!(out) チェビシェフデータの 2 階 R 微分
real(8), dimension(1,size(u_data)) :: au_work
! 作業用配列
real(8), dimension(1,0:im) :: ag_work
! 作業用配列
au_work(1,:) = u_data
ag_work = ag_Dr2_au(au_work)
g_Dr2_u = ag_work(1,:)
end function g_Dr2_u
| Function : | |||
| g_Dr_u : | real(8), dimension(0:im)
| ||
| u_data : | real(8), dimension(:), intent(in)
|
入力チェビシェフデータに R 微分を作用する(1 次元配列用).
チェビシェフデータの R 微分とは, 対応する格子点データに R 微分を 作用させたデータのチェビシェフ変換のことである.
function g_Dr_u(u_data)
!
! 入力チェビシェフデータに R 微分を作用する(1 次元配列用).
!
! チェビシェフデータの R 微分とは, 対応する格子点データに R 微分を
! 作用させたデータのチェビシェフ変換のことである.
!
!
real(8), dimension(:), intent(in) :: u_data
!(in) 入力チェビシェフデータ
real(8), dimension(0:im) :: g_Dr_u
!(out) チェビシェフデータの R 微分
real(8), dimension(1,size(u_data)) :: au_work
! 作業用配列
real(8), dimension(1,0:im) :: ag_work
! 作業用配列
au_work(1,:) = u_data
ag_work = ag_Dr_au(au_work)
g_Dr_u = ag_work(1,:)
end function g_Dr_u
| Function : | |||
| g_u : | double precision, dimension(0:im)
| ||
| u_data : | double precision, dimension(:), intent(in)
|
チェビシェフデータから格子データへ変換する(1 次元配列用).
function g_u(u_data)
!
! チェビシェフデータから格子データへ変換する(1 次元配列用).
!
double precision, dimension(:), intent(in) :: u_data
!(in) チェビシェフデータ
double precision, dimension(0:im) :: g_u
!(out) 格子点データ
double precision, dimension(1,size(u_data)) :: u_work
! 作業用配列
double precision, dimension(1,0:im) :: g_work
! 作業用配列
u_work(1,:) = u_data
g_work = ag_au(u_work)
g_u = g_work(1,:)
end function g_u
| Function : | |||
| u_g : | double precision, dimension(0:km)
| ||
| g_data : | double precision, dimension(:), intent(in)
|
格子 -> スペクトル
格子データからチェビシェフデータへ変換する(1 次元配列用).
function u_g(g_data) ! 格子 -> スペクトル
!
! 格子データからチェビシェフデータへ変換する(1 次元配列用).
!
double precision, dimension(:), intent(in) :: g_data
!(in) 格子点データ
double precision, dimension(0:km) :: u_g
!(out) チェビシェフデータ
real(8), dimension(1,size(g_data)) :: ag_work
real(8), dimension(1,0:km) :: au_work
ag_work(1,:) = g_data
au_work = au_ag(ag_work)
u_g = au_work(1,:)
end function u_g