psmile_global_search_nnx_dble.F90

Go to the documentation of this file.
00001 !-----------------------------------------------------------------------
00002 ! Copyright 2006-2010, NEC Europe Ltd., London, UK.
00003 ! All rights reserved. Use is subject to OASIS4 license terms.
00004 !-----------------------------------------------------------------------
00005 !BOP
00006 !
00007 ! !ROUTINE: PSMILe_global_search_nnx_dble
00008 !
00009 ! !INTERFACE:
00010 
00011       subroutine psmile_global_search_nnx_dble (comp_info, search,        &
00012                         var_id, tgt_coords_x, tgt_coords_y, tgt_coords_z, &
00013                         neighbors_3d, nloc, num_neigh, nb_extra,          &
00014                         extra_search, send_index,                         &
00015                         ierror)
00016 !
00017 ! !USES:
00018 !
00019       use PRISM
00020 !
00021       use psmile_grid, only : psmile_transform_extent_cyclic, &
00022                               psmile_transform_extent_back, &
00023                               max_num_trans_parts, &
00024                               code_no_trans, &
00025                               common_grid_range
00026 !
00027       use PSMILe, dummy_interface => PSMILe_global_search_nnx_dble
00028 
00029       Implicit none
00030 !
00031 ! !INPUT PARAMETERS:
00032 
00033       Type (Enddef_comp), Intent (In) :: comp_info
00034 !
00035 !     Info on the component in which the donor cells
00036 !     should be searched.
00037 !
00038       Type (Enddef_search), Intent (InOut) :: search
00039 
00040 !     Info's on coordinates to be searched
00041 
00042       Integer,            Intent (In) :: var_id
00043 
00044 !     Handle to the grid function
00045 
00046       Integer,            Intent (In) :: send_index
00047 
00048 !     Send index of coupler send for the method and coordinates
00049 
00050       Integer,            Intent (In) :: nloc
00051 !
00052 !     Total  Number of locations to be transferred
00053 !
00054       Double Precision,   Intent (In) :: tgt_coords_x (nloc)
00055       Double Precision,   Intent (In) :: tgt_coords_y (nloc)
00056       Double Precision,   Intent (In) :: tgt_coords_z (nloc)
00057 
00058 !     Coordinates of the target points (which were searched and found)
00059 !
00060       Integer,            Intent (In) :: num_neigh
00061 !
00062 !     Last dimension of neighbors array "neighbors_3d" and
00063 !     number of neighbors to be searched.
00064 !     besser n_corners
00065 
00066       Integer,            Intent (In) :: nb_extra
00067 !
00068 !     Number of nearest neigbhbours to be searched per extra point
00069 !
00070 ! !INPUT/OUTPUT PARAMETERS:
00071 !
00072       Integer,            Intent (InOut) :: neighbors_3d (ndim_3d, nloc, 
00073                                                           num_neigh)
00074 
00075 !     Indices of neighbor locations (interpolation bases)
00076 !
00077       Type (Extra_search_info), Intent (InOut) :: extra_search
00078 !
00079 !     Number of locations where
00080 !       (*) required mask values were not true
00081 
00082 ! !OUTPUT PARAMETERS:
00083 !
00084       Integer,           Intent (Out) :: ierror
00085 
00086 !     Returns the error code of PSMILe_global_search_nnx_dble;
00087 !             ierror = 0 : No error
00088 !             ierror > 0 : Severe error
00089 !
00090 ! !LOCAL PARAMETERS
00091 !
00092 !  DBLE_EARTH = Earth radius in meter
00093 !
00094 !  LEN_ITEM = Number of pieces of information
00095 !             in integer buffer "ibuf"
00096 !             1: index in indices/dist_dble/send_mask
00097 !  INLP_LEN = Inner loop length for optimization
00098 !  lon   = Index of Longitudes in arrays "boxes"
00099 !  lat   = Index of Latitudes  in arrays "boxes"
00100 !  vrt   = Index of height     in arrays "boxes"
00101 !
00102 !
00103       Double Precision, Parameter     :: dble_earth = 6400000.0d0
00104 !
00105       Integer, Parameter              :: len_item = 1
00106 !
00107       Integer, Parameter              :: inlp_len = 256
00108 !
00109       Integer, Parameter              :: lon = 1
00110       Integer, Parameter              :: lat = 2
00111       Integer, Parameter              :: vrt = 3
00112 !
00113 !
00114 ! !LOCAL VARIABLES
00115 !
00116 !     ... Method pointer
00117 !
00118       Integer                         :: comp_id, grid_id
00119       Integer                         :: global_grid_id
00120       Integer, Pointer                :: indices (:)
00121 !
00122 !     ... Info's on actual component
00123 !
00124       Integer                         :: igrid, rank
00125       Integer                         :: n_total
00126       Integer                         :: grid_type
00127       Real (PSMILe_float_kind), Pointer :: extents (:, :, :)
00128 !
00129 !     ... lookup table
00130 !
00131       Integer, allocatable            :: igrid_to_dest_comp(:)
00132 !
00133 !     ... loop variables
00134 !
00135       Integer                         :: j, n
00136       Integer                         :: ibeg, iend
00137 !
00138 !     ... for data to other processes
00139 !
00140       Logical                         :: mask_changed
00141       Integer                         :: n_extra
00142 !
00143       Logical, Allocatable            :: send_mask (:)
00144       Double Precision, Allocatable   :: boxes (:, :, :)
00145       Real (PSMILe_float_kind)        :: range_box (2, ndim_3d)
00146       Real (PSMILe_float_kind)        :: dist_max (2)
00147       Double Precision                :: dble_huge
00148 !
00149 !     ... For locations controlled
00150 !
00151 !     Double Precision, Pointer       :: sin_search (:, :)
00152 !     Double Precision, Pointer       :: cos_search (:, :)
00153 !     Double Precision, Pointer       :: z_search (:)
00154       Double Precision, Pointer       :: dist_dble (:, :)
00155       Double Precision                :: r_earth2, r_lat
00156       Double Precision                :: delta, sin_d, cos_lat
00157 !
00158 !     ... transformed faces
00159 !
00160       Integer                         :: n_trans, n_int
00161 !
00162       Integer                         :: tr_codes (max_num_trans_parts)
00163       Integer                         :: found (max_num_trans_parts)
00164       Real (PSMILe_float_kind)        :: dinter_trans (2, ndim_3d)
00165       Real (PSMILe_float_kind)        :: transformed (2, ndim_3d, 
00166                                                       max_num_trans_parts), 
00167                                          dinter (2, ndim_3d, max_num_trans_parts)
00168 !
00169       Double Precision, Save          :: period2 (ndim_3d)
00170 !
00171 !     ... for points found
00172 !
00173       Integer                         :: n_found, n_liste
00174       Integer                         :: ip_dist
00175 !
00176 !     ... for send to partners
00177 !
00178       Type (Send_information), Pointer :: send_info
00179       Integer                         :: extra_msg (nd_msgextra)
00180 !
00181       Integer                         :: i, ip, ipi, ireq
00182       Integer                         :: len_ibuf, ndibuf, n_send
00183       Integer                         :: len_rbuf, len_rtem, ndrbuf
00184       Integer, Allocatable            :: ibuf (:)
00185       Double Precision, Pointer       :: buf (:)
00186 !
00187 !     ... for recv from partners
00188 !
00189       Integer                         :: answer (nd_msgextra)
00190       Integer, Allocatable            :: selected (:, :)
00191       Type (Select_search_info), Pointer  :: sel_info (:)
00192 !
00193 !     ... for communication
00194 !
00195       Integer                         :: dest, index, dest_comp, sender
00196       Integer                         :: nrecv, n_recv_req
00197       Integer                         :: recv_req
00198       Integer                         :: save_lreq (2:3)
00199       Integer                         :: status (MPI_STATUS_SIZE)
00200 !
00201 !     ... for error handling
00202 !
00203       Integer, Parameter              :: nerrp = 3
00204       Integer                         :: ierrp (nerrp)
00205 !
00206 ! !DESCRIPTION:
00207 !
00208 ! Subroutine "PSMILe_global_search_nnx_dble" performs a global 
00209 ! nearest neighbour search for the interpolation points 
00210 ! which require an extra seach.
00211 !
00212 ! TODO: Save buffer indices in indices/send_mask/dist_dble (see len_item)
00213 !       locally instead of passing them !!!
00214 !
00215 ! !REVISION HISTORY:
00216 !
00217 !   Date      Programmer   Description
00218 ! ----------  ----------   -----------
00219 ! 09.10.06    H. Ritzdorf  created
00220 !
00221 !EOP
00222 !----------------------------------------------------------------------
00223 !
00224 !  $Id: psmile_global_search_nnx_dble.F90 2935 2011-02-03 07:52:41Z redler $
00225 !  $Author: redler $
00226 !
00227    Character(len=len_cvs_string), save :: mycvs = 
00228        '$Id: psmile_global_search_nnx_dble.F90 2935 2011-02-03 07:52:41Z redler $'
00229 !
00230 !----------------------------------------------------------------------
00231 !
00232 !  Initialization
00233 !
00234 #ifdef VERBOSE
00235       print 9990, trim(ch_id), var_id, search%msg_intersections%first_tgt_method_id, search%sender
00236 #endif /* VERBOSE */
00237 
00238       call psmile_flushstd
00239 !
00240       ierror = 0
00241 !
00242       ndrbuf = 0
00243       ndibuf = 0
00244       n_recv_req = 0
00245 !
00246       r_earth2 = 1.0d0 / (dble_earth * 2.0)
00247       r_lat = 1.0d0 / (dble_earth * dble_deg2rad)
00248 !
00249       period2 = (common_grid_range(2,:) - common_grid_range(1,:)) / 2.0d0
00250 !
00251       grid_id        = Methods(Fields(var_id)%method_id)%grid_id
00252       global_grid_id = Grids(grid_id)%global_grid_id
00253       grid_type      = Grids(grid_id)%grid_type
00254 !
00255       comp_id = comp_info%comp_id
00256 !
00257 ! Uebergeben oder ein-dimensional
00258 !
00259       send_info => Methods(Fields(var_id)%method_id)%send_infos_coupler(send_index)
00260 !
00261       indices    => extra_search%indices
00262       dist_dble  => extra_search%dist_dble
00263 !
00264       n_extra = extra_search%n_extra
00265 !
00266 #ifdef PRISM_ASSERTION
00267 #ifdef HUHU
00268       sin_search => extra_search%sin_search_dble
00269       cos_search => extra_search%cos_search_dble 
00270         z_search => extra_search%z_search_dble
00271       if ( .not. Associated (extra_search%dist_dble)       .or. &
00272            .not. Associated (extra_search%cos_search_dble) .or. &
00273            .not. Associated (extra_search%sin_search_dble) .or. &
00274            .not. Associated (extra_search%z_search_dble)   ) then
00275 #else
00276       if ( .not. Associated (extra_search%dist_dble) ) then
00277 #endif
00278 !
00279          call psmile_assert (__FILE__, __LINE__, &
00280                              "arrays should be allocated and set")
00281       endif
00282 #endif
00283 !
00284 !  Rank of actual process in Component communicator
00285 !
00286       rank    = Comps(comp_id)%rank
00287 !
00288 ! n_total   = Total number of grids/extents       in array "all_extents"
00289 ! igrid_end = Last  grid/extent of actual process in array "all_extents"
00290 ! igrid     = Index of actual grid in array "all_extents"
00291 !
00292       extents => comp_info%all_extents
00293 !
00294       n_total   = SUM (comp_info%Number_of_grids_vector(:))
00295 !
00296       igrid = search%msg_intersections%first_src_all_extents_grid_id
00297 !
00298 ! Can man die offset und partition information ausnutzen ?
00299 !
00300 !===> Allocate work vectors
00301 !
00302 ! boxes(i)     = Box around ith extra point with interior radius
00303 !                "dist_dble (i)"
00304 ! send_mask(i) = Does the i-th extra point to be transferred 
00305 !                to the corresponding process ?
00306 !
00307       Allocate (boxes (2, ndim_3d, n_extra), STAT = ierror)
00308 
00309       if ( ierror > 0 ) then
00310          ierrp (1) = ierror
00311          ierrp (2) = n_extra * (2 * ndim_3d)
00312 
00313          ierror = PRISM_Error_Alloc
00314          call psmile_error ( ierror, 'boxes', &
00315                              ierrp, 2, __FILE__, __LINE__ )
00316          return
00317       endif
00318 !
00319       Allocate (send_mask (n_extra), STAT = ierror)
00320 
00321       if ( ierror > 0 ) then
00322          ierrp (1) = ierror
00323          ierrp (2) = n_extra
00324 
00325          ierror = PRISM_Error_Alloc
00326          call psmile_error ( ierror, 'send_mask', &
00327                              ierrp, 2, __FILE__, __LINE__ )
00328          return
00329       endif
00330 !
00331       mask_changed = .true.
00332 !
00333 !===> Compute range (bounding box) for global nearest neighbour
00334 !     search of extra points
00335 !
00336 !     ?dist_dble = huge ? neighbors_3d (:, i, nb_extra) auswerten ?
00337 !     !!! TODO: Diese Punkte loesen eine Suche in allen Bloecken aus !
00338 !               Besser erst lokal in der Nachbarschaft suchen !
00339 !
00340 !==> Get maximal extension for 3rd direction (z-direction)
00341 !    ? einmal berechnen ?
00342 !
00343      dble_huge = huge (dist_dble(1,1))
00344      dist_max (1) = extents (1, vrt, igrid)
00345      dist_max (2) = extents (2, vrt, igrid)
00346 !
00347 #ifdef DEBUGX
00348      print *, "dist_max", dist_max
00349 #endif
00350 !
00351       do n = 1, n_total
00352         if (global_grid_id == comp_info%all_extent_infos(4,n)) then
00353            dist_max (1) = min (dist_max(1), extents(1, vrt, n))
00354            dist_max (2) = max (dist_max(2), extents(2, vrt, n))
00355         endif
00356       end do
00357 #ifdef DEBUGX
00358      print *, "dist_max", dist_max
00359 #endif
00360 !
00361       do ibeg = 1, n_extra, inlp_len
00362          iend = min (n_extra, ibeg + inlp_len - 1)
00363 !
00364 !        Construct boxes of interest in lon direction
00365 !        Delta lon = 2 * asin (sin (dist_dble/(2*dble_earth)) / cos (lat))
00366 !                    / dble_deg2rad
00367 !cdir vector
00368          do i = ibeg, iend
00369             if (dist_dble(i, nb_extra) * r_earth2 >= dble_pih) then
00370                sin_d = 1.0d0
00371             else
00372                sin_d = abs(sin(dist_dble(i, nb_extra) * r_earth2))
00373             endif
00374 
00375             cos_lat = cos (tgt_coords_y(indices(i)) * dble_deg2rad)
00376 
00377             if (sin_d >= cos_lat) then
00378                delta = period2(lon)
00379             else
00380                delta = 2.0d0 * asin (sin_d / cos_lat) / dble_deg2rad
00381                delta = min (period2(lon), delta)
00382             endif
00383 
00384             boxes (1, lon, i) = tgt_coords_x(indices(i)) - delta
00385             boxes (2, lon, i) = tgt_coords_x(indices(i)) + delta
00386          end do
00387 
00388 !cdir vector
00389          do i = ibeg, iend
00390             if (boxes (2,lon,i) - boxes (1,lon,i) > period2(lon)*2) then
00391                boxes (1,lon,i) = -period2(lon)
00392                boxes (2,lon,i) =  period2(lon)
00393             else if (boxes (1,lon,i) < -period2(lon)*2) then
00394                boxes (1,lon,i) = boxes (1,lon,i) + period2(lon)*2
00395                boxes (2,lon,i) = boxes (2,lon,i) + period2(lon)*2
00396             else if (boxes (2,lon,i) >  period2(lon)*2) then
00397                boxes (1,lon,i) = boxes (1,lon,i) - period2(lon)*2
00398                boxes (2,lon,i) = boxes (2,lon,i) - period2(lon)*2
00399             endif
00400          end do ! i
00401 
00402 !        Construct boxes of interest in lat direction
00403 !        Delta lat = dist_dble / (dble_earth * dble_deg2rad)
00404 
00405 !cdir vector
00406          do i = ibeg, iend
00407             boxes (1, lat, i) = max (tgt_coords_y(indices(i)) -                        &
00408                                      min (period2(lat), dist_dble(i, nb_extra)*r_lat), &
00409                                      common_grid_range(1,lat))
00410             boxes (2, lat, i) = min (tgt_coords_y(indices(i)) +                        &
00411                                      min (period2(lat), dist_dble(i, nb_extra)*r_lat), &
00412                                      common_grid_range(2,lat))
00413          end do
00414       end do ! j
00415 !
00416       range_box (1, lon) = minval (boxes (1, lon, :))
00417       range_box (2, lon) = maxval (boxes (2, lon, :))
00418 !
00419       range_box (1, lat) = minval (boxes (1, lat, :))
00420       range_box (2, lat) = maxval (boxes (2, lat, :))
00421 !
00422 !        Construct boxes of interest in vertical direction
00423 !cdir vector
00424       do i = 1, n_extra
00425          if (dist_dble(i, nb_extra) == dble_huge) then
00426             boxes (1, vrt, i) = dist_max (1)
00427             boxes (2, vrt, i) = dist_max (2)
00428          else
00429             boxes (1, vrt, i) = tgt_coords_z(indices(i)) -             &
00430                               dist_dble(i, nb_extra)
00431             boxes (2, vrt, i) = tgt_coords_z(indices(i)) +             &
00432                               dist_dble(i, nb_extra)
00433 #ifdef DEBUGX
00434      print *, "dist_dble", i, indices(i), dist_dble(i, nb_extra)
00435 #endif
00436          endif
00437       end do
00438 !
00439       range_box (1, vrt) = minval (boxes (1, vrt, :))
00440       range_box (2, vrt) = maxval (boxes (2, vrt, :))
00441 !
00442 #ifdef PRISM_ASSERTION
00443       if (range_box (2,lon) - range_box (1,lon) > period2(lon)*4) then
00444           print *, 'range in lon direction', range_box (1:2,lon)
00445          call psmile_assert ( __FILE__, __LINE__, &
00446                              'range_box too large in lon direction')
00447       endif
00448 !
00449       if (range_box (2,lat) - range_box (1,lat) > period2(lat)*4) then
00450           print *, 'range in lat direction', range_box (1:2,lat)
00451          call psmile_assert ( __FILE__, __LINE__, &
00452                              'range_box too large in lat direction')
00453       endif
00454 #endif
00455 !
00456 !===> Transform range "range_box" into cyclic ranges
00457 !
00458       call psmile_transform_extent_cyclic (grid_type,           &
00459                   range_box, transformed, tr_codes, n_trans, ierror)
00460       if (ierror > 0) return
00461 !
00462 !     create lookup table for translating igrid into a icomp
00463 !
00464       Allocate (igrid_to_dest_comp(SUM(comp_info%Number_of_grids_vector)), stat = ierror)
00465 
00466       if ( ierror > 0 ) then
00467          ierrp (1) = ierror
00468          ierrp (2) = SUM(comp_info%Number_of_grids_vector)
00469 
00470          ierror = PRISM_Error_Alloc
00471          call psmile_error ( ierror, 'igrid_to_dest_comp', &
00472                              ierrp, 2, __FILE__, __LINE__ )
00473          return
00474       endif
00475 
00476       igrid = 0
00477       do dest_comp = 1, comp_info%size
00478          do j = 1, comp_info%Number_of_grids_vector(dest_comp)
00479             igrid = igrid + 1
00480             igrid_to_dest_comp(igrid) = dest_comp
00481          enddo
00482       enddo
00483 !
00484 !===> Control extents of other domains in order to find partner
00485 !
00486 ! igrid = current grid
00487 !
00488 !     loop over all grids/blocks (local and remote ones)
00489       do igrid = 1, SUM(comp_info%Number_of_grids_vector)
00490 
00491          dest_comp = igrid_to_dest_comp(igrid)
00492 
00493          if (mask_changed) then
00494             mask_changed  = .false.
00495             send_mask (:) = .false.
00496          endif
00497 !
00498 ! TODO:
00499 ! Das ist mir zu teuer; erst mit den extents in einer einfachen
00500 ! schleife potentiell partner finden; siehe found (:)
00501 ! in psmile_find_intersect
00502 !
00503 !        if current block is not part of the same global grid
00504          if (global_grid_id /= comp_info%all_extent_infos(4,igrid)) cycle
00505 !
00506 !===> ... Is this my info
00507 !         (note ranks start with 0, ...)
00508 !
00509          if (rank == dest_comp-1 .and. &
00510                comp_info%all_extent_infos(1,igrid) == grid_id) cycle
00511 !
00512 !===> ... Does the "n"-th grid and "range_box" coincide ?
00513 !        Rausziehen und vektorisieren ?
00514 !
00515 !  n_int = Number of significant intersections
00516 !
00517 !cdir vector
00518          do i = 1, n_trans
00519             dinter (1, :, i) = max (transformed(1,:,i), &
00520                                     extents(1,:,igrid))
00521             dinter (2, :, i) = min (transformed(2,:,i), &
00522                                     extents(2,:,igrid))
00523          end do
00524 !
00525          n_int = 0
00526 !cdir vector
00527          do i = 1, n_trans
00528             if (minval(dinter (2,:,i) - dinter (1,:,i)) >= 0.0d0) then
00529                n_int = n_int + 1
00530                found (n_int) = i
00531             endif
00532          end do
00533 !
00534          if (n_int == 0) cycle
00535 !
00536 !===> ... Transform intersections back into original range
00537 !
00538          do i = 1, n_int
00539             if (tr_codes(found(i)) /= code_no_trans) then
00540                call psmile_transform_extent_back (tr_codes(found(i)), &
00541                   dinter(:, :, found(i)), dinter_trans, 1, ierror)
00542                if ( ierror /= 0 ) return
00543 
00544                dinter (:, :, found(i)) = dinter_trans
00545             endif
00546          end do
00547 !
00548 !===> ... Get the extra points whose radius has an intersection
00549 !         with the extent of the "n"-th grid
00550 !
00551 ! send_mask(i) = Does the i-th extra point to be transferred 
00552 !                to the corresponding process ?
00553 !???  What about cyclic boundaries ????
00554 !???  use global offsets here !
00555 !
00556 ! Bedingung: 1. Punkt is in dinter drin
00557 !            2. vereinfachte distanz kleiner als dist_dble
00558 !
00559          do i = 1, n_int
00560 #ifdef DEBUGX
00561 print *, 'extent controlled', i, n_int, dinter(:,:,found(i))
00562 #endif
00563 !cdir vector
00564             do j = 1, n_extra
00565                send_mask (j) = send_mask (j) .or. &
00566                      (boxes(2,lon,j) >= dinter(1,lon,found(i)) .and. &
00567                       boxes(1,lon,j) <= dinter(2,lon,found(i)) .and. &
00568                       boxes(2,lat,j) >= dinter(1,lat,found(i)) .and. &
00569                       boxes(1,lat,j) <= dinter(2,lat,found(i)) .and. &
00570                       boxes(2,vrt,j) >= dinter(1,vrt,found(i)) .and. &
00571                       boxes(1,vrt,j) <= dinter(2,vrt,found(i)))
00572 #ifdef DEBUGX
00573 print *, j, boxes(:,:,j)
00574 #endif
00575             end do ! j
00576          end do ! i
00577 !
00578 !===> ... Get number of points to be sent
00579 !
00580          n_send = COUNT(send_mask)
00581          if (n_send == 0) cycle
00582 !
00583          mask_changed = .true.
00584 !
00585 !===> ... A grid of process "dest_comp" is a potential partner
00586 !
00587          dest = comp_info%psmile_ranks(dest_comp)
00588 !
00589          n_recv_req = n_recv_req + 1
00590 !
00591 #ifdef VERBOSE
00592          print 9970, trim(ch_id), rank, dest_comp, dest, n_send
00593 
00594          call psmile_flushstd
00595 #endif /* VERBOSE */
00596 !
00597 !===> ... Allocate send buffers
00598 !
00599 !  cf. subroutine PSMILe_Store_faces_3d_reg_dble
00600 !
00601 !  len_rtem = Number of pieces of information
00602 !             per point in Double Precision buffer "rbuf"
00603 !
00604 !  Double Precision vector buf (1:ndrbuf):
00605 !  buf (:) = Coordinates of the point to be searched
00606 !            ndim_3d data items
00607 !  buf (:) = Maximal distance
00608 !            1 data item
00609 !
00610 !  Integer buffer ibuf (1:ndibuf):
00611 !
00612 !  ibuf (:) = Index in indices/dist_dble/send_mask
00613 !
00614 !        len_rtem = ndim_3d + nb_extra ! coords + alle distancen
00615          len_rtem = ndim_3d + 1        ! coords + groesste Distance
00616 !
00617          len_rbuf = n_send * len_rtem
00618          len_ibuf = n_send * len_item
00619 !
00620          if (len_rbuf > ndrbuf) then
00621             if (ndrbuf > 0) then
00622                Deallocate (buf)
00623             endif
00624 !
00625             ndrbuf = len_rbuf
00626             Allocate (buf(ndrbuf), STAT = ierror)
00627 
00628             if ( ierror > 0 ) then
00629                ierrp (1) = ierror
00630                ierrp (2) = ndrbuf
00631 
00632                ierror = PRISM_Error_Alloc
00633                call psmile_error ( ierror, 'buf', &
00634                                    ierrp, 2, __FILE__, __LINE__ )
00635                return
00636             endif
00637          endif
00638 !
00639          if (len_ibuf > ndibuf) then
00640             if (ndibuf > 0) then
00641                Deallocate (ibuf)
00642             endif
00643 !
00644             ndibuf = len_ibuf
00645             Allocate (ibuf(ndibuf), STAT = ierror)
00646 
00647             if ( ierror > 0 ) then
00648                ierrp (1) = ierror
00649                ierrp (2) = ndibuf
00650 
00651                ierror = PRISM_Error_Alloc
00652                call psmile_error ( ierror, 'ibuf', &
00653                                    ierrp, 2, __FILE__, __LINE__ )
00654                return
00655             endif
00656          endif
00657 !
00658 !===> Store data in send buffers
00659 !     ??? compact machen !?!?
00660 !         Mehrfache Zellen Info's in ibuf und corner volumen
00661 !         eliminieren ?
00662 !
00663 #ifdef USE_PACK
00664          ibuf (1:n_send*len_item:len_item) = &
00665             PACK ((/ (i, i=1,n_extra) /), send_mask)
00666 #else
00667          ipi = 0
00668 
00669 !cdir vector
00670          do i = 1, n_extra
00671             if (send_mask (i)) then
00672                ibuf (ipi+1) = i
00673                ipi = ipi + len_item
00674             endif
00675          end do
00676 #endif /* USE_PACK */
00677 !
00678 !===> ... store coordinates and distance a single vectors 
00679 !         (to be consistent with storage of PRISM external coordinates)
00680 !         ? ist das wiklich besser, als die per Punkt zu speichern.
00681 !           Grund fuer die Feldweise Speicherung ist, die
00682 !           moegliche Wiederverwendung von Routinen.
00683 !
00684 ! ? besser direkt cos_search, sin_search, z versenden ?
00685 ! Das waeren 5 satt 3 items;
00686 ! Neu rechnen schneller als senden ?
00687 !              buf (ip+1) = cos_search (i, 1)
00688 !              buf (ip+2) = cos_search (i, 2)
00689 !              buf (ip+3) = sin_search (i, 1)
00690 !              buf (ip+4) = sin_search (i, 2)
00691 !              buf (ip+5) = z_search (i) = tgt_coords_z (indices(i))
00692 !
00693 #ifdef ALL_ITEM_PER_POINT
00694          ip = 0
00695 !cdir vector
00696          do i = 1, n_extra
00697             if (send_mask (i)) then
00698 !
00699                buf (ip+1) = tgt_coords_x (indices(i))
00700                buf (ip+2) = tgt_coords_y (indices(i))
00701                buf (ip+3) = tgt_coords_z (indices(i))
00702 !
00703                buf (ip+4) = dist_dble (i, nb_extra)
00704                ip = ip + len_rtem
00705             endif
00706          end do
00707 #else
00708          ip = 0
00709 !cdir vector
00710          do i = 1, n_extra
00711             if (send_mask (i)) then
00712                ip = ip + 1
00713                buf (ip           ) = tgt_coords_x (indices(i))
00714                buf (ip+ n_send   ) = tgt_coords_y (indices(i))
00715                buf (ip+(n_send*2)) = tgt_coords_z (indices(i))
00716                buf (ip+(n_send*3)) = dist_dble (i, nb_extra)
00717             endif
00718          end do
00719 #endif
00720 !
00721 #ifdef TODO
00722 ! TODO: If dest_comp == rank, direct call of psmile_search_donor_extra()
00723          if (dest_comp == rank) then
00724 !
00725             search_global%sender = dest
00726             search_global%msg_extra = msg_extra (1:nd_msg)
00727 !     search_global%len_msg = nd_msg
00728 !
00729             call psmile_search_donor_extra (search_global, tol, ierror)
00730             if (ierror > 0) return
00731 
00732          endif
00733 #endif /* TODO */
00734 !
00735 !===> ... Send request to destination process
00736 !         extra_msg is received by routine PSMILe_Enddef_extra and
00737 !         the other buffer are received by routine
00738 !         PSMILe_Enddef_action_extra.
00739 !
00740 !  extra_msg (1)  = Type of request
00741 !  extra_msg (2)  = Datatype
00742 !  extra_msg (3)  = Length of buffer "ibuf" containing the integer data.
00743 !  extra_msg (4)  = Length of buffer  "buf" containing the
00744 !                   real/double data.
00745 !  extra_msg (5)  = Global comp id of component
00746 !  extra_msg (6)  = Global var id "id_trans_out"
00747 !  extra_msg (7)  = Grid Type of sending grid
00748 !                   (PRISM_Reglonlatvrt, ...)
00749 !  extra_msg (8)  = Number of control volumes sent
00750 !  extra_msg (9)  = Number of integer data items per control
00751 !                   volume sent
00752 !  extra_msg (10) = Number of real/double data items per control
00753 !                   volume sent
00754 !  extra_msg (11) = Is data on global offset available ?
00755 !  extra_msg (12) = I-Index of global offset (partition)
00756 !  extra_msg (13) = J-Index of global offset (partition)
00757 !  extra_msg (14) = K-Index of global offset (partition)
00758 !
00759 !  extra_msg (15) = Number of the request
00760 !  extra_msg (16) = num_neigh (Number of interpolation bases)
00761 !  extra_msg (17) = local grid id on message destination process
00762 !
00763          extra_msg (1)  = PSMILe_nnghbr3D
00764          extra_msg (2)  = PRISM_DOUBLE_PRECISION
00765          extra_msg (3)  = len_ibuf
00766          extra_msg (4)  = len_rbuf
00767          extra_msg (5)  = comp_info%global_comp_id
00768          extra_msg (6)  = search%msg_intersections%transient_out_id
00769 !
00770          extra_msg (7)  = grid_type
00771          extra_msg (8)  = n_send
00772          extra_msg (9)  = len_item
00773          extra_msg (10) = len_rtem
00774 !
00775 !        ... No partition info
00776 !        Partition info senden; dann koennte man srcloc ausnutzen
00777 !
00778          extra_msg (11) = 0
00779 !
00780          extra_msg (15) = n_recv_req
00781          extra_msg (16) = nb_extra
00782 
00783          extra_msg (17) = comp_info%all_extent_infos(1,igrid)
00784 !
00785 #ifdef DEBUGX
00786       print *, 'extra_msg (1:4)', extra_msg (1:4)
00787          do i = 1, n_send
00788             print *, ibuf ((i-1)*len_item+1:i*len_item)
00789          end do
00790 #endif
00791 !
00792          call psmile_bsend (extra_msg, nd_msgextra, MPI_INTEGER, &
00793                             dest, exttag, comm_psmile, ierror)
00794          if (ierror /= MPI_SUCCESS) then
00795             ierrp (1) = ierror
00796             ierrp (2) = dest
00797             ierrp (3) = exttag
00798 
00799             ierror = PRISM_Error_Send
00800 
00801             call psmile_error (ierror, 'psmile_bsend(msg)', &
00802                                ierrp, 3, __FILE__, __LINE__ )
00803             return
00804          endif
00805 !
00806          call psmile_bsend (ibuf, len_ibuf, MPI_INTEGER, &
00807                             dest, exttag, comm_psmile, ierror)
00808          if (ierror /= MPI_SUCCESS) then
00809             ierrp (1) = ierror
00810             ierrp (2) = dest
00811             ierrp (3) = exttag
00812 
00813             ierror = PRISM_Error_Send
00814 
00815             call psmile_error (ierror, 'psmile_bsend(ibuf)', &
00816                                ierrp, 3, __FILE__, __LINE__ )
00817             return
00818          endif
00819 !
00820          call psmile_bsend (buf, len_rbuf, MPI_DOUBLE_PRECISION, &
00821                             dest, exttag, comm_psmile, ierror)
00822          if (ierror /= MPI_SUCCESS) then
00823             ierrp (1) = ierror
00824             ierrp (2) = dest
00825             ierrp (3) = exttag
00826 
00827             ierror = PRISM_Error_Send
00828 
00829             call psmile_error (ierror, 'psmile_bsend(buf)', &
00830                                ierrp, 3, __FILE__, __LINE__ )
00831             return
00832          endif
00833 !
00834 !===> ... Setup request for answer of destination process
00835 !         ??? wirklich; sollte wohl von dem normalen abgehandelt werden
00836 !
00837          if (n_recv_req == 1) then
00838             call MPI_Irecv (answer, nd_msgextra, MPI_INTEGER, MPI_ANY_SOURCE, &
00839                             rexttag, comm_psmile, recv_req, ierror)
00840             if (ierror /= MPI_SUCCESS) then
00841 
00842                ierrp (1) = ierror
00843                ierrp (2) = dest
00844                ierrp (3) = rexttag
00845 
00846                ierror = PRISM_Error_Recv
00847 
00848                call psmile_error ( ierror, 'MPI_Irecv', &
00849                                    ierrp, 3, __FILE__, __LINE__ )
00850                return
00851 
00852             endif
00853          endif
00854 !
00855       end do ! igrid
00856 !
00857 !===> Deallocate
00858 !
00859       Deallocate (send_mask, boxes, igrid_to_dest_comp)
00860 !
00861       if (ndrbuf > 0) Deallocate (buf)
00862       if (ndibuf > 0) Deallocate (ibuf)
00863 !
00864 #ifdef __BUG__
00865       if (n_recv_req == 0) then
00866 
00867 !rr      send_info%nrecv and send_info%num2recv already may contain the results
00868 !rr      from the global search for filling the interpolation stencil. Here we
00869 !rr      perform the extra search for points for which no unmasked source points
00870 !rr      have been found. It must not be set to zero here as it is later used
00871 !rr      in psmile_compact_neighbours to compact points from the global search.
00872 !rr      send_info%nrecv and send_info%num2recv get updated in psmile_select_nn_found
00873 !rr      which is called from this routine.
00874 
00875          send_info%nrecv    = 0
00876          send_info%num2recv = 0
00877 
00878          go to 1000
00879       endif
00880 #endif
00881 
00882       if (n_recv_req == 0) go to 1000
00883 
00884 !
00885 !-------------------------------------------------------------------------
00886 !     Wait for answers
00887 !      Note: (2) Message from a partner with an intersection is disabled
00888 !                since request for grid receive (lrequest (3)) is setup
00889 !                if such a message is found.
00890 !            ??? Koennte man enablen wenn lrequest(3) == MPI_REQUEST_NULL
00891 !            (3) Old receive of grid data (paction%lrequest (3)) is disabled
00892 !-------------------------------------------------------------------------
00893 !
00894 ! nrecv      = Number of significant messages received
00895 !
00896       nrecv = 0
00897 !
00898       Allocate (sel_info (n_recv_req), stat = ierror)
00899       if ( ierror > 0 ) then
00900          ierrp (1) = ierror
00901          ierrp (2) = n_recv_req
00902 
00903          ierror = PRISM_Error_Alloc
00904          call psmile_error ( ierror, 'sel_info', ierrp, 2, &
00905                              __FILE__, __LINE__ )
00906          return
00907       endif
00908 !
00909 !===> Save old values of requests (2:3),
00910 !     ignore index 2 () and
00911 !     set index 3 to first receive of returned meta data
00912 !
00913       save_lreq (2:3) = paction%lrequest (2:3)
00914       paction%lrequest (2) = MPI_REQUEST_NULL
00915 !
00916       do n = 1, n_recv_req
00917          paction%lrequest (3) = recv_req
00918 !
00919          index = 0
00920          do while (index /= 3) 
00921 #ifdef DEBUG
00922             print *, trim(ch_id), paction%nreq, recv_req
00923             call psmile_flushstd
00924 #endif
00925 !
00926             call MPI_Waitany (paction%nreq, paction%lrequest, index, status, ierror)
00927 
00928             if ( ierror /= MPI_SUCCESS ) then
00929                ierrp (1) = ierror
00930                ierrp (2) = status (MPI_SOURCE)
00931                ierrp (3) = status (MPI_TAG)
00932 
00933                ierror = PRISM_Error_MPI
00934 
00935                call psmile_error ( ierror, 'MPI_Waitany', &
00936                                  ierrp, 3, __FILE__, __LINE__ )
00937                return
00938             endif
00939 
00940 #ifdef PRISM_ASSERTION
00941             if (index == MPI_UNDEFINED) then
00942                call psmile_assert ( __FILE__, __LINE__, &
00943                                     'request list is empty')
00944             endif
00945 #endif
00946 !
00947             if (index /= 3) then
00948                call psmile_enddef_action (search, index, status, ierror)
00949                if (ierror > 0) return
00950             endif
00951          end do ! while
00952 !
00953 !===> ... Get 
00954 !
00955          sender = status (MPI_SOURCE)
00956          len_ibuf = answer (3)
00957          len_rbuf = answer (4)
00958 !
00959 #ifdef VERBOSE
00960          print 9960, trim(ch_id), sender, len_ibuf, len_rbuf
00961 
00962          call psmile_flushstd
00963 #endif /* VERBOSE */
00964 !
00965 #ifdef PRISM_ASSERTION
00966          if (len_ibuf < 0) then
00967             print *, 'len_ibuf =', len_ibuf
00968             call psmile_assert (__FILE__, __LINE__, &
00969                  "len_ibuf should be >= 0")
00970          endif
00971 !
00972          if (len_rbuf < 0) then
00973             print *, 'len_rbuf =', len_rbuf
00974             call psmile_assert (__FILE__, __LINE__, &
00975                  "len_rbuf should be >= 0")
00976          endif
00977 #endif
00978 !
00979          if (len_ibuf > 0) then
00980             Allocate (ibuf (1:len_ibuf), stat = ierror)
00981 
00982             if ( ierror > 0 ) then
00983                ierrp (1) = ierror
00984                ierrp (2) = len_ibuf
00985 
00986                ierror = PRISM_Error_Alloc
00987                call psmile_error ( ierror, 'ibuf', ierrp, 2, &
00988                                    __FILE__, __LINE__ )
00989                return
00990             endif
00991 !
00992             call MPI_Recv (ibuf, len_ibuf, MPI_INTEGER, sender, &
00993                            rexttag, comm_psmile, status, ierror)
00994             if (ierror /= MPI_SUCCESS) then
00995 
00996                ierrp (1) = ierror
00997                ierrp (2) = sender
00998                ierrp (3) = rexttag
00999 
01000                ierror = PRISM_Error_Recv
01001 
01002                call psmile_error ( ierror, 'MPI_Recv(ibuf)', ierrp, 3, &
01003                                    __FILE__, __LINE__ )
01004                return
01005             endif
01006 !
01007             Allocate (buf (1:len_rbuf), stat = ierror)
01008 
01009             if ( ierror > 0 ) then
01010                ierrp (1) = ierror
01011                ierrp (2) = len_rbuf
01012 
01013                ierror = PRISM_Error_Alloc
01014                call psmile_error ( ierror, 'buf', ierrp, 2, &
01015                                    __FILE__, __LINE__ )
01016                return
01017             endif
01018 !
01019             call MPI_Recv (buf, len_rbuf, MPI_DOUBLE_PRECISION, sender, &
01020                            rexttag, comm_psmile, status, ierror)
01021             if (ierror /= MPI_SUCCESS) then
01022 
01023                ierrp (1) = ierror
01024                ierrp (2) = sender
01025                ierrp (3) = rexttag
01026 
01027                ierror = PRISM_Error_Recv
01028 
01029                call psmile_error ( ierror, 'MPI_Recv(rbuf)', ierrp, 3, &
01030                                    __FILE__, __LINE__ )
01031                return
01032             endif
01033 !
01034 !===> ...
01035 !
01036 ! n_send  = Number of cells to be searched
01037 ! n_found = Number of interpolation bases found
01038 ! n_liste = Number of data items to be used for interpolation
01039 !           n_liste <= n_found since a data item can be used
01040 !           multiply for interpolation.
01041 !
01042             n_send  = answer (7)
01043             n_liste = answer (8)
01044             n_found = answer (9)
01045             ireq    = answer (15)
01046 !
01047 #ifdef PRISM_ASSERTION
01048             if (answer (1) /= PSMILe_nnghbr3D) then
01049                print *, 'answer(1)', answer(1), PSMILe_nnghbr3D
01050                call psmile_assert (__FILE__, __LINE__, &
01051                     "expected nearest neighbour interpolation")
01052             endif
01053 !
01054             if (ireq < 1 .or. ireq > n_recv_req) then
01055                print *, 'ireq, n_recv_req', ireq, n_recv_req
01056                call psmile_assert (__FILE__, __LINE__, &
01057                     "ireq must be in range of 1:n_recv_req")
01058             endif
01059 #endif
01060 !
01061             nrecv = nrecv + 1
01062 !
01063             sel_info(nrecv)%sender    = sender
01064             sel_info(nrecv)%n_liste   = n_liste
01065             sel_info(nrecv)%index     = answer (10)
01066             sel_info(nrecv)%method_id = answer (11)
01067             sel_info(nrecv)%msg_id    = answer (16)
01068 
01069             sel_info(nrecv)%dble_buf => buf
01070 !
01071 !===> ... Allocate and initialize array "selected"
01072 !
01073 ! selected = Temporary vector for global nearest neighbour search
01074 !            for extra points with
01075 !            selected (1, *) = Number (index) of the receive
01076 !                              from which the nearest neigbour was
01077 !                              selected.
01078 !            selected (2, *) = Index in list of points 
01079 !                              (sent by neighbouring process)
01080 !            (cf. routine PSMILe_Add_nn_found_dble)
01081 !            Dimension : selected (2, n_extra)
01082 !
01083 !
01084             if (.not. Allocated (selected)) then
01085                Allocate (selected(2, n_extra), stat = ierror)
01086 !
01087                if (ierror /= 0) then
01088                   ierrp (1) = n_extra * 2
01089 
01090                   ierror = PRISM_Error_Alloc
01091 
01092                   call psmile_error ( ierror, 'selected', ierrp, 1, &
01093                               __FILE__, __LINE__ )
01094                   return
01095                endif
01096 !
01097                selected (1, :) = 0
01098             endif
01099 !
01100 !===> ... Add information on points found by global search 
01101 !
01102             ip_dist = n_liste * ndim_3d
01103 !
01104             call psmile_add_nn_found_dble (search, extra_search,     &
01105                         ibuf (1:n_send),                             &
01106                         ibuf   (n_send+1:2*n_send), n_send,          &
01107                         ibuf (2*n_send+1:2*n_send+n_found),          &
01108                         buf (ip_dist+1:ip_dist+n_found), n_found,    &
01109                         nb_extra, selected, sel_info, nrecv, ierror)
01110             if (ierror > 0) return
01111 !
01112             Deallocate (ibuf)
01113          endif
01114 !
01115 !===> ... Setup new request
01116 !
01117          if (n < n_recv_req) then
01118             call MPI_Irecv (answer, nd_msgextra, MPI_INTEGER, MPI_ANY_SOURCE, &
01119                               rexttag, comm_psmile, recv_req, &
01120                               ierror)
01121             if (ierror /= MPI_SUCCESS) then
01122 
01123                ierrp (1) = ierror
01124                ierrp (2) = dest
01125                ierrp (3) = rexttag
01126 
01127                ierror = PRISM_Error_Recv
01128 
01129                call psmile_error ( ierror, 'MPI_Irecv', &
01130                                     ierrp, 3, __FILE__, __LINE__ )
01131                return
01132             endif
01133          endif
01134       end do
01135 !
01136 !===> Determine which points are selected and return info to
01137 !     neighbouring processes
01138 !
01139       if (nrecv > 0) then
01140          call psmile_select_nn_found (search, extra_search,  &
01141                      send_info,                              &
01142                      selected, sel_info, nrecv, nb_extra,    &
01143                      neighbors_3d, nloc, num_neigh,          &
01144                      Grids(grid_id)%grid_shape, ierror)
01145          if (ierror > 0) return
01146       endif
01147 !
01148 !    ... Free memory
01149 !
01150       if (Allocated (selected)) then
01151          Deallocate (selected)
01152       endif
01153 !
01154       Deallocate (sel_info)
01155 !
01156 !    ... Restore original requests (2:3)
01157 !
01158 #ifdef PRISM_ASSERTION
01159       if (paction%lrequest (2) /= MPI_REQUEST_NULL .or. &
01160           paction%lrequest (3) /= MPI_REQUEST_NULL) then
01161          print *, 'request: ', paction%lrequest (2:3)
01162          call psmile_assert ( __FILE__, __LINE__, &
01163                              'Illegal request stored')
01164 
01165       endif
01166 #endif
01167 !
01168       paction%lrequest (2:3) = save_lreq (2:3)
01169 !
01170 !-------------------------------------------------------------------------
01171 !===> All done
01172 !-------------------------------------------------------------------------
01173 !
01174 1000  continue
01175 #ifdef VERBOSE
01176       print 9980, trim(ch_id), ierror
01177 
01178       call psmile_flushstd
01179 #endif /* VERBOSE */
01180 !
01181 !  Formats:
01182 !
01183 
01184 #ifdef VERBOSE
01185 
01186 9990 format (1x, a, ': psmile_global_search_nnx_dble: var_id', i3, &
01187                     ' to ', i3, '(', i2, ')')
01188 9980 format (1x, a, ': psmile_global_search_nnx_dble: eof ierror =', i3)
01189 9970 format (1x, a, ': psmile_global_search_nnx_dble: send from', i3, &
01190                     ' to', i3, '[', i3, '], n_send =', i6)
01191 
01192 9960 format (1x, a, ': psmile_global_search_nnx_dble: got rexttag message:', &
01193                     ' sender ', i4, ', len_ibuf, len_rbuf', 2i8)
01194 9950 format (1x, a, ': psmile_global_search_nnx_dble: before waitany :', &
01195                     'nreq =', i4, ', recv_req ', i8)
01196 #endif /* VERBOSE */
01197 
01198 #ifdef DEBUG
01199 #endif
01200 
01201       end subroutine PSMILe_global_search_nnx_dble

Generated on 18 Mar 2011 for Oasis4 by  doxygen 1.6.1