IGMBaseLib 1.0

src/core/grid/STDGrid_Builder.f90

Go to the documentation of this file.
00001 
00034 module STDGrid_Builder
00035 
00036   ! モジュール引用 ; Use statements
00037   !
00038 
00039   ! 種類型パラメタ
00040   ! Kind type parameter
00041   !
00042   use dc_types, only: DP           ! 倍精度実数型. Double precision
00043 
00044   ! 数学
00045   ! Mathematic
00046   !
00047   use igmcore_math, only: PI     ! 円周率. PI.
00048 
00049   ! 線形代数
00050   ! Linear algebra
00051   !
00052   use igmcore_linear_algebra, only: &
00053     & vec_length, rotateZ
00054 
00055   ! 座標変換
00056   ! Coordinate conversion
00057   !
00058   use igmcore_coordinate_conversion, only: &
00059     & geo_to_orth_pos
00060 
00061   ! 球面三角関数
00062   ! Spherical trigonometry
00063   !
00064   use igmcore_spherical_trigonometry, only: &
00065     & spherical_penta_area, &
00066     & spherical_hex_area
00067 
00068   ! 正二十面体格子データの管理
00069   ! Manager of Icosahedral grid data
00070   !
00071   use IcGrid2D_FVM_Manager, only: &
00072     & IcGrid2D_FVM, &
00073     & paste_margin_width, calc_icosahedron_vertex, set_rcregion_bounds, &
00074     & get_IdMin, get_EffSize_Min, get_EffSize_Max, get_IcRadius, &
00075     & generate_CV5_GPindex, generate_CV6_GPindex, &
00076     & ICOSAHEDRON_VERTEX_NUM, RC_REGIONS_NUM
00077 
00078   ! 宣言文 ; Declaration statements
00079   !
00080   implicit none 
00081   private
00082 
00083   ! 公開手続き
00084   ! Public procedures
00085   !
00086   public :: construct_STDGrid
00087   public :: calc_STDGrid_GP_vertex, calc_CV_vertex, calc_CV_Area
00088   public :: project_on_sphere
00089 
00090 contains 
00091 
00092 !
00103 subroutine construct_STDGrid(icgrid)
00104 
00105   ! 宣言文 ; Declaration statements
00106   !
00107   type(IcGrid2D_FVM), intent(inout) :: icgrid
00108 
00109   ! 実行文 ; Executable statements
00110   !
00111 
00112   call calc_STDGrid_GP_vertex(icgrid)
00113   call calc_CV_vertex(icgrid)
00114   call calc_CV_Area(icgrid)
00115 
00116 end subroutine construct_STDGrid
00117 
00118 !
00133 subroutine calc_STDGrid_GP_vertex( &
00134   & icgrid &  ! (inout)
00135   & )
00136 
00137   ! 宣言文 ; Declaration statements
00138   !
00139   type(IcGrid2D_FVM), intent(inout) :: icgrid
00140 
00141   ! 作業変数
00142   ! Work variables
00143   !
00144   real(DP) :: orth_icvertex(ICOSAHEDRON_VERTEX_NUM, 3)
00145   integer :: ringID
00146   integer :: rcID
00147 
00148   integer :: EMin, EMax
00149   integer :: upper_IDs(6) = (/ 2, 3, 4, 5, 6, 2 /)
00150   integer :: lower_IDs(6) = (/ 7, 8, 9, 10, 11, 7 /)
00151 
00152   ! 実行文 ; Executable statements
00153   !
00154 
00155   !write(*,*) 'calc STDGP_vertex'
00156   ! (単位)正二十面体の 12 個の頂点の座標を計算する.
00157   call calc_icosahedron_vertex(orth_icvertex)
00158 
00159   ! 球の半径分だけ拡大する
00160   orth_icvertex(:,:) = get_IcRadius(icgrid) * orth_icvertex(:,:)
00161 
00162   ! 各矩形領域の端にあたる格子点が, 正二十面体の頂点に重なるように, 座標を設定する.
00163   do ringID=1,5
00164     ! 上側の矩形領域に対して
00165     call set_rcregion_bounds( &
00166       & self=icgrid, &                                    ! (inout)
00167       & rcID=ringID, &                                      ! (in)
00168       & top=orth_icvertex(1,:), &                           ! (in)
00169       & left=orth_icvertex(upper_IDs(ringID),:), &          ! (in)
00170       & bottom=orth_icvertex(lower_IDs(ringID), :), &       ! (in)
00171       & right=orth_icvertex(upper_IDs(ringID+1),:) )        ! (in)
00172 
00173     ! 下側の矩形領域に対して
00174     call set_rcregion_bounds( &
00175       & self=icgrid, &                                    ! (inout)
00176       & rcID=ringID+5, &                                    ! (in)
00177       & top=orth_icvertex(upper_IDs(ringID+1),:), &         ! (in)
00178       & left=orth_icvertex(lower_IDs(ringID),:), &          ! (in)
00179       & bottom=orth_icvertex(12,:), &                       ! (in)
00180       & right=orth_icvertex(lower_IDs(ringID+1),:) )        ! (in)
00181 
00182   end do
00183 
00184   ! 配列インデックスの境界に関する情報を取得
00185   EMin = get_EffSize_Min(icgrid)
00186   EMax = get_EffSize_Max(icgrid)
00187 
00188   ! 各矩形領域の端の格子点座標が決まったので, それをもとに再帰的に各矩形領域を分割していく.
00189   do rcID=1, RC_REGIONS_NUM
00190     call split_rectangle_region( &
00191       & rc_AGrid=icgrid%rcs_AGrid(rcID, EMin:EMax,EMin:EMax,:), & ! (inout)
00192       & ic_radius=get_IcRadius(icgrid), &                         ! (in)
00193       & row1=EMin, row2=EMax, &                                        ! (in)
00194       & col1=EMin, col2=EMax )                                         ! (in)
00195   end do
00196 
00197   ! のりしろを貼り合わせる
00198   call paste_margin_width(icgrid)
00199 
00200 end subroutine calc_STDGrid_GP_vertex
00201 
00202 !
00217 subroutine calc_CV_vertex(icgrid)
00218 
00219   ! 宣言文 ; Declaration statements
00220   !
00221   type(IcGrid2D_FVM), intent(inout) :: icgrid
00222 
00223   ! 作業変数
00224   ! Work variable
00225   !
00226   integer :: CV6_GPindx(6, 3, 2)
00227   integer :: CV5_GPindx(5, 3, 2)
00228   integer :: rcID, i, j, cvID
00229   integer :: EMin, EMax, idMin
00230   real(DP) :: ic_radius
00231 
00232   ! 実行文 ; Executable statemnets
00233   !
00234 
00235 !  write(*,*) 'calc STDCV_vertex'
00236 
00237   ! 配列インデックスの境界に関する情報を取得
00238   EMin = get_EffSize_Min(icgrid)
00239   EMax = get_EffSize_Max(icgrid)
00240   idMin = get_IdMin(icgrid)
00241   ! 半径の取得
00242   ic_radius = get_IcRadius(icgrid)
00243 
00244   ! 各格子点について, そのコントロールボリュームの頂点座標を計算する.
00245   do rcID=1, RC_REGIONS_NUM
00246     do j=EMin, EMax
00247       do i=EMin, EMax
00248 
00249         if ( ( rcID > 5 .and. i==EMin .and. j==EMin  ) .or. ( i==EMin .and. j== EMax ) &
00250           & .or. ( i==EMax .and. j== EMin ) .or. ( rcID <= 5 .and. i==EMax .and. j== EMax ) ) then
00251           ! 矩形領域の左右端の特異格子点のコントロールボリュームの頂点(5個)座標を求める.
00252 
00253           CV5_GPindx(:,:,:) = generate_CV5_GPindex(icgrid, GP_i=i, GP_j=j, rcID=rcID )
00254           do cvID=1,5
00255             icgrid%rcs_CV(rcID,i,j,cvID, 1:3) = &
00256               & calc_each_CV_vertex( icgrid%rcs_AGrid(rcID,:,:,:), CV5_GPindx(cvID,:,:), ic_radius, idMin )
00257           end do
00258 
00259         else if( rcID <= 5 .and. i==EMin .and. j==EMin  ) then
00260           ! 北極にある格子点が持つコントロールボリュームの頂点(5個)座標を求める.
00261           do cvID=1,5
00262              icgrid%rcs_CV(rcID,EMin,EMin, cvID, :) = &
00263                & (  icgrid%rcs_AGrid(cvID,EMin,EMin, :)    &
00264                &  + icgrid%rcs_AGrid(cvID,EMin+1,EMin, :) &
00265                &  + icgrid%rcs_AGrid(cvID,EMin,EMin+1, :) &
00266                &  ) / 3.0d0
00267 
00268              call project_on_sphere( ic_radius, icgrid%rcs_CV(rcID,i,j,cvID,:) )
00269            end do
00270 
00271         else if( rcID > 5 .and. i==EMax .and. j== EMax ) then
00272           ! 南極にある格子点が持つコントロールボリュームの頂点(5個)座標を求める.
00273           do cvID=1,5
00274              icgrid%rcs_CV(rcID,EMax,EMax, cvID, :) = &
00275                & (   icgrid%rcs_AGrid(11-cvID,EMax,EMax, :) &
00276                &   + icgrid%rcs_AGrid(11-cvID,EMax-1,EMax, :) &
00277                &   + icgrid%rcs_AGrid(11-cvID,EMax,EMax-1, :) &
00278                &  ) / 3.0d0
00279 
00280              call project_on_sphere(ic_radius, icgrid%rcs_CV(rcID,i,j,cvID,:))
00281            end do
00282 
00283         else
00284           ! 特異点以外の格子点のコントロールボリュームの頂点(6個)座標を求める.
00285           CV6_GPindx(:,:,:) =  generate_CV6_GPindex(icgrid, GP_i=i, GP_j=j, rcID=rcID )
00286 
00287           do cvID=1,6
00288             icgrid%rcs_CV(rcID,i,j,cvID, 1:3) = &
00289               & calc_each_CV_vertex(icgrid%rcs_AGrid(rcID,:,:,:), CV6_GPindx(cvID,:,:), ic_radius, idMin)
00290           end do
00291 
00292         end if
00293       end do
00294     end do
00295   end do
00296 
00297 end subroutine calc_CV_vertex
00298 
00299 !
00314 subroutine calc_CV_Area( &
00315   & icgrid &
00316   & )
00317 
00318   ! 宣言文 ; Declaration statements
00319   !
00320   type(IcGrid2D_FVM), intent(inout) :: icgrid
00321 
00322 
00323   ! 作業変数
00324   ! Work variables
00325   !
00326   integer :: rcID, i, j
00327   integer :: EMin, EMax, idMin, k
00328   real(DP) :: ic_radius
00329   real(DP) :: CV5(5, 3), CV6(6, 3)
00330 
00331   ! 実行文 ; Executable statements
00332   !
00333 
00334 !  write(*,*) 'calc CV_Area'
00335 
00336   ! 配列インデックスの境界に関する情報を取得
00337   EMin = get_EffSize_Min(icgrid)
00338   EMax = get_EffSize_Max(icgrid)
00339   ! 半径の取得
00340   ic_radius = get_IcRadius(icgrid)
00341 
00342   ! それぞれの格子点について, それに付随するコントールボリュームの面積を求める.
00343   do rcID=1,RC_REGIONS_NUM
00344     do j=EMin, EMax
00345       do i=EMin, EMax
00346         if ( ( i==EMin .and. j==EMin ) .or. ( i==EMax .and. j== EMin ) .or. &
00347           &  ( i==EMin .and. j== EMax ) .or. ( i==EMax .and. j== EMax ) ) then
00348           ! 特異格子点のコントールボリューム(頂点数 5 個)に対して
00349 
00350           CV5(:,:) = icgrid%rcs_CV(rcID,i,j,1:5, :)
00351 
00352           icgrid%rcs_CVArea(rcID,i,j) = &
00353             & spherical_penta_area( ic_radius, CV5(1,:), CV5(2,:), CV5(3,:),CV5(4,:),CV5(5,:) )
00354 
00355         else
00356           ! 通常の格子点のコントールボリューム(頂点数 6 個)に対して
00357 
00358           CV6(:,:) = icgrid%rcs_CV(rcID,i,j,1:6, :)
00359 
00360           icgrid%rcs_CVArea(rcID,i,j) = &
00361             & spherical_hex_area( ic_radius, CV6(1,:), CV6(2,:), CV6(3,:),CV6(4,:),CV6(5,:), CV6(6,:) )
00362 
00363         end if
00364       end do
00365     end do
00366   end do
00367 
00368 end subroutine calc_CV_Area
00369 
00370 
00371 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00372 !
00373 ! モジュール外非公開手続き
00374 !
00375 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00376 
00377 !
00398 recursive subroutine split_rectangle_region( &
00399   & rc_AGrid,                         &  ! (inout)
00400   & ic_radius, row1, row2, col1, col2 &  ! (in)
00401   & )
00402 
00403   ! 宣言文 ; Declaration statements
00404   !
00405   real(DP), intent(inout) :: rc_AGrid(:,:,:)
00406   real(DP), intent(in) :: ic_radius
00407   integer, intent(in) :: row1
00408   integer, intent(in) :: row2
00409   integer, intent(in) :: col1
00410   integer, intent(in) :: col2
00411 
00412   ! 作業変数
00413   ! Work variable
00414   !
00415   integer mid_row, mid_col
00416 
00417   ! 実行文 ; Executable statements
00418   !
00419 
00420   if( mod(row1+row2, 2) == 1 ) then
00421     ! 分割予定の格子点が存在しないので, 再帰処理を終了する.
00422     return
00423   end if
00424 
00425   ! 対象の矩形領域の各辺の中点と矩形領域内の中心点の座標を計算する.
00426   mid_row = (row1 + row2) / 2
00427   mid_col = (col1 + col2) / 2
00428 
00429   rc_AGrid(row1, mid_col, :) = 0.5d0 * ( rc_AGrid(row1, col1, :) + rc_AGrid(row1, col2, :) )
00430   rc_AGrid(row2, mid_col, :) = 0.5d0 * ( rc_AGrid(row2, col1, :) + rc_AGrid(row2, col2, :) )
00431   rc_AGrid(mid_row, col1, :) = 0.5d0 * ( rc_AGrid(row1, col1, :) + rc_AGrid(row2, col1, :) )
00432   rc_AGrid(mid_row, col2, :) = 0.5d0 * ( rc_AGrid(row1, col2, :) + rc_AGrid(row2, col2, :) )
00433   rc_AGrid(mid_row, mid_col, :) = 0.5d0 * ( rc_AGrid(row2, col1, :) + rc_AGrid(row1, col2, :) )
00434 
00435   ! 平面図形として矩形平面上に存在する 5 点を, 原点を中心として球面上に射影する.
00436   call project_on_sphere(ic_radius, rc_AGrid(row1, mid_col, :))
00437   call project_on_sphere(ic_radius, rc_AGrid(row2, mid_col, :))
00438   call project_on_sphere(ic_radius, rc_AGrid(mid_row, col1, :))
00439   call project_on_sphere(ic_radius, rc_AGrid(mid_row, col2, :))
00440   call project_on_sphere(ic_radius, rc_AGrid(mid_row, mid_col, :))
00441 
00442   ! 頂点の座標が決まった4つの矩形を, それぞれさらに分割する.
00443   call split_rectangle_region(rc_AGrid, ic_radius, row1, mid_row, col1, mid_col)
00444   call split_rectangle_region(rc_AGrid, ic_radius, row1, mid_row, mid_col, col2)
00445   call split_rectangle_region(rc_AGrid, ic_radius, mid_row, row2, col1, mid_col)
00446   call split_rectangle_region(rc_AGrid, ic_radius, mid_row, row2, mid_col, col2)
00447 
00448 end subroutine split_rectangle_region
00449 
00450 !
00463 subroutine project_on_sphere( &
00464   & radius, &  ! (in)
00465   & vec     &  ! (inout)
00466   & )
00467 
00468   ! 宣言文 ; Declaration statements
00469   !
00470   real(8), intent(in) :: radius    ! 正二十面体格子を内包する球の半径
00471   real(8), intent(inout) :: vec(3) ! 射影したい点の位置ベクトル
00472 
00473   ! 実行文 ; Executable statements
00474   !
00475 
00476   vec = radius / vec_length(vec) * vec
00477 end subroutine project_on_sphere
00478 
00479 !
00499 function calc_each_CV_vertex( &
00500   & rc_AGrid, GP3_index, ic_radius, idMin &  ! (in)
00501   & ) result(cv_pt)
00502 
00503   ! 宣言文 ; Declaration statements
00504   !
00505   integer, intent(in) :: idMin
00506   real(DP), intent(in) :: rc_AGrid(idMin:,idMin:,:)
00507   integer, intent(in) :: GP3_index(:,:)
00508   real(DP), intent(in) :: ic_radius
00509   real(DP) cv_pt(3)
00510 
00511   ! 作業変数
00512   ! Work variables
00513   !
00514   integer  k
00515 
00516   ! 実行文 ; Executable statements
00517   !
00518 
00519   cv_pt(:) = 0.0d0
00520 
00521   do k=1,3
00522     cv_pt(:) = cv_pt(:) + rc_AGrid(GP3_index(k, 1), GP3_index(k, 2), :)
00523   end do
00524 
00525   cv_pt(:) = cv_pt(:) / 3.0d0
00526   call project_on_sphere(ic_radius, cv_pt(:))
00527 
00528 end function calc_each_CV_vertex
00529 
00530 end module STDGrid_Builder
 All Classes Namespaces Files Functions Variables