00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 subroutine psmile_get_halo_points (comp_id, ierror)
00013
00014
00015
00016 use psmile, only : halo_info, halo_block, fields, grids, methods, comps, &
00017 coords_block
00018
00019 use psmile_common, only : ndim_2d, ndim_3d, ch_id, number_of_methods_allocated, &
00020 psmile_status_defined, psmile_undef, len_cvs_string, &
00021 MPI_Request_Null, MPI_STATUS_SIZE, MPI_REAL, &
00022 MPI_DOUBLE_PRECISION, halotag
00023
00024 use prism_constants, only : prism_irrlonlat_regvrt, &
00025 prism_irrlonlatvrt, &
00026 prism_error_alloc
00027
00028 use psmile_reallocate, only : psmile_realloc
00029
00030 implicit none
00031
00032
00033
00034 integer, intent (in) :: comp_id
00035
00036
00037
00038 integer, intent (out) :: ierror
00039
00040
00041
00042
00043
00044
00045
00046 integer :: grid_id
00047 integer :: halo_id
00048 integer :: field_id
00049 integer :: method_id
00050 integer :: shift(ndim_3d)
00051 type (halo_info), pointer :: halo
00052
00053 logical :: method_needs_halos(number_of_methods_allocated)
00054 integer :: num_requests
00055 integer, pointer :: requests(:)
00056 integer, allocatable :: statuses(:,:)
00057 double precision, pointer :: dble_send_buf(:)
00058 real, pointer :: real_send_buf(:)
00059 integer :: ndim
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 Character(len=len_cvs_string), save :: mycvs =
00081 '$Id: psmile_get_halo_points.F90 2790 2010-12-01 11:26:54Z coquart $'
00082
00083
00084
00085
00086
00087 #ifdef VERBOSE
00088 print 9990, trim(ch_id)
00089 call psmile_flushstd
00090 #endif /* VERBOSE */
00091
00092 ierror = 0
00093 num_requests = 0
00094
00095 nullify (requests)
00096 nullify (dble_send_buf)
00097 nullify (real_send_buf)
00098
00099
00100 do grid_id = 1, size (Grids)
00101
00102 if ( Grids(grid_id)%status /= psmile_status_defined .or. &
00103 Grids(grid_id)%comp_id /= comp_id .or. &
00104 (Grids(grid_id)%grid_type /= prism_irrlonlat_regvrt .and. &
00105 Grids(grid_id)%grid_type /= prism_irrlonlatvrt) .or. &
00106 Grids(grid_id)%nbr_halo_segments < 1 ) then
00107 cycle
00108 endif
00109
00110 #ifdef PRISM_ASSERTION
00111 if ( .not. associated (Grids(grid_id)%partition)) then
00112 call psmile_assert (__FILE__, __LINE__, &
00113 "psmile_get_halo_points requires partition information")
00114 endif
00115 if (size (Grids(grid_id)%partition, 1) /= 1) then
00116 call psmile_assert (__FILE__, __LINE__, &
00117 "psmile_get_halo_points does not support more than one block per grid")
00118 endif
00119 #endif
00120
00121 method_needs_halos = .false.
00122
00123
00124
00125 do field_id = 1, size (Fields)
00126
00127
00128
00129 if (fields(field_id)%smioc_loc /= psmile_undef .and. &
00130 associated (fields(field_id)%taskout)) then
00131
00132
00133
00134 if ( methods(fields(field_id)%method_id)%grid_id == grid_id) then
00135
00136 method_needs_halos(fields(field_id)%method_id) = .true.
00137
00138 call init_method_halos(fields(field_id)%method_id, &
00139 Grids(grid_id)%nbr_halo_segments)
00140 endif
00141 endif
00142 enddo
00143
00144
00145
00146 if (count (method_needs_halos) == 0) cycle
00147
00148
00149
00150
00151 shift = Grids(grid_id)%grid_shape(1,:)-(Grids(grid_id)%partition(1,:) + 1)
00152
00153
00154
00155 if ( Grids(grid_id)%grid_type == prism_irrlonlat_regvrt ) then
00156 ndim = ndim_2d
00157 else
00158 ndim = ndim_3d
00159 endif
00160
00161
00162
00163 requests => psmile_realloc(requests, num_requests + Grids(grid_id)%nbr_halo_segments &
00164 * count (method_needs_halos) * ndim)
00165 requests(num_requests+1:) = MPI_Request_Null
00166
00167
00168
00169 do halo_id = 1, Grids(grid_id)%nbr_halo_segments
00170
00171
00172 halo => Grids(grid_id)%halo(halo_id)
00173
00174
00175
00176 do method_id = 1, size (method_needs_halos)
00177
00178 if (method_needs_halos(method_id)) then
00179
00180
00181
00182
00183
00184
00185 call recv_halo (method_id, halo, halo_id, shift, ndim, &
00186 requests(num_requests+1:num_requests+ndim), ierror)
00187 num_requests = num_requests + ndim
00188
00189
00190
00191 call send_halo (method_id, halo, shift, ndim, ierror)
00192
00193 endif
00194 enddo
00195 enddo
00196 enddo
00197
00198 if (num_requests > 0) then
00199
00200 allocate (statuses(MPI_STATUS_SIZE,num_requests), stat=ierror)
00201 if (ierror /= 0) then
00202 ierror = prism_error_alloc
00203 call psmile_error (ierror, 'statuses', (/num_requests * MPI_STATUS_SIZE/), &
00204 1, __FILE__, __LINE__)
00205 return
00206 endif
00207
00208
00209
00210 call MPI_Waitall ( num_requests, requests, statuses, ierror )
00211
00212 deallocate (requests, statuses)
00213
00214 if (associated (dble_send_buf)) deallocate (dble_send_buf)
00215 if (associated (real_send_buf)) deallocate (real_send_buf)
00216
00217 endif
00218
00219 #ifdef VERBOSE
00220 print 9980, trim(ch_id), ierror
00221 call psmile_flushstd
00222 #endif /* VERBOSE */
00223
00224
00225
00226 9990 format (1x, a, ': psmile_get_halo_points')
00227 9980 format (1x, a, ': psmile_get_halo_points; eof ierror =', i4)
00228
00229 contains
00230
00231
00232
00233 subroutine init_method_halos (method_id, num_halos)
00234
00235 integer, intent (in) :: method_id
00236 integer, intent (in) :: num_halos
00237
00238 integer :: i
00239 integer :: j
00240
00241 allocate(Methods(method_id)%halo_pointer(num_halos), stat=ierror)
00242 if (ierror /= 0) then
00243 ierror = prism_error_alloc
00244 call psmile_error (ierror, 'halo_pointer', (/num_halos/), 1, &
00245 __FILE__, __LINE__ )
00246 return
00247 endif
00248
00249 do i = 1, num_halos
00250
00251 Methods(method_id)%halo_pointer(i)%halo_local = .false.
00252 Methods(method_id)%halo_pointer(i)%halo_shape = psmile_undef
00253 do j = 1, ndim_3d
00254 nullify(Methods(method_id)%halo_pointer(i)%halo_real(j)%vector)
00255 nullify(Methods(method_id)%halo_pointer(i)%halo_dble(j)%vector)
00256 #if defined ( PRISM_QUAD_TYPE )
00257 nullify(Methods(method_id)%halo_pointer(i)%halo_quad(j)%vector)
00258 #endif
00259 enddo
00260
00261 enddo
00262
00263 end subroutine
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276 integer function generate_send_tag (grid_id, remote_grid_id, face)
00277
00278 integer, intent (in) :: grid_id
00279 integer, intent (in) :: remote_grid_id
00280 integer, intent (in) :: face
00281
00282 #ifdef PRISM_ASSERTION
00283 if ((grid_id > 255) .or. (remote_grid_id > 255)) then
00284 call psmile_assert (__FILE__, __LINE__, &
00285 "local grid id is bigger than 255 (halo tag definition needs to be adjusted)")
00286 endif
00287 #endif
00288 generate_send_tag = halotag + ishft(grid_id, 16) + ishft(remote_grid_id, 24)
00289
00290 end function generate_send_tag
00291
00292
00293
00294 integer function generate_recv_tag (grid_id, remote_grid_id, face)
00295
00296 integer, intent (in) :: grid_id
00297 integer, intent (in) :: remote_grid_id
00298 integer, intent (in) :: face
00299
00300 #ifdef PRISM_ASSERTION
00301 if ((grid_id > 255) .or. (remote_grid_id > 255)) then
00302 call psmile_assert (__FILE__, __LINE__, &
00303 "local grid id is bigger than 255 (halo tag definition needs to be adjusted)")
00304 endif
00305 #endif
00306 generate_recv_tag = halotag + ishft(grid_id, 24) + ishft(remote_grid_id, 16)
00307
00308 end function generate_recv_tag
00309
00310
00311
00312 subroutine extract_data_2d_dble (tgt, tgt_shape, src, src_shape)
00313
00314 integer, intent (in) :: tgt_shape(2,ndim_2d)
00315
00316 double precision, intent (out) :: tgt(tgt_shape(1,1):tgt_shape(2,1),
00317 tgt_shape(1,2):tgt_shape(2,2))
00318
00319 integer, intent (in) :: src_shape(2,ndim_2d)
00320
00321 double precision, intent (in) :: src(src_shape(1,1):src_shape(2,1),
00322 src_shape(1,2):src_shape(2,2))
00323
00324 tgt = src(tgt_shape(1,1):tgt_shape(2,1), &
00325 tgt_shape(1,2):tgt_shape(2,2))
00326
00327 end subroutine extract_data_2d_dble
00328
00329
00330
00331 subroutine extract_data_2d_real (tgt, tgt_shape, src, src_shape)
00332
00333 integer, intent (in) :: tgt_shape(2,ndim_2d)
00334
00335 real, intent (out) :: tgt(tgt_shape(1,1):tgt_shape(2,1),
00336 tgt_shape(1,2):tgt_shape(2,2))
00337
00338 integer, intent (in) :: src_shape(2,ndim_2d)
00339
00340 real, intent (in) :: src(src_shape(1,1):src_shape(2,1),
00341 src_shape(1,2):src_shape(2,2))
00342
00343 tgt = src(tgt_shape(1,1):tgt_shape(2,1), &
00344 tgt_shape(1,2):tgt_shape(2,2))
00345
00346 end subroutine extract_data_2d_real
00347
00348
00349
00350 subroutine extract_data_3d_dble (tgt, tgt_shape, src, src_shape)
00351
00352 integer, intent (in) :: tgt_shape(2,ndim_3d)
00353
00354 double precision, intent (out) :: tgt(tgt_shape(1,1):tgt_shape(2,1),
00355 tgt_shape(1,2):tgt_shape(2,2),
00356 tgt_shape(1,3):tgt_shape(2,3))
00357
00358 integer, intent (in) :: src_shape(2,ndim_3d)
00359
00360 double precision, intent (in) :: src(src_shape(1,1):src_shape(2,1),
00361 src_shape(1,2):src_shape(2,2),
00362 src_shape(1,3):src_shape(2,3))
00363
00364 tgt = src(tgt_shape(1,1):tgt_shape(2,1), &
00365 tgt_shape(1,2):tgt_shape(2,2), &
00366 tgt_shape(1,3):tgt_shape(2,3))
00367
00368 end subroutine extract_data_3d_dble
00369
00370
00371
00372 subroutine extract_data_3d_real (tgt, tgt_shape, src, src_shape)
00373
00374 integer, intent (in) :: tgt_shape(2,ndim_3d)
00375
00376 real, intent (out) :: tgt(tgt_shape(1,1):tgt_shape(2,1),
00377 tgt_shape(1,2):tgt_shape(2,2),
00378 tgt_shape(1,3):tgt_shape(2,3))
00379
00380 integer, intent (in) :: src_shape(2,ndim_3d)
00381
00382 real, intent (in) :: src(src_shape(1,1):src_shape(2,1),
00383 src_shape(1,2):src_shape(2,2),
00384 src_shape(1,3):src_shape(2,3))
00385
00386 tgt = src(tgt_shape(1,1):tgt_shape(2,1), &
00387 tgt_shape(1,2):tgt_shape(2,2), &
00388 tgt_shape(1,3):tgt_shape(2,3))
00389
00390 end subroutine extract_data_3d_real
00391
00392
00393
00394 subroutine send_halo (method_id, halo, shift, ndim, ierror)
00395
00396 integer, intent (in) :: method_id
00397 type (halo_info), intent (inout) :: halo
00398 integer, intent (in) :: shift(ndim_3d)
00399 integer, intent (in) :: ndim
00400 integer, intent (inout) :: ierror
00401
00402 integer :: curr_buffer_size
00403 integer :: local_send_range(2, ndim_3d)
00404 integer :: i
00405 integer :: tag
00406 type (coords_block), pointer :: coords_pointer
00407
00408 tag = generate_send_tag(Methods(method_id)%grid_id, halo%remote_grid_id, 1)
00409
00410 local_send_range(1,:) = halo%send_range(1,:) + shift
00411 local_send_range(2,:) = halo%send_range(2,:) + shift
00412
00413 #ifdef DEBUG
00414 print 9995, trim(ch_id), " sending halo to rank ", halo%remote_rank, " with tag ", tag
00415 print 9996, trim(ch_id), " local range: ", local_send_range
00416 print 9996, trim(ch_id), " global range: ", halo%send_range
00417 call psmile_flushstd
00418 #endif
00419
00420 coords_pointer => Methods(method_id)%coords_pointer
00421
00422 if (coords_pointer%coords_datatype == MPI_REAL) then
00423
00424
00425 if (.not. associated (real_send_buf)) then
00426 curr_buffer_size = 0
00427 else
00428 curr_buffer_size = size (real_send_buf)
00429 endif
00430
00431
00432 if (curr_buffer_size < halo%halo_size) then
00433 real_send_buf => psmile_realloc (real_send_buf, halo%halo_size)
00434 endif
00435
00436 do i = 1, ndim
00437
00438 if (ndim == ndim_3d) then
00439 call extract_data_3d_real (real_send_buf, local_send_range, &
00440 coords_pointer%coords_real(i)%vector, &
00441 coords_pointer%coords_shape)
00442 else
00443 call extract_data_2d_real (real_send_buf, local_send_range, &
00444 coords_pointer%coords_real(i)%vector, &
00445 coords_pointer%coords_shape)
00446 endif
00447
00448 call psmile_bsend (real_send_buf, halo%halo_size, MPI_REAL, halo%remote_rank, &
00449 tag, Comps(comp_id)%comm, ierror)
00450 enddo
00451
00452 else
00453
00454
00455
00456 if (.not. associated (dble_send_buf)) then
00457 curr_buffer_size = 0
00458 else
00459 curr_buffer_size = size (dble_send_buf)
00460 endif
00461
00462
00463
00464 if (curr_buffer_size < halo%halo_size) then
00465 dble_send_buf => psmile_realloc (dble_send_buf, halo%halo_size)
00466 endif
00467
00468 do i = 1, ndim
00469
00470
00471
00472 if (ndim == ndim_3d) then
00473 call extract_data_3d_dble (dble_send_buf, local_send_range, &
00474 coords_pointer%coords_dble(i)%vector, &
00475 coords_pointer%coords_shape)
00476 else
00477 call extract_data_2d_dble (dble_send_buf, local_send_range, &
00478 coords_pointer%coords_dble(i)%vector, &
00479 coords_pointer%coords_shape)
00480 endif
00481
00482 call psmile_bsend (dble_send_buf, halo%halo_size, MPI_DOUBLE_PRECISION, halo%remote_rank, &
00483 tag, Comps(comp_id)%comm, ierror)
00484 enddo
00485
00486 endif
00487
00488 9995 format (1x, a, ': psmile_get_halo_points:', a, i4, a, i10)
00489 9996 format (1x, a, ': psmile_get_halo_points:', a, 6i4)
00490
00491 end subroutine send_halo
00492
00493
00494
00495 subroutine recv_halo (method_id, halo, halo_id, shift, ndim, request, ierror)
00496
00497 integer, intent (in) :: method_id
00498 type (halo_info), intent (inout) :: halo
00499 integer, intent (in) :: halo_id
00500 integer, intent (in) :: shift(ndim_3d)
00501 integer, intent (in) :: ndim
00502 integer, intent (out) :: request(ndim)
00503 integer, intent (inout) :: ierror
00504
00505 integer :: tag
00506 integer :: i
00507 type (halo_block), pointer :: halo_pointer
00508
00509 tag = generate_recv_tag (Methods(method_id)%grid_id, halo%remote_grid_id, 1)
00510
00511 halo_pointer => Methods(method_id)%halo_pointer(halo_id)
00512
00513 halo_pointer%halo_shape(1,:) = halo%global_range(1,:) + shift(:)
00514 halo_pointer%halo_shape(2,:) = halo%global_range(2,:) + shift(:)
00515
00516 #ifdef DEBUG
00517 print 9995, trim(ch_id), " requesting halo from rank ", halo%remote_rank, " with tag ", tag
00518 print 9996, trim(ch_id), " local range: ", halo_pointer%halo_shape
00519 print 9996, trim(ch_id), " global range: ", halo%global_range
00520 call psmile_flushstd
00521 #endif
00522
00523 if (Methods(method_id)%coords_pointer%coords_datatype == MPI_REAL) then
00524
00525 do i = 1, ndim
00526
00527 allocate(halo_pointer%halo_real(i)%vector(halo%halo_size), &
00528 stat=ierror)
00529 if (ierror /= 0) then
00530 ierror = PRISM_Error_Alloc
00531 call psmile_error ( ierror, 'halo_pointer', (/halo%halo_size/), 1, &
00532 __FILE__, __LINE__ )
00533 return
00534 endif
00535
00536 call MPI_Irecv (halo_pointer%halo_real(i)%vector, &
00537 halo%halo_size, MPI_REAL, halo%remote_rank, tag, &
00538 Comps(comp_id)%comm, request(i), ierror)
00539 enddo
00540
00541 else
00542
00543 do i = 1, ndim
00544
00545 allocate(halo_pointer%halo_dble(i)%vector(halo%halo_size), &
00546 stat=ierror)
00547 if (ierror /= 0) then
00548 ierror = PRISM_Error_Alloc
00549 call psmile_error ( ierror, 'halo_pointer', (/halo%halo_size/), 1, &
00550 __FILE__, __LINE__ )
00551 return
00552 endif
00553
00554 call MPI_Irecv (halo_pointer%halo_dble(i)%vector, &
00555 halo%halo_size, MPI_DOUBLE_PRECISION, halo%remote_rank, tag, &
00556 Comps(comp_id)%comm, request(i), ierror)
00557 enddo
00558
00559 endif
00560
00561 9995 format (1x, a, ': psmile_get_halo_points:', a, i4, a, i10)
00562 9996 format (1x, a, ': psmile_get_halo_points:', a, 6i4)
00563
00564 end subroutine recv_halo
00565
00566 end subroutine psmile_get_halo_points