00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 subroutine psmile_mg_method_gauss2_real (method_id, search_range, &
00012 tgt_shape, tgt_coords_x, &
00013 tgt_coords_y, loc_fnd_shape, &
00014 found, loc, virtual_cell, &
00015 ierror)
00016
00017
00018
00019 use PRISM_constants
00020 use psmile, dummy => psmile_mg_method_gauss2_real
00021 use psmile_geometry, only : point_is_in_quadrangle
00022 use psmile_grid, only : common_grid_range, psmile_transform_cell_cyclic
00023 use psmile_grid_reduced_gauss
00024 #ifdef DEBUG_TRACE
00025 use psmile_debug_trace
00026 #endif
00027
00028 implicit none
00029
00030
00031
00032 integer, intent (in) :: method_id
00033
00034 integer, intent (in) :: search_range (2, ndim_3d)
00035
00036
00037 integer, intent (in) :: loc_fnd_shape (2, ndim_3d)
00038
00039
00040
00041 integer, intent (in) :: tgt_shape (2, ndim_3d)
00042
00043
00044
00045
00046 real, intent (in) :: tgt_coords_x (tgt_shape(1,1):tgt_shape(2,1),
00047 tgt_shape(1,2):tgt_shape(2,2),
00048 tgt_shape(1,3):tgt_shape(2,3)),
00049 tgt_coords_y (tgt_shape(1,1):tgt_shape(2,1),
00050 tgt_shape(1,2):tgt_shape(2,2),
00051 tgt_shape(1,3):tgt_shape(2,3))
00052
00053
00054
00055
00056
00057 integer, intent (inout) :: found (loc_fnd_shape(1,1):loc_fnd_shape(2,1),
00058 loc_fnd_shape(1,2):loc_fnd_shape(2,2),
00059 loc_fnd_shape(1,3):loc_fnd_shape(2,3))
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 integer, intent (inout) :: loc (loc_fnd_shape(1,1):loc_fnd_shape(2,1),
00074 loc_fnd_shape(1,2):loc_fnd_shape(2,2),
00075 loc_fnd_shape(1,3):loc_fnd_shape(2,3))
00076
00077
00078
00079
00080
00081
00082
00083 integer, intent (out) :: virtual_cell (loc_fnd_shape(1,1):loc_fnd_shape(2,1),
00084 loc_fnd_shape(1,2):loc_fnd_shape(2,2),
00085 loc_fnd_shape(1,3):loc_fnd_shape(2,3))
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 integer, intent (out) :: ierror
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 integer, parameter :: val_coupler = -1
00113
00114
00115
00116 integer, pointer :: local_1d_stencil_lookup(:,:)
00117
00118 integer :: i, j, k, n, n_end
00119
00120 integer :: not_found
00121
00122 real, pointer :: src_coords_x(:),
00123 src_coords_y(:)
00124
00125
00126
00127 integer, pointer :: local_coords_shape(:,:)
00128 integer :: num_local_points, num_remote_points, num_global_lats
00129
00130 integer, pointer :: curr_stencil(:)
00131 integer :: curr_stencil_idx
00132 integer :: curr_3d_base_idx(ndim_3d)
00133 type(point_real) :: method_cell (4), point
00134 real :: grid_extent
00135 integer :: grid_id
00136
00137 integer, allocatable :: loc_3d(:,:,:,:)
00138
00139 integer, parameter :: n_to_stencil_base_idx(9) = (/1,2,3, 5,6,7,
00140 9,10,11/)
00141 integer, parameter :: stencil_idx_to_virtual_cell(16) = (/1,2,3,-1,
00142 4,5,6,-1,
00143 7,8,9,-1,
00144 -1,-1,-1,-1/)
00145
00146 #ifdef DEBUG_TRACE
00147
00148
00149
00150 logical :: debug_trace
00151 type(point_real) :: debug_point
00152 character (len=*), parameter :: out_prefix = "ictl psmile_mg_method_gauss2_real:"
00153 #endif
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 Character(len=len_cvs_string), save :: mycvs =
00178 '$Id: psmile_mg_method_gauss2_real.F90 3011 2011-03-10 17:50:02Z hanke $'
00179
00180
00181 #ifdef VERBOSE
00182 print 9990, trim(ch_id)
00183
00184 call psmile_flushstd
00185 #endif /* VERBOSE */
00186
00187
00188
00189 ierror = 0
00190
00191 grid_id = methods(method_id)%grid_id
00192 local_1d_stencil_lookup => &
00193 grids(grid_id)%reduced_gauss_data%local_1d_stencil_lookup
00194 num_global_lats = &
00195 size (grids(grid_id)%reduced_gauss_data%nbr_points_per_lat)
00196 not_found = - (grids(grid_id)%nlev + 2)
00197 local_coords_shape => Methods(method_id)%coords_pointer%coords_shape
00198
00199
00200 num_local_points = local_coords_shape(2,1) - local_coords_shape(1,1)
00201 if (associated (grids(grid_id)%remote_index)) then
00202 num_remote_points = size (grids(grid_id)%remote_index)
00203 else
00204 num_remote_points = 0
00205 endif
00206
00207
00208
00209 if (num_remote_points <= 0) then
00210
00211 src_coords_x => Methods(method_id)%coords_pointer%coords_real(1)%vector
00212 src_coords_y => Methods(method_id)%coords_pointer%coords_real(2)%vector
00213 else
00214
00215
00216 allocate (src_coords_x(local_coords_shape(1,1):local_coords_shape(2,1)+num_remote_points), &
00217 src_coords_y(local_coords_shape(1,1):local_coords_shape(2,1)+num_remote_points), &
00218 stat = ierror)
00219
00220 if ( ierror > 0 ) then
00221 call psmile_error (PRISM_Error_Alloc, 'src_coords_x and src_coords_y', (/ierror, &
00222 2*(local_coords_shape(2,1)-local_coords_shape(1,1)+1+num_remote_points)/), &
00223 2, __FILE__, __LINE__ )
00224 return
00225 endif
00226
00227 src_coords_x(local_coords_shape(1,1):local_coords_shape(2,1)) = &
00228 Methods(method_id)%coords_pointer%coords_real(1)%vector
00229 src_coords_y(local_coords_shape(1,1):local_coords_shape(2,1)) = &
00230 Methods(method_id)%coords_pointer%coords_real(2)%vector
00231
00232 src_coords_x(local_coords_shape(2,1)+1:local_coords_shape(2,1)+num_remote_points) = &
00233 Methods(method_id)%gauss2_real(1)%vector
00234 src_coords_y(local_coords_shape(2,1)+1:local_coords_shape(2,1)+num_remote_points) = &
00235 Methods(method_id)%gauss2_real(2)%vector
00236 endif
00237
00238
00239 virtual_cell = 0
00240
00241
00242 grid_extent = common_grid_range(2,1) - common_grid_range(1,1)
00243
00244
00245 allocate (loc_3d(ndim_3d, loc_fnd_shape(1,1):loc_fnd_shape(2,1), &
00246 loc_fnd_shape(1,2):loc_fnd_shape(2,2), &
00247 loc_fnd_shape(1,3):loc_fnd_shape(2,3)))
00248
00249 loc_3d(:,:,:,:) = reshape (psmile_gauss_local_1d_to_3d(grid_id, &
00250 reshape(loc, (/size(loc)/)), &
00251 size(loc)), &
00252 (/ndim_3d, size(loc,1), size(loc,2), size(loc,3)/))
00253
00254 do i = search_range(1, 1), search_range(2,1)
00255 do j = search_range(1, 2), search_range(2,2)
00256 do k = search_range(1, 3), search_range(2,3)
00257 #ifdef DEBUG_TRACE
00258 if (i == ictl_ind(1) .and. j == ictl_ind(2)) then
00259 print *, out_prefix, ' ictl_ind', &
00260 ictl_ind (1:ndim_2d), ' old found = ', &
00261 found (ictl_ind(1),ictl_ind(2),search_range(1,3)), &
00262 ', old loc =', loc (ictl_ind(1),ictl_ind(2),search_range(1,3))
00263 debug_trace = .true.
00264 else
00265 debug_trace = .false.
00266 endif
00267 #endif
00268
00269 if (found (i,j,k) == 1) then
00270
00271 point%x = tgt_coords_x (i,j,k)
00272 point%y = tgt_coords_y (i,j,k)
00273
00274 curr_stencil => local_1d_stencil_lookup(:, loc (i,j,k))
00275 curr_3d_base_idx(:) = loc_3d (:,i,j,k)
00276
00277 #ifdef DEBUG_TRACE
00278 if (debug_trace) then
00279 print '(2(1x,a),2f8.2)', out_prefix, 'point to be searched: ', point
00280 debug_point = point
00281 endif
00282 #endif
00283
00284
00285 if (curr_3d_base_idx(2) == 1) then
00286 n = 4
00287 else
00288 n = 1
00289 endif
00290
00291
00292 if (curr_3d_base_idx(2) == num_global_lats - 1) then
00293 n_end = 6
00294 else
00295 n_end = 9
00296 endif
00297
00298
00299 do n = n, n_end
00300
00301 curr_stencil_idx = n_to_stencil_base_idx(n)
00302
00303
00304 method_cell = get_method_cell (curr_stencil_idx, curr_stencil, &
00305 curr_3d_base_idx(2))
00306
00307
00308 do while (point%x < minval (method_cell(:)%x))
00309 point%x = point%x + grid_extent
00310 enddo
00311 do while (point%x > maxval (method_cell(:)%x))
00312 point%x = point%x - grid_extent
00313 enddo
00314
00315 #ifdef DEBUG_TRACE
00316 if (debug_trace) then
00317 if (debug_point%x /= point%x) then
00318 print '(2(1x,a),/,2f8.2)', out_prefix, &
00319 "point coordinates were adjusted to method cell range:", point
00320 debug_point = point
00321 endif
00322 endif
00323 #endif
00324
00325
00326 if (point_is_in_quadrangle (point, method_cell)) then
00327
00328 found (i,j,k) = val_coupler
00329 exit
00330 endif
00331 enddo
00332
00333
00334 if (found (i,j,k) == val_coupler) then
00335 #ifdef DEBUG_TRACE
00336 if (debug_trace) then
00337 print *, out_prefix, ' found matching cell'
00338 endif
00339 #endif
00340
00341 if (curr_stencil(curr_stencil_idx) <= local_coords_shape(2,1)) then
00342
00343 loc (i,j,k) = curr_stencil(curr_stencil_idx)
00344 #ifdef DEBUG_TRACE
00345 if (debug_trace) then
00346 print *, out_prefix, ' new loc =', loc (i,j,k)
00347 endif
00348 #endif
00349 else
00350
00351 virtual_cell (i,j,k) = &
00352 stencil_idx_to_virtual_cell(curr_stencil_idx)
00353 #ifdef DEBUG_TRACE
00354 if (debug_trace) then
00355 print *, out_prefix, ' cell is virtual cell at stencil idx', &
00356 curr_stencil_idx, 'virt. cell idx', virtual_cell (i,j,k)
00357 endif
00358 #endif
00359 endif
00360 else
00361 found (i,j,k) = not_found
00362 endif
00363 endif
00364 enddo
00365 enddo
00366 enddo
00367
00368
00369 deallocate (loc_3d)
00370 if (num_remote_points > 0) deallocate (src_coords_x, src_coords_y)
00371
00372 #ifdef VERBOSE
00373 print 9980, trim(ch_id)
00374
00375 call psmile_flushstd
00376 #endif /* VERBOSE */
00377
00378
00379
00380 9990 format (1x, a, ': psmile_mg_method_gauss2_real:')
00381 9980 format (1x, a, ': psmile_mg_method_gauss2_real: eof')
00382
00383 contains
00384
00385
00386
00387
00388
00389 function get_method_cell(idx, stencil, g_latitude_idx)
00390
00391 integer, intent (in) :: idx, stencil(16), g_latitude_idx
00392
00393 type (point_real) :: get_method_cell(4)
00394
00395 type (point_real) :: method_cell(4)
00396 integer, parameter :: neighbours(3,16) =
00397 reshape ((/ 2, 6, 5, 3, 7, 6, 4, 8, 7, -1,-1,-1,
00398 6,10, 9, 7,11,10, 8,12,11, -1,-1,-1,
00399 10,14,13, 11,15,14, 12,16,15, -1,-1,-1,
00400 -1,-1,-1, -1,-1,-1, -1,-1,-1, -1,-1,-1/),
00401 (/3,16/))
00402
00403 integer, parameter :: latitude_off(16) = (/-1,-1,-1, 0,
00404 0, 0, 0, 0,
00405 1, 1, 1, 0,
00406 0, 0, 0, 0/)
00407
00408 #ifdef DEBUG_TRACE
00409 if (debug_trace) then
00410 print *, out_prefix, ' stencil =', stencil
00411 print *, out_prefix, ' stencil idx =', idx
00412 print *, out_prefix, ' generating method cell with indices:', &
00413 stencil(idx), stencil(neighbours(:,idx))
00414 endif
00415 #endif
00416
00417 method_cell(1)%x = src_coords_x(stencil(idx))
00418
00419
00420
00421 method_cell(2)%x = src_coords_x(stencil(neighbours(1,idx)))
00422
00423
00424 method_cell(3)%x = src_coords_x(stencil(neighbours(2,idx)))
00425
00426
00427 method_cell(4)%x = src_coords_x(stencil(neighbours(3,idx)))
00428
00429
00430 if (g_latitude_idx + latitude_off(idx) == 1) then
00431
00432 method_cell(1:2)%y = sign (90.0, src_coords_y(stencil(idx)))
00433
00434 #ifdef DEBUG_TRACE
00435 if (debug_trace) then
00436 print *, out_prefix, ' extending method cell to pole'
00437 endif
00438 #endif
00439 else
00440
00441 method_cell(1)%y = src_coords_y(stencil(idx))
00442 method_cell(2)%y = src_coords_y(stencil(neighbours(1,idx)))
00443 endif
00444
00445
00446 if (g_latitude_idx + latitude_off(idx) == num_global_lats - 1) then
00447
00448 method_cell(3:4)%y = sign (90.0, src_coords_y(stencil(idx)))
00449
00450 #ifdef DEBUG_TRACE
00451 if (debug_trace) then
00452 print *, out_prefix, ' extending method cell to pole'
00453 endif
00454 #endif
00455 else
00456
00457 method_cell(3)%y = src_coords_y(stencil(neighbours(2,idx)))
00458 method_cell(4)%y = src_coords_y(stencil(neighbours(3,idx)))
00459 endif
00460
00461 #ifdef DEBUG_TRACE
00462 if (debug_trace) then
00463 print "(2(1x,a),4(/,2f8.2))", out_prefix, 'generated method cell:', &
00464 method_cell
00465 endif
00466 #endif
00467
00468
00469 call psmile_transform_cell_cyclic(method_cell(:)%x, grid_extent, ierror)
00470
00471 #ifdef DEBUG_TRACE
00472 if (debug_trace) then
00473 print "(2(1x,a),4(/,2f8.2))", &
00474 out_prefix, 'after cyclic transformation:', method_cell
00475 endif
00476 #endif
00477
00478 get_method_cell = method_cell
00479
00480 end function get_method_cell
00481
00482 end subroutine psmile_mg_method_gauss2_real