00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 subroutine psmile_init_gauss_data (grid_id, nbr_points_per_lat)
00084
00085 use psmile, only : grids
00086
00087 implicit none
00088
00089 integer, intent(in) :: grid_id
00090 integer, intent(in) :: nbr_points_per_lat(:)
00091
00092 integer :: i
00093
00094 allocate (grids(grid_id)%reduced_gauss_data%nbr_points_per_lat(size (nbr_points_per_lat)), &
00095 grids(grid_id)%reduced_gauss_data%global_lat_offsets(size (nbr_points_per_lat)))
00096
00097 grids(grid_id)%reduced_gauss_data%nbr_points_per_lat = nbr_points_per_lat
00098
00099 grids(grid_id)%reduced_gauss_data%global_lat_offsets(1) = 0
00100
00101 do i = 2, size (nbr_points_per_lat)
00102 grids(grid_id)%reduced_gauss_data%global_lat_offsets(i) = &
00103 grids(grid_id)%reduced_gauss_data%global_lat_offsets(i-1) + nbr_points_per_lat(i-1)
00104 enddo
00105
00106 end subroutine psmile_init_gauss_data
00107
00108
00109
00110 subroutine psmile_gauss_gen_aux_grid (grid_id)
00111
00112 use psmile_common, only : ndim_3d
00113 use psmile, only : grids, MPI_REAL, psmile_assert
00114
00115 implicit none
00116
00117 integer, intent(in) :: grid_id
00118
00119 double precision :: max_size_grid_cell (ndim_3d)
00120 double precision :: local_partition_extent (2, ndim_3d)
00121
00122 integer :: aux_grid_size (ndim_3d)
00123
00124 double precision :: dxyz(ndim_3d)
00125
00126 double precision, pointer :: k_corners_dble(:)
00127 real, pointer :: k_corners_real(:)
00128
00129 integer :: i, j
00130
00131
00132 max_size_grid_cell(1) = 360.d0 / &
00133 dble (maxval (grids(grid_id)%reduced_gauss_data%nbr_points_per_lat))
00134
00135 max_size_grid_cell(2) = 180.d0 / &
00136 dble ( size (grids(grid_id)%reduced_gauss_data%nbr_points_per_lat))
00137
00138 if (grids (grid_id)%corner_pointer%corner_datatype == MPI_REAL) then
00139
00140 k_corners_real => grids (grid_id)%corner_pointer%corners_real(3)%vector
00141 max_size_grid_cell(3) = minval ( abs (k_corners_real(size(k_corners_real)/2+1:size(k_corners_real)) - &
00142 k_corners_real( 1:size(k_corners_real)/2)))
00143 else
00144
00145 k_corners_dble => grids (grid_id)%corner_pointer%corners_dble(3)%vector
00146 max_size_grid_cell(3) = minval ( abs (k_corners_dble(size(k_corners_dble)/2+1:size(k_corners_dble)) - &
00147 k_corners_dble( 1:size(k_corners_dble)/2)))
00148 endif
00149
00150 do i = 1, ndim_3d
00151 if (grids (grid_id)%corner_pointer%corner_datatype == MPI_REAL) then
00152
00153
00154 local_partition_extent(1, i) = minval (grids (grid_id)%corner_pointer%corners_real(i)%vector)
00155 local_partition_extent(2, i) = maxval (grids (grid_id)%corner_pointer%corners_real(i)%vector)
00156 else
00157
00158
00159 local_partition_extent(1, i) = minval (grids (grid_id)%corner_pointer%corners_dble(i)%vector)
00160 local_partition_extent(2, i) = maxval (grids (grid_id)%corner_pointer%corners_dble(i)%vector)
00161 endif
00162 enddo
00163
00164 #ifdef PRISM_ASSERTION
00165 if (any (max_size_grid_cell == 0) .or. &
00166 any (local_partition_extent(2,:) - &
00167 local_partition_extent(1,:) <= 0)) then
00168
00169 print *, "grid extent in at least one dimension is equal to 0"
00170 call psmile_assert (__FILE__, __LINE__, &
00171 'error in grid corner data')
00172 endif
00173 #endif
00174
00175 aux_grid_size (:) = ceiling ((local_partition_extent(2,:) - local_partition_extent(1,:)) / &
00176 max_size_grid_cell(:))
00177
00178
00179
00180
00181
00182 where (aux_grid_size(:) > 1)
00183
00184 aux_grid_size(:) = aux_grid_size(:) * 3
00185 endwhere
00186
00187
00188 allocate (grids(grid_id)%reduced_gauss_data%aux_corners(1)%vector(2*aux_grid_size(1)), &
00189 grids(grid_id)%reduced_gauss_data%aux_corners(2)%vector(2*aux_grid_size(2)), &
00190 grids(grid_id)%reduced_gauss_data%aux_corners(3)%vector(2*aux_grid_size(3)))
00191
00192 dxyz(:) = (local_partition_extent(2,:) - local_partition_extent(1,:)) / aux_grid_size (:)
00193
00194 do i = 1, ndim_3d
00195 grids(grid_id)%reduced_gauss_data%aux_corners(i)%vector(2*aux_grid_size(i)) = &
00196 local_partition_extent(2,i)
00197 enddo
00198
00199 do i = 1, ndim_3d
00200 do j = 1, aux_grid_size(i)
00201
00202 grids(grid_id)%reduced_gauss_data%aux_corners(i)%vector(j) = &
00203 local_partition_extent(1,i) + (j - 1) * dxyz(i)
00204 enddo
00205
00206 grids(grid_id)%reduced_gauss_data%aux_corners(i)%vector(aux_grid_size(i)+1:2*aux_grid_size(i)-1) = &
00207 grids(grid_id)%reduced_gauss_data%aux_corners(i)%vector(2:aux_grid_size(i))
00208 enddo
00209
00210 end subroutine psmile_gauss_gen_aux_grid
00211
00212
00213
00214 subroutine psmile_gauss_gen_aux_grid_map (grid_id)
00215
00216 use psmile_common, only : ndim_3d, dble_vector, real_vector
00217 use psmile, only : grids, MPI_REAL
00218
00219 implicit none
00220
00221 integer, intent (in) :: grid_id
00222
00223 integer :: cell_index, num_total_cells, grid_extent(2)
00224 integer :: iblock, i, j, level
00225 integer :: cell_overlap_range(2,ndim_3d)
00226
00227 type (dble_vector), pointer :: p_aux_corners(:), p_corners_dble(:)
00228 type (real_vector), pointer :: p_corners_real(:)
00229
00230 double precision :: cell (2, ndim_3d)
00231
00232 p_aux_corners => grids(grid_id)%reduced_gauss_data%aux_corners
00233
00234 if (grids (grid_id)%corner_pointer%corner_datatype == MPI_REAL) then
00235 p_corners_real => grids(grid_id)%corner_pointer%corners_real
00236 else
00237 p_corners_dble => grids(grid_id)%corner_pointer%corners_dble
00238 endif
00239
00240 allocate (grids(grid_id)%reduced_gauss_data%aux_3d_to_local_1d_map( &
00241 size (p_aux_corners(1)%vector)/2, &
00242 size (p_aux_corners(2)%vector)/2, &
00243 size (p_aux_corners(3)%vector)/2))
00244
00245
00246 grids(grid_id)%reduced_gauss_data%aux_3d_to_local_1d_map = -1
00247
00248 cell_index = 1
00249 num_total_cells = sum (grids(grid_id)%extent(:,1))
00250 grid_extent(:) = grids(grid_id)%grid_shape(2,1:2) - grids(grid_id)%grid_shape(1,1:2) + 1
00251
00252
00253
00254
00255 do iblock = 1, size (grids(grid_id)%extent, 1)
00256
00257
00258 do level = 1, grid_extent(2)
00259
00260 if (grids (grid_id)%corner_pointer%corner_datatype == MPI_REAL) then
00261
00262 cell(:, 3) = p_corners_real(3)%vector(level:level+grid_extent(2):grid_extent(2))
00263 else
00264
00265 cell(:, 3) = p_corners_dble(3)%vector(level:level+grid_extent(2):grid_extent(2))
00266 endif
00267
00268
00269
00270 cell_overlap_range (:,3) = get_matching_range (cell(:, 3), p_aux_corners(3))
00271
00272
00273 do i = 1, grids(grid_id)%extent(iblock, 1)
00274
00275 do j = 1, 2
00276
00277 if (grids (grid_id)%corner_pointer%corner_datatype == MPI_REAL) then
00278
00279 cell(:, j) = p_corners_real(j)%vector(cell_index:cell_index+num_total_cells:num_total_cells)
00280 else
00281
00282 cell(:, j) = p_corners_dble(j)%vector(cell_index:cell_index+num_total_cells:num_total_cells)
00283 endif
00284
00285
00286
00287 cell_overlap_range (:,j) = get_matching_range (cell(:, j), p_aux_corners(j))
00288 enddo
00289
00290
00291 grids(grid_id)%reduced_gauss_data%aux_3d_to_local_1d_map (&
00292 cell_overlap_range(1,1):cell_overlap_range(2,1), &
00293 cell_overlap_range(1,2):cell_overlap_range(2,2), &
00294 cell_overlap_range(1,3):cell_overlap_range(2,3)) = cell_index
00295
00296
00297 cell_index = cell_index + 1
00298 enddo
00299 enddo
00300 enddo
00301
00302 contains
00303
00304 function get_matching_range (cell_corners, grid_corners)
00305
00306 double precision, intent (in) :: cell_corners(2)
00307 type (dble_vector), intent (in) :: grid_corners
00308
00309 integer :: get_matching_range(2)
00310
00311 integer :: i, num_cells_in_grid
00312
00313 num_cells_in_grid = size (grid_corners%vector) / 2
00314
00315
00316 do i = 1, num_cells_in_grid
00317
00318 if (grid_corners%vector(i) > cell_corners(1)) exit
00319 enddo
00320 get_matching_range(1) = max (1, i-1)
00321
00322
00323
00324 do i = 1, num_cells_in_grid
00325
00326 if (grid_corners%vector(i + num_cells_in_grid) >= cell_corners(2)) exit
00327 enddo
00328 get_matching_range(2) = min (i, num_cells_in_grid)
00329
00330 end function get_matching_range
00331
00332 end subroutine psmile_gauss_gen_aux_grid_map
00333
00334
00335
00336 subroutine psmile_free_aux_grid_data (grid_id)
00337
00338 use psmile, only : grids
00339
00340 implicit none
00341
00342 integer, intent (in) :: grid_id
00343
00344 deallocate (grids(grid_id)%reduced_gauss_data%aux_3d_to_local_1d_map, &
00345 grids(grid_id)%reduced_gauss_data%aux_corners(1)%vector, &
00346 grids(grid_id)%reduced_gauss_data%aux_corners(2)%vector, &
00347 grids(grid_id)%reduced_gauss_data%aux_corners(3)%vector)
00348
00349 end subroutine psmile_free_aux_grid_data
00350
00351
00352
00353 integer function psmile_gauss_blockidx_to_glat (grid_id, block_idx)
00354
00355 use psmile, only : grids
00356
00357 implicit none
00358
00359 integer, intent (in) :: grid_id, block_idx
00360
00361 integer :: block_start_offset, accu, i
00362
00363 block_start_offset = grids(grid_id)%partition(block_idx, 1)
00364
00365 accu = 0
00366
00367 do i = 1, size (grids(grid_id)%reduced_gauss_data%nbr_points_per_lat)
00368
00369 accu = accu + grids(grid_id)%reduced_gauss_data%nbr_points_per_lat(i)
00370
00371 if (accu > block_start_offset) exit
00372 enddo
00373
00374 psmile_gauss_blockidx_to_glat = i
00375
00376 end function psmile_gauss_blockidx_to_glat
00377
00378
00379
00380 function psmile_gauss_1_local_1d_to_3d (grid_id, idx)
00381
00382 use psmile_common, only : ndim_3d
00383 use psmile, only : grids
00384 use psmile_grid_reduced_gauss, only : psmile_gauss_blockidx_to_glat
00385
00386 implicit none
00387
00388 integer, intent (in) :: grid_id, idx
00389
00390 integer :: psmile_gauss_1_local_1d_to_3d (ndim_3d)
00391
00392 integer :: lon_idx, i
00393
00394
00395
00396 if (associated (grids(grid_id)%reduced_gauss_data%local_block_info)) then
00397
00398 do i = 1, size (grids(grid_id)%reduced_gauss_data%local_block_info)
00399
00400 if (idx >= grids(grid_id)%reduced_gauss_data%local_block_info(i)%local_1d_start_idx .and. &
00401 idx <= grids(grid_id)%reduced_gauss_data%local_block_info(i)%local_1d_end_idx) then
00402
00403 psmile_gauss_1_local_1d_to_3d(:) = &
00404 grids(grid_id)%reduced_gauss_data%local_block_info(i)%global_3d_start_idx
00405
00406 psmile_gauss_1_local_1d_to_3d(1) = psmile_gauss_1_local_1d_to_3d(1) + idx - &
00407 grids(grid_id)%reduced_gauss_data%local_block_info(i)%local_1d_start_idx
00408
00409 exit
00410 endif
00411 enddo
00412
00413 else
00414
00415 lon_idx = idx
00416
00417
00418 do i = 1, size (grids(grid_id)%extent, 1)
00419
00420 if (lon_idx <= grids(grid_id)%extent(i,1)) exit
00421
00422 lon_idx = lon_idx - grids(grid_id)%extent(i,1)
00423 enddo
00424
00425 psmile_gauss_1_local_1d_to_3d(2) = psmile_gauss_blockidx_to_glat(grid_id, i)
00426 psmile_gauss_1_local_1d_to_3d(1) = lon_idx + grids(grid_id)%partition(i, 1) - &
00427 grids(grid_id)%reduced_gauss_data%global_lat_offsets(psmile_gauss_1_local_1d_to_3d(2))
00428 psmile_gauss_1_local_1d_to_3d(3) = 1
00429
00430 endif
00431
00432 end function psmile_gauss_1_local_1d_to_3d
00433
00434
00435
00436 function psmile_gauss_n_local_1d_to_3d (grid_id, idx, num_points)
00437
00438 use psmile_common, only : ndim_3d
00439 use psmile, only : grids
00440 use psmile_grid_reduced_gauss, only : psmile_gauss_blockidx_to_glat, block_info
00441
00442 implicit none
00443
00444 integer, intent (in) :: num_points
00445 integer, intent (in) :: grid_id, idx(num_points)
00446
00447 integer :: psmile_gauss_n_local_1d_to_3d (ndim_3d,num_points)
00448
00449 integer :: lon_idx, i, n, curr_block, num_blocks
00450 type (block_info), pointer :: local_block_info(:)
00451
00452
00453
00454
00455 if (associated (grids(grid_id)%reduced_gauss_data%local_block_info)) then
00456
00457 curr_block = 1
00458 num_blocks = size (grids(grid_id)%reduced_gauss_data%local_block_info)
00459 local_block_info => grids(grid_id)%reduced_gauss_data%local_block_info
00460
00461 outer: do n = 1, num_points
00462
00463 if (idx(n) >= local_block_info(curr_block)%local_1d_start_idx .and. &
00464 idx(n) <= local_block_info(curr_block)%local_1d_end_idx) then
00465
00466 psmile_gauss_n_local_1d_to_3d(2:3,n) = &
00467 local_block_info(curr_block)%global_3d_start_idx(2:3)
00468
00469 psmile_gauss_n_local_1d_to_3d(1,n) = &
00470 local_block_info(curr_block)%global_3d_start_idx(1) + idx(n) - &
00471 local_block_info(curr_block)%local_1d_start_idx
00472
00473 cycle outer
00474 endif
00475
00476 do i = curr_block+1, num_blocks, 1
00477
00478 if (idx(n) >= local_block_info(i)%local_1d_start_idx .and. &
00479 idx(n) <= local_block_info(i)%local_1d_end_idx) then
00480
00481 psmile_gauss_n_local_1d_to_3d(2:3,n) = &
00482 local_block_info(i)%global_3d_start_idx(2:3)
00483
00484 psmile_gauss_n_local_1d_to_3d(1,n) = &
00485 local_block_info(i)%global_3d_start_idx(1) + idx(n) - &
00486 local_block_info(i)%local_1d_start_idx
00487
00488 curr_block = curr_block + 1
00489 cycle outer
00490 endif
00491 enddo
00492
00493 do i = curr_block-1, 1, -1
00494
00495 if (idx(n) >= local_block_info(i)%local_1d_start_idx .and. &
00496 idx(n) <= local_block_info(i)%local_1d_end_idx) then
00497
00498 psmile_gauss_n_local_1d_to_3d(2:3,n) = &
00499 local_block_info(i)%global_3d_start_idx(2:3)
00500
00501 psmile_gauss_n_local_1d_to_3d(1,n) = &
00502 local_block_info(i)%global_3d_start_idx(1) + idx(n) - &
00503 local_block_info(i)%local_1d_start_idx
00504
00505 curr_block = curr_block - 1
00506 cycle outer
00507 endif
00508 enddo
00509 enddo outer
00510
00511 else
00512
00513 do n = 1, num_points
00514
00515 lon_idx = idx(n)
00516
00517
00518 do i = 1, size (grids(grid_id)%extent, 1)
00519
00520 if (lon_idx <= grids(grid_id)%extent(i,1)) exit
00521
00522 lon_idx = lon_idx - grids(grid_id)%extent(i,1)
00523 enddo
00524
00525 psmile_gauss_n_local_1d_to_3d(2,n) = psmile_gauss_blockidx_to_glat(grid_id, i)
00526 psmile_gauss_n_local_1d_to_3d(1,n) = lon_idx + grids(grid_id)%partition(i, 1) - &
00527 grids(grid_id)%reduced_gauss_data%global_lat_offsets(psmile_gauss_n_local_1d_to_3d(2,n))
00528 psmile_gauss_n_local_1d_to_3d(3,n) = 1
00529 enddo
00530
00531 endif
00532
00533 end function psmile_gauss_n_local_1d_to_3d
00534
00535
00536
00537 integer function get_gauss_neighbour_cell (idx, nbr_points_lat, nbr_points_lat_neigh)
00538
00539 implicit none
00540
00541 integer, intent (in) :: idx,
00542 nbr_points_lat,
00543 nbr_points_lat_neigh
00544
00545
00546 integer :: intermediate_idx
00547
00548 if (nbr_points_lat == nbr_points_lat_neigh) then
00549 get_gauss_neighbour_cell = idx
00550 return
00551 endif
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561 intermediate_idx = (idx-1)*3*nbr_points_lat_neigh + nint(real(nbr_points_lat_neigh)*1.5)
00562
00563 get_gauss_neighbour_cell = intermediate_idx / (3 * nbr_points_lat) + 1
00564
00565 end function get_gauss_neighbour_cell
00566
00567
00568
00569 integer function get_gauss_opposite_neighbour_cell (idx, nbr_points_lat, nbr_points_lat_neigh)
00570
00571 implicit none
00572
00573 integer, intent (in) :: idx,
00574 nbr_points_lat,
00575 nbr_points_lat_neigh
00576
00577
00578 integer :: intermediate_idx
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588 intermediate_idx = (idx-1)*3*nbr_points_lat_neigh + nint(real(nbr_points_lat_neigh)*1.5)
00589
00590
00591 intermediate_idx = mod(intermediate_idx + nbr_points_lat * nbr_points_lat_neigh * 3 / 2, &
00592 nbr_points_lat * nbr_points_lat_neigh * 3)
00593
00594 get_gauss_opposite_neighbour_cell = intermediate_idx / (3 * nbr_points_lat) + 1
00595
00596 end function get_gauss_opposite_neighbour_cell
00597
00598
00599
00600 function psmile_gauss_get_bicu_stencil (grid_id, base)
00601
00602 use psmile_common, only : ndim_3d
00603 use psmile_grid_reduced_gauss, only : psmile_gauss_shift_bicu_stencil
00604
00605 implicit none
00606
00607 integer, intent (in) :: grid_id, base(ndim_3d)
00608
00609 integer :: psmile_gauss_get_bicu_stencil(ndim_3d, 16)
00610
00611 psmile_gauss_get_bicu_stencil = psmile_gauss_shift_bicu_stencil(grid_id, base, (/0,0,0/))
00612
00613 end function psmile_gauss_get_bicu_stencil
00614
00615
00616
00617 function psmile_gauss_shift_bicu_stencil (grid_id, base, shift)
00618
00619 use psmile_common, only : ndim_3d
00620 use psmile, only : grids, psmile_assert
00621 use psmile_grid_reduced_gauss, only : get_gauss_opposite_neighbour_cell, &
00622 get_gauss_neighbour_cell
00623
00624 implicit none
00625
00626 integer, intent (in) :: grid_id, base (ndim_3d), shift(ndim_3d)
00627
00628 integer :: psmile_gauss_shift_bicu_stencil (ndim_3d, 16)
00629
00630 integer :: global_num_lats, i, i_
00631 integer, pointer :: g_nbr_points_per_lat(:)
00632 integer, parameter :: lon_shift(3) = (/1,2,-1/)
00633 integer :: orientation(4)
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645 g_nbr_points_per_lat => grids(grid_id)%reduced_gauss_data%nbr_points_per_lat
00646 global_num_lats = size (g_nbr_points_per_lat)
00647 orientation(:) = 1
00648
00649 #ifdef PRISM_ASSERTION
00650 if (any (abs (shift(:)) > 1)) then
00651 call psmile_assert (__FILE__, __LINE__, &
00652 "shifting by more than one cell is not supported")
00653 endif
00654 if (base(2)+shift(2) < 1 .or. &
00655 base(2)+shift(2) > size (g_nbr_points_per_lat)) then
00656 call psmile_assert (__FILE__, __LINE__, &
00657 "shifting of the base point over the pole is not supported")
00658 endif
00659 #endif
00660
00661
00662
00663
00664 if (shift(2) /= 1) then
00665
00666
00667 if (base(2)+shift(2) == 1) then
00668
00669 psmile_gauss_shift_bicu_stencil(1,2) = &
00670 get_gauss_opposite_neighbour_cell(base(1), g_nbr_points_per_lat(1), &
00671 g_nbr_points_per_lat(1)) + &
00672 shift(1)
00673
00674 psmile_gauss_shift_bicu_stencil(2,2) = 1
00675
00676 orientation(1) = -1
00677 else
00678
00679 psmile_gauss_shift_bicu_stencil(1,2) = &
00680 get_gauss_neighbour_cell(base(1), &
00681 g_nbr_points_per_lat(base(2)), &
00682 g_nbr_points_per_lat(base(2)-1+shift(2))) &
00683 + shift(1)
00684
00685 psmile_gauss_shift_bicu_stencil(2,2) = base(2) - 1 + shift(2)
00686 endif
00687 else
00688
00689 psmile_gauss_shift_bicu_stencil(1,2) = base(1) + shift(1)
00690 psmile_gauss_shift_bicu_stencil(2,2) = base(2)
00691 endif
00692
00693 psmile_gauss_shift_bicu_stencil(3, 2) = base(3) + shift(3)
00694
00695
00696
00697
00698 if (abs(shift(2)) == 1) then
00699
00700 psmile_gauss_shift_bicu_stencil(1,6) = &
00701 get_gauss_neighbour_cell(base(1), g_nbr_points_per_lat(base(2)), &
00702 g_nbr_points_per_lat(base(2)+shift(2))) &
00703 + shift(1)
00704
00705 psmile_gauss_shift_bicu_stencil(2,6) = base(2) + shift(2)
00706
00707 else
00708
00709 psmile_gauss_shift_bicu_stencil(1:2,6) = base(1:2) + shift(1:2)
00710 endif
00711
00712 psmile_gauss_shift_bicu_stencil(3,6) = base(3) + shift(3)
00713
00714
00715
00716
00717 if (shift(2) >= 0) then
00718
00719
00720 if (base(2)+shift(2) == global_num_lats) then
00721
00722 psmile_gauss_shift_bicu_stencil(1,10) = &
00723 get_gauss_opposite_neighbour_cell( &
00724 base(1), g_nbr_points_per_lat(global_num_lats), &
00725 g_nbr_points_per_lat(global_num_lats)) &
00726 + shift(1)
00727
00728 psmile_gauss_shift_bicu_stencil(2,10) = global_num_lats
00729
00730 orientation(3) = -1
00731 else
00732
00733 psmile_gauss_shift_bicu_stencil(1,10) = &
00734 get_gauss_neighbour_cell(base(1), &
00735 g_nbr_points_per_lat(base(2)), &
00736 g_nbr_points_per_lat(base(2)+1+shift(2))) &
00737 + shift(1)
00738
00739 psmile_gauss_shift_bicu_stencil(2,10) = base(2) + 1 + shift(2)
00740 endif
00741
00742 else
00743
00744 psmile_gauss_shift_bicu_stencil(1,10) = base(1) + shift(1)
00745 psmile_gauss_shift_bicu_stencil(2,10) = base(2)
00746 endif
00747
00748 psmile_gauss_shift_bicu_stencil(3,10) = base(3) + shift(3)
00749
00750
00751
00752
00753 if (base(2)+shift(2) == global_num_lats) then
00754
00755 psmile_gauss_shift_bicu_stencil(1,14) = &
00756 get_gauss_opposite_neighbour_cell( &
00757 base(1), g_nbr_points_per_lat(global_num_lats), &
00758 g_nbr_points_per_lat(global_num_lats-1)) &
00759 + shift(1)
00760
00761 psmile_gauss_shift_bicu_stencil(2,14) = global_num_lats-1
00762
00763 orientation(4) = -1
00764 else if (base(2)+shift(2) == global_num_lats-1) then
00765
00766 psmile_gauss_shift_bicu_stencil(1,14) = &
00767 get_gauss_opposite_neighbour_cell( &
00768 base(1), g_nbr_points_per_lat(global_num_lats-1), &
00769 g_nbr_points_per_lat(global_num_lats)) &
00770 + shift(1)
00771
00772 psmile_gauss_shift_bicu_stencil(2,14) = global_num_lats
00773
00774 orientation(4) = -1
00775 else
00776
00777 psmile_gauss_shift_bicu_stencil(1,14) = &
00778 get_gauss_neighbour_cell(base(1), &
00779 g_nbr_points_per_lat(base(2)), &
00780 g_nbr_points_per_lat(base(2)+2+shift(2))) &
00781 + shift(1)
00782
00783 psmile_gauss_shift_bicu_stencil(2,14) = base(2) + 2 + shift(2)
00784 endif
00785
00786 psmile_gauss_shift_bicu_stencil(3,14) = base(3) + shift(3)
00787
00788
00789
00790 do i = 2, 4
00791
00792
00793
00794 i_ = iand (i, 3) + 1
00795
00796 psmile_gauss_shift_bicu_stencil(1,i_::4) = psmile_gauss_shift_bicu_stencil(1,2::4) &
00797 + lon_shift(i-1) * orientation(:)
00798 psmile_gauss_shift_bicu_stencil(2:3,i_::4) = psmile_gauss_shift_bicu_stencil(2:3,2::4)
00799 enddo
00800
00801
00802
00803 where (psmile_gauss_shift_bicu_stencil(1,:) < 1)
00804 psmile_gauss_shift_bicu_stencil(1,:) = psmile_gauss_shift_bicu_stencil(1,:) + &
00805 g_nbr_points_per_lat(psmile_gauss_shift_bicu_stencil(2,:))
00806 end where
00807
00808 where (psmile_gauss_shift_bicu_stencil(1,:) > &
00809 g_nbr_points_per_lat(psmile_gauss_shift_bicu_stencil(2,:)))
00810 psmile_gauss_shift_bicu_stencil(1,:) = psmile_gauss_shift_bicu_stencil(1,:) - &
00811 g_nbr_points_per_lat(psmile_gauss_shift_bicu_stencil(2,:))
00812 end where
00813
00814 end function psmile_gauss_shift_bicu_stencil
00815
00816
00817
00818 function psmile_gauss_get_neigh_stencil (grid_id, base)
00819
00820 use psmile_common, only : ndim_3d
00821 use psmile, only : grids
00822 use psmile_grid_reduced_gauss, only : get_gauss_opposite_neighbour_cell, &
00823 get_gauss_neighbour_cell
00824
00825 implicit none
00826
00827 integer, intent (in) :: grid_id, base(ndim_3d)
00828
00829 integer :: psmile_gauss_get_neigh_stencil(ndim_3d, 9)
00830
00831 integer :: global_num_lats, i
00832 integer, pointer :: g_nbr_points_per_lat(:)
00833 integer, parameter :: lon_shift(3) = (/-1,0,1/)
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843 g_nbr_points_per_lat => grids(grid_id)%reduced_gauss_data%nbr_points_per_lat
00844 global_num_lats = size (g_nbr_points_per_lat)
00845
00846 psmile_gauss_get_neigh_stencil(3, :) = base(3)
00847 psmile_gauss_get_neigh_stencil(:, 5) = base
00848
00849
00850
00851 psmile_gauss_get_neigh_stencil(2,1:3) = max (base(2)-1, 1)
00852
00853
00854 psmile_gauss_get_neigh_stencil(2,4:6) = base(2)
00855
00856 psmile_gauss_get_neigh_stencil(2,7:9) = min (base(2)+1, global_num_lats)
00857
00858
00859
00860
00861
00862
00863 do i = 2, 8, 6
00864
00865
00866 if (base(2) == psmile_gauss_get_neigh_stencil(2,i)) then
00867
00868 psmile_gauss_get_neigh_stencil(1,i) = &
00869 get_gauss_opposite_neighbour_cell(base(1), &
00870 g_nbr_points_per_lat(base(2)), &
00871 g_nbr_points_per_lat(psmile_gauss_get_neigh_stencil(2,i)))
00872 else
00873
00874 psmile_gauss_get_neigh_stencil(1,i) = &
00875 get_gauss_neighbour_cell(base(1), &
00876 g_nbr_points_per_lat(base(2)), &
00877 g_nbr_points_per_lat(psmile_gauss_get_neigh_stencil(2,i)))
00878 endif
00879
00880 enddo
00881
00882
00883
00884 do i = 1, 3, 2
00885
00886 psmile_gauss_get_neigh_stencil(1,i::3) = psmile_gauss_get_neigh_stencil(1,2::3) + lon_shift(i)
00887 enddo
00888
00889
00890
00891 where (psmile_gauss_get_neigh_stencil(1,:) < 1)
00892 psmile_gauss_get_neigh_stencil(1,:) = psmile_gauss_get_neigh_stencil(1,:) + &
00893 g_nbr_points_per_lat(psmile_gauss_get_neigh_stencil(2,:))
00894 end where
00895
00896 where (psmile_gauss_get_neigh_stencil(1,:) > &
00897 g_nbr_points_per_lat(psmile_gauss_get_neigh_stencil(2,:)))
00898 psmile_gauss_get_neigh_stencil(1,:) = psmile_gauss_get_neigh_stencil(1,:) - &
00899 g_nbr_points_per_lat(psmile_gauss_get_neigh_stencil(2,:))
00900 end where
00901
00902 end function psmile_gauss_get_neigh_stencil
00903
00904
00905
00906 function psmile_gauss_get_bili_stencil (grid_id, base)
00907
00908 use psmile_common, only : ndim_3d
00909 use psmile_grid_reduced_gauss, only : psmile_gauss_shift_bili_stencil
00910
00911 implicit none
00912
00913 integer, intent (in) :: grid_id, base(ndim_3d)
00914
00915 integer :: psmile_gauss_get_bili_stencil(ndim_3d, 4)
00916
00917
00918 psmile_gauss_get_bili_stencil = psmile_gauss_shift_bili_stencil (grid_id, base, (/0,0,0/))
00919
00920 end function psmile_gauss_get_bili_stencil
00921
00922
00923
00924 function psmile_gauss_shift_bili_stencil (grid_id, base, shift)
00925
00926 use psmile_common, only : ndim_3d
00927 use psmile, only : grids, psmile_assert
00928 use psmile_grid_reduced_gauss, only : get_gauss_opposite_neighbour_cell, &
00929 get_gauss_neighbour_cell
00930
00931 implicit none
00932
00933 integer, intent (in) :: grid_id, base (ndim_3d), shift(ndim_3d)
00934
00935 integer :: psmile_gauss_shift_bili_stencil (ndim_3d, 4)
00936
00937 integer :: global_num_lats
00938 integer, pointer :: g_nbr_points_per_lat(:)
00939 integer :: orientation
00940
00941
00942
00943
00944
00945
00946
00947 g_nbr_points_per_lat => grids(grid_id)%reduced_gauss_data%nbr_points_per_lat
00948 global_num_lats = size (g_nbr_points_per_lat)
00949 orientation = 1
00950
00951 #ifdef PRISM_ASSERTION
00952 if (any (abs (shift(:)) > 1)) then
00953 call psmile_assert (__FILE__, __LINE__, &
00954 "shifting by more than one cell is not supported")
00955 endif
00956 if (base(2)+shift(2) < 1 .or. &
00957 base(2)+shift(2) > size (g_nbr_points_per_lat)) then
00958 call psmile_assert (__FILE__, __LINE__, &
00959 "shifting of the base point over the pole is not supported")
00960 endif
00961 #endif
00962
00963
00964
00965
00966 if (abs(shift(2)) == 1) then
00967
00968 psmile_gauss_shift_bili_stencil(1,1) = &
00969 get_gauss_neighbour_cell(base(1), g_nbr_points_per_lat(base(2)), &
00970 g_nbr_points_per_lat(base(2)+shift(2))) &
00971 + shift(1)
00972
00973 psmile_gauss_shift_bili_stencil(2,1) = base(2) + shift(2)
00974
00975 else
00976
00977 psmile_gauss_shift_bili_stencil(1:2,1) = base(1:2) + shift(1:2)
00978 endif
00979
00980 psmile_gauss_shift_bili_stencil(3,1) = base(3) + shift(3)
00981
00982
00983
00984
00985 if (shift(2) >= 0) then
00986
00987
00988 if (base(2)+shift(2) == global_num_lats) then
00989
00990 psmile_gauss_shift_bili_stencil(1,4) = &
00991 get_gauss_opposite_neighbour_cell( &
00992 base(1), g_nbr_points_per_lat(global_num_lats), &
00993 g_nbr_points_per_lat(global_num_lats)) &
00994 + shift(1)
00995
00996 psmile_gauss_shift_bili_stencil(2,4) = global_num_lats
00997
00998 orientation = -1
00999 else
01000
01001 psmile_gauss_shift_bili_stencil(1,4) = &
01002 get_gauss_neighbour_cell(base(1), &
01003 g_nbr_points_per_lat(base(2)), &
01004 g_nbr_points_per_lat(base(2)+1+shift(2))) &
01005 + shift(1)
01006
01007 psmile_gauss_shift_bili_stencil(2,4) = base(2) + 1 + shift(2)
01008 endif
01009
01010 else
01011
01012 psmile_gauss_shift_bili_stencil(1,4) = base(1) + shift(1)
01013 psmile_gauss_shift_bili_stencil(2,4) = base(2)
01014 endif
01015
01016 psmile_gauss_shift_bili_stencil(3,4) = base(3) + shift(3)
01017
01018
01019 psmile_gauss_shift_bili_stencil(:,2) = psmile_gauss_shift_bili_stencil(:,1) + (/1,0,0/)
01020 psmile_gauss_shift_bili_stencil(:,3) = psmile_gauss_shift_bili_stencil(:,4) + &
01021 (/orientation,0,0/)
01022
01023
01024 where (psmile_gauss_shift_bili_stencil(1,:) < 1)
01025 psmile_gauss_shift_bili_stencil(1,:) = psmile_gauss_shift_bili_stencil(1,:) + &
01026 g_nbr_points_per_lat(psmile_gauss_shift_bili_stencil(2,:))
01027 end where
01028
01029 where (psmile_gauss_shift_bili_stencil(1,:) > &
01030 g_nbr_points_per_lat(psmile_gauss_shift_bili_stencil(2,:)))
01031 psmile_gauss_shift_bili_stencil(1,:) = psmile_gauss_shift_bili_stencil(1,:) - &
01032 g_nbr_points_per_lat(psmile_gauss_shift_bili_stencil(2,:))
01033 end where
01034
01035 end function psmile_gauss_shift_bili_stencil
01036
01037
01038
01039 function psmile_gauss_3d_to_global_1d (grid_id, points_3d, num_points)
01040
01041 use psmile_common, only : ndim_3d
01042 use psmile, only : grids
01043
01044 implicit none
01045
01046 integer, intent(in) :: grid_id, num_points
01047 integer, intent(in) :: points_3d(ndim_3d, num_points)
01048
01049 integer :: psmile_gauss_3d_to_global_1d(num_points)
01050
01051 integer :: i, num_lats
01052
01053 num_lats = size (grids(grid_id)%reduced_gauss_data%nbr_points_per_lat)
01054
01055 do i = 1, num_points
01056
01057 if ((points_3d(2,i) == 1) .or. (points_3d(2,i) > num_lats)) then
01058
01059 psmile_gauss_3d_to_global_1d(i) = points_3d(1,i)
01060
01061 else
01062
01063 if (points_3d(1,i) >= 1 .and. &
01064 points_3d(1,i) <= grids(grid_id)%reduced_gauss_data%nbr_points_per_lat(points_3d(2,i))) then
01065
01066 psmile_gauss_3d_to_global_1d(i) = points_3d(1,i) + &
01067 sum (grids(grid_id)%reduced_gauss_data%nbr_points_per_lat(1:points_3d(2,i)-1))
01068 else
01069 psmile_gauss_3d_to_global_1d(i) = points_3d(1,i)
01070 endif
01071 endif
01072 enddo
01073
01074 end function psmile_gauss_3d_to_global_1d
01075
01076
01077
01078 function psmile_gauss_1d_global_to_local (grid_id, points_1d, num_points, &
01079 fill_value, inc_remote_neigh)
01080
01081 use psmile, only : grids
01082
01083 implicit none
01084
01085 integer, intent(in) :: grid_id, num_points, fill_value
01086 integer, intent(in) :: points_1d(num_points)
01087 logical, intent(in), optional :: inc_remote_neigh
01088
01089
01090
01091
01092 integer :: psmile_gauss_1d_global_to_local(num_points)
01093
01094 integer :: i, j, num_local_points, curr_block
01095
01096 psmile_gauss_1d_global_to_local(:) = fill_value
01097
01098 if (associated (grids(grid_id)%reduced_gauss_data%local_block_info)) then
01099
01100 curr_block = 1
01101
01102
01103 outer: do i = 1, num_points
01104
01105 do j = curr_block, size (grids(grid_id)%partition, 1)
01106
01107 if (points_1d(i) >= &
01108 grids(grid_id)%reduced_gauss_data%local_block_info(j)%global_1d_start_idx &
01109 .and. &
01110 points_1d(i) <= &
01111 grids(grid_id)%reduced_gauss_data%local_block_info(j)%global_1d_end_idx) then
01112
01113 psmile_gauss_1d_global_to_local(i) = &
01114 grids(grid_id)%reduced_gauss_data%local_block_info(j)%local_1d_start_idx + &
01115 points_1d(i) - &
01116 grids(grid_id)%reduced_gauss_data%local_block_info(j)%global_1d_start_idx
01117
01118 curr_block = j
01119 cycle outer
01120 endif
01121 enddo
01122
01123 do j = 1, curr_block-1
01124
01125 if (points_1d(i) >= &
01126 grids(grid_id)%reduced_gauss_data%local_block_info(j)%global_1d_start_idx &
01127 .and. &
01128 points_1d(i) <= &
01129 grids(grid_id)%reduced_gauss_data%local_block_info(j)%global_1d_end_idx) then
01130
01131 psmile_gauss_1d_global_to_local(i) = &
01132 grids(grid_id)%reduced_gauss_data%local_block_info(j)%local_1d_start_idx + &
01133 points_1d(i) - &
01134 grids(grid_id)%reduced_gauss_data%local_block_info(j)%global_1d_start_idx
01135
01136 curr_block = j
01137 cycle outer
01138 endif
01139 enddo
01140 enddo outer
01141
01142 else
01143
01144
01145 do i = 1, size (grids(grid_id)%partition, 1)
01146
01147
01148 where (points_1d(:) > grids(grid_id)%partition(i,1) .and. &
01149 points_1d(:) <= grids(grid_id)%partition(i,1) + grids(grid_id)%extent(i,1))
01150
01151 psmile_gauss_1d_global_to_local(:) = points_1d(:) - &
01152 grids(grid_id)%partition(i,1) + &
01153 sum (grids(grid_id)%extent(1:i-1,1))
01154
01155 end where
01156
01157 enddo
01158
01159 endif
01160
01161
01162
01163 if (present(inc_remote_neigh)) then
01164 if (.not. inc_remote_neigh) return
01165 endif
01166
01167
01168 if (associated (grids(grid_id)%remote_index)) then
01169
01170 num_local_points = sum (grids(grid_id)%extent(:,1))
01171
01172
01173 outer2:do i = 1, num_points
01174
01175 if (psmile_gauss_1d_global_to_local(i) == fill_value) then
01176
01177 do j = 1, size (grids(grid_id)%remote_index)
01178
01179 if (points_1d(i) == grids(grid_id)%remote_index(j)) then
01180
01181 psmile_gauss_1d_global_to_local(i) = j + num_local_points
01182 cycle outer2
01183
01184 endif
01185 enddo
01186 endif
01187 enddo outer2
01188 endif
01189
01190 end function psmile_gauss_1d_global_to_local
01191
01192
01193
01194 function psmile_gauss_3d_to_local_1d (grid_id, points_3d, num_points, &
01195 fill_value, inc_remote_neigh)
01196
01197 use psmile, only : grids
01198 use psmile_common, only : ndim_3d
01199 use psmile_grid_reduced_gauss, only : psmile_gauss_3d_to_global_1d, &
01200 psmile_gauss_1d_global_to_local, &
01201 block_info
01202
01203 implicit none
01204
01205 integer, intent(in) :: grid_id, num_points, fill_value
01206 integer, intent(in) :: points_3d(ndim_3d, num_points)
01207 logical, intent(in), optional :: inc_remote_neigh
01208
01209
01210
01211
01212 integer :: psmile_gauss_3d_to_local_1d(num_points)
01213
01214 integer :: i, j, num_blocks, num_local_points
01215 integer :: point_global_1d(1)
01216 type (block_info), pointer :: local_block_info (:)
01217
01218
01219
01220 if (associated (grids(grid_id)%reduced_gauss_data%local_block_info)) then
01221
01222 psmile_gauss_3d_to_local_1d = fill_value
01223 local_block_info => grids(grid_id)%reduced_gauss_data%local_block_info
01224 num_blocks = size (local_block_info)
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241 do i = 1 , num_blocks
01242
01243 where (points_3d(1, :) >= local_block_info(i)%global_3d_start_idx(1) .and. &
01244 points_3d(1, :) <= local_block_info(i)%global_3d_end_idx(1) .and. &
01245 points_3d(2, :) == local_block_info(i)%global_3d_start_idx(2))
01246
01247 psmile_gauss_3d_to_local_1d(:) = &
01248 local_block_info(i)%local_1d_start_idx + &
01249 points_3d(1, :) - &
01250 local_block_info(i)%global_3d_start_idx(1)
01251 endwhere
01252 enddo
01253
01254 if (present(inc_remote_neigh)) then
01255
01256 if (inc_remote_neigh) then
01257
01258 num_local_points = sum (grids(grid_id)%extent(:,1))
01259
01260 outer: do i = 1, num_points
01261
01262 if (psmile_gauss_3d_to_local_1d(i) == fill_value) then
01263
01264 point_global_1d = psmile_gauss_3d_to_global_1d(grid_id, (/points_3d(:, i)/), 1)
01265
01266 do j = 1, size (grids(grid_id)%remote_index)
01267
01268 if (point_global_1d(1) == grids(grid_id)%remote_index(j)) then
01269
01270 psmile_gauss_3d_to_local_1d(i) = j + num_local_points
01271 cycle outer
01272
01273 endif
01274 enddo
01275 endif
01276 enddo outer
01277 endif
01278 endif
01279
01280 else
01281
01282 if (present(inc_remote_neigh)) then
01283 psmile_gauss_3d_to_local_1d = psmile_gauss_1d_global_to_local (grid_id, &
01284 psmile_gauss_3d_to_global_1d (grid_id, &
01285 points_3d, &
01286 num_points), &
01287 num_points, fill_value, inc_remote_neigh)
01288 else
01289 psmile_gauss_3d_to_local_1d = psmile_gauss_1d_global_to_local (grid_id, &
01290 psmile_gauss_3d_to_global_1d (grid_id, &
01291 points_3d, &
01292 num_points), &
01293 num_points, fill_value)
01294 endif
01295 endif
01296
01297 end function psmile_gauss_3d_to_local_1d