psmile_trili_gauss2_extra.F90

Go to the documentation of this file.
00001 !-----------------------------------------------------------------------
00002 ! Copyright 2006-2010, NEC Europe Ltd., London, UK.
00003 ! Copyright 2011, DKRZ, Hamburg, Germany.
00004 ! All rights reserved. Use is subject to OASIS4 license terms.
00005 !-----------------------------------------------------------------------
00006 !BOP
00007 !
00008 ! !ROUTINE: psmile_trili_gauss2_extra
00009 !
00010 ! !INTERFACE:
00011 
00012       subroutine psmile_trili_gauss2_extra (search, grid_id, mask_array, &
00013                         mask_shape, mask_available, ibuf, len_item,      &
00014                         n_send, num_neigh, ierror)
00015 !
00016 ! !USES:
00017 !
00018       use PRISM
00019       use PSMILe, dummy_interface => psmile_trili_gauss2_extra
00020       use psmile_grid_reduced_gauss
00021 
00022       Implicit none
00023 !
00024 ! !INPUT PARAMETERS:
00025 !
00026       Integer,                      Intent (In)    :: grid_id
00027 
00028       Integer,                      Intent (In)    :: mask_shape (2, ndim_3d)
00029 
00030 !     Dimension of (method) mask array
00031 
00032       Logical,                      Intent (In)    ::     
00033           mask_array ( mask_shape (1,1):mask_shape (2,1), 
00034                        mask_shape (1,2):mask_shape (2,2), 
00035                        mask_shape (1,3):mask_shape (2,3) )
00036 !     Mask of the method
00037 
00038       Logical,                     Intent (In)     :: mask_available
00039 
00040 !     Is mask specified in array "mask_array" ?
00041 !     mask_available = .false. : Mask is not available
00042 !                      .true.  : Mask is     available
00043 !
00044       Integer,                     Intent (In)     :: len_item
00045 !
00046 !     Number of pieces of information in integer buffer "ibuf".
00047 !        1:3: (i,j,k) index of lower left corner
00048 !        4  : Index in
00049 !        5  : Code for points required
00050 !
00051       Integer,                     Intent (In)    :: n_send
00052 !
00053 !     Number of extra points sent
00054 
00055       Integer,                     Intent (In)    :: num_neigh
00056 !
00057 !     (Maximal) Number of interpolations bases required..
00058 !
00059 ! !INPUT/OUTPUT PARAMETERS:
00060 !
00061       Type (Enddef_global_search), Intent (InOut) :: search
00062 
00063 !     Data on the points to be searched
00064 
00065       Integer,                     Intent (InOut) :: ibuf (len_item, n_send)
00066 !
00067 !     Integer buffer containing the packed integer data.
00068 !     On return, ibuf (5, *) contains the code of the points found.
00069 !
00070 ! !OUTPUT PARAMETERS:
00071 !
00072       Integer,                     Intent (Out)   :: ierror
00073 
00074 !     Returns the error code of PSMILe_Search_donor_extra;
00075 !             ierror = 0 : No error
00076 !             ierror > 0 : Severe error
00077 !
00078 ! !LOCAL PARAMETERS:
00079 !
00080 ! n_corners_3d = Number of interpolation bases in 3d case
00081 !
00082 ! masked_out   = Hash value for a point which is masked out
00083 !
00084       Integer, Parameter           :: n_corners_3d = 2 * 2 * 2
00085 !
00086       Integer, Parameter           :: masked_out = 0
00087 !
00088 ! !LOCAL VARIABLES
00089 !
00090 !     ... loop variables
00091 !
00092       Integer                      :: j, n, i, k
00093 !
00094 !     ... For Grids
00095 !
00096       Type (Grid), Pointer         :: grid_info
00097       Integer,     Pointer         :: grid_valid_shape (:, :)
00098 !
00099 !     ... For Gaussreduced Grids
00100 !
00101       Logical                      :: virtual_cell_available
00102 !
00103 !     ... For searched points of control volume
00104 !
00105       Integer                      :: code, n_corners, outside
00106 !
00107       Integer, Allocatable         :: locs (:, :)
00108       Integer, Allocatable         :: neighbours_3d_extra (:, :, :)
00109       Integer, Allocatable         :: hash (:)
00110 !
00111 !
00112 !
00113       Logical                      :: missing_points(num_neigh, n_send)
00114       Integer                      :: decode_mask(num_neigh)
00115       Integer                      :: num_missing_points
00116 
00117       integer, parameter           :: shift_3d(ndim_3d, 9) = 
00118                                           reshape ((/-1,-1,0, 0,-1,0, +1,-1,0,
00119                                                      -1, 0,0, 0, 0,0, +1, 0,0,
00120                                                      -1,+1,0, 0,+1,0, +1,+1,0/), 
00121                                                    (/ndim_3d,9/))
00122 !
00123 !     ... for error parameters
00124 !
00125       Integer, parameter           :: nerrp = 1
00126       Integer                      :: ierrp (nerrp)
00127 !
00128 #ifdef DEBUG_TRACE
00129       Integer                      :: ictl_req, ind_loc (n_corners_3d)
00130 #endif
00131 !
00132 ! !DESCRIPTION:
00133 !
00134 ! Subroutine "psmile_trili_gauss2_extra" performs the
00135 ! additional (global) search for grids of type "PRISM_Gaussreduced_regvrt".
00136 !
00137 ! !REVISION HISTORY:
00138 !
00139 !   Date      Programmer   Description
00140 ! ----------  ----------   -----------
00141 ! 03.07.05    H. Ritzdorf  created as psmile_trili_gauss2_extra_dble
00142 ! 17.02.11    M. Hanke     simplified code and corrected shifting, removed difference
00143 !                          between dble and real implementation
00144 !
00145 !EOP
00146 !----------------------------------------------------------------------
00147 !
00148 ! $Id: psmile_trili_gauss2_extra.F90 3023 2011-03-17 10:21:20Z hanke $
00149 ! $Author: hanke $
00150 !
00151    Character(len=len_cvs_string), save :: mycvs = 
00152        '$Id: psmile_trili_gauss2_extra.F90 3023 2011-03-17 10:21:20Z hanke $'
00153 !
00154 !----------------------------------------------------------------------
00155 !
00156 !  Initialization
00157 !
00158 #ifdef VERBOSE
00159       print 9990, trim(ch_id), grids(grid_id)%comp_id
00160 
00161       call psmile_flushstd
00162 #endif /* VERBOSE */
00163 !
00164       ierror = 0
00165       n_corners = num_neigh
00166 !
00167 !===> Get grid info
00168 !
00169 !  grid_valid_shape (2, ndim_3d) : Specifies the valid block shape
00170 !                                  for the "ndim_3d"-dimensional block
00171 !                                  (without halo/overlap regions)
00172 !
00173       grid_info => Grids(grid_id)
00174 !
00175       grid_valid_shape => grid_info%grid_shape
00176 !
00177       virtual_cell_available = len_item > ndim_3d + 2 ! unschoen
00178 !
00179       if (grid_info%grid_type /= PRISM_Gaussreduced_Regvrt) then
00180          print *, "grid_type", grid_info%grid_type
00181          call psmile_assert (__FILE__, __LINE__, &
00182                    "This routine is not designed for this grid type")
00183       endif
00184 !
00185       outside = grid_valid_shape (1, 1) - 11
00186 !
00187 #ifdef PRISM_ASSERTION
00188 
00189       if (num_neigh < 1 .or. num_neigh > n_corners_3d) then
00190          print *, 'num_neigh', num_neigh, n_corners_3d
00191          call psmile_assert ( __FILE__, __LINE__, &
00192                 'Invalid value for num_neigh (number of interpolation bases')
00193       endif
00194 !
00195 !===> Control input values contained in "ibuf"
00196 !
00197 !cdir vector
00198       do n = 1, n_send
00199          if (ibuf (2, n) < 1 .or. ibuf (2, n) > grid_info%nbr_latitudes) exit
00200       end do
00201 !
00202       if (n <= n_send) then
00203          print *, "i,j,k, gnbr_lats", ibuf(1:3,n), grid_info%nbr_latitudes
00204          call psmile_assert (__FILE__, __LINE__, &
00205                    "second (virtual) index out of range")
00206       endif
00207 !
00208 !cdir vector
00209       do n = 1, n_send
00210          if (ibuf (1, n) < 1 .or. &
00211              ibuf (1, n) > grid_info%nbr_points_per_lat(ibuf(2,n))) exit
00212       end do
00213 !
00214       if (n <= n_send) then
00215          print *, "i,j,k, points_per_lat", &
00216                   ibuf(1:3,n), grid_info%nbr_points_per_lat(ibuf(2,n))
00217          call psmile_assert (__FILE__, __LINE__, &
00218                    "first (virtual) index out of range")
00219       endif
00220 #endif
00221 
00222 #ifdef DEBUG_TRACE
00223 !cdir vector
00224       do ictl_req = 1, n_send
00225          if (ibuf (4, ictl_req) == 1) exit
00226       end do
00227 #endif
00228 
00229       ! 1st we rebuilt the neighbours_3d (global 3d representation) array
00230       ! for the source locations received
00231 
00232       allocate (neighbours_3d_extra (ndim_3d, n_send, 4), stat=ierror)
00233       if (ierror /= 0) then
00234          call psmile_error ( PRISM_Error_Alloc, 'locs', (/ndim_3d * n_send * 4/), 1, &
00235                  __FILE__, __LINE__ )
00236          return
00237       endif
00238 
00239       if (virtual_cell_available) then
00240          ! for all locations
00241          do n = 1, n_send
00242 
00243             if (ibuf(6, n) == 0) then
00244 
00245                neighbours_3d_extra(:,n,1:4) = &
00246                   psmile_gauss_get_bili_stencil (grid_id, ibuf(1:3,n))
00247 
00248             else
00249 
00250                neighbours_3d_extra(:,n,1:4) = &
00251                   psmile_gauss_shift_bili_stencil (grid_id, ibuf(1:3,n), shift_3d(:,ibuf(6, n)))
00252 
00253             endif
00254          enddo ! n
00255       else
00256          neighbours_3d_extra(:,n,1:4) = psmile_gauss_get_bili_stencil (grid_id, ibuf(1:3,n))
00257       endif
00258 !
00259 !  decode which points are missing
00260 !
00261       do i = 1, num_neigh
00262          decode_mask(i) = ishft (1, i - 1)
00263       enddo
00264 
00265       do n = 1, n_send
00266          missing_points(:, n) = iand (decode_mask(:), ibuf(5, n)) /= 0
00267       enddo
00268 !
00269 !  how many points are missing?
00270 !
00271       num_missing_points = count (missing_points)
00272 #ifdef PRISM_ASSERTION
00273       if (num_missing_points <= 0) then
00274          call psmile_assert ( __FILE__, __LINE__, &
00275                              'Number of points to be searched == 0 ?!?')
00276       endif
00277 #endif
00278 
00279 #ifdef DEBUGX
00280       print *, 'code for locations to be searched (n_send =', num_missing_points, ')'
00281       do n = 1, n_send
00282          print *, n, 'srcloc =', ibuf(1:3,n), 'code =', ibuf (5, n)
00283          print *, '   decoded     =', missing_points(:,n)
00284       end do
00285 #endif
00286 !
00287 #ifdef DEBUG_TRACE
00288       if (ictl_req <= n_send) then
00289          print *, 'code for indices_req', ibuf (4, ictl_req)
00290          print *, 'ictl_req', ictl_req, 'srcloc', ibuf(1:3,ictl_req), &
00291                   'code', ibuf (5, ictl_req), missing_points(:, ictl_req)
00292       endif
00293 #endif
00294 !
00295 !  Allocate memory for the indices of the missing points
00296 !
00297       Allocate (locs (ndim_3d, num_missing_points), stat = ierror)
00298       if (ierror /= 0) then
00299          call psmile_error ( PRISM_Error_Alloc, 'locs', (/ndim_3d * num_missing_points/), 1, &
00300                  __FILE__, __LINE__ )
00301          return
00302       endif
00303 
00304       k = 0
00305 
00306       do i = 1, n_corners
00307 !cdir vector
00308          do n = 1, n_send
00309             if (missing_points (i,n)) then
00310 
00311                k = k + 1
00312 
00313                locs (:, k) = neighbours_3d_extra(:, n, iand (i-1, 3)+1)
00314 
00315                if (grid_valid_shape(2,3) - grid_valid_shape(1,3) >= ishft(n_corners, -2) - 1 .and. &
00316                    n_corners > 4) then
00317                   locs (3, k) = locs (3, k) + ishft (i-1, -2)
00318                endif
00319             end if
00320          end do ! n
00321       end do ! i
00322 !
00323 #ifdef PRISM_ASSERTION
00324       if (k /= num_missing_points) then
00325          print *, 'k, num_missing_points', k, num_missing_points
00326          call psmile_assert ( __FILE__, __LINE__, &
00327                 'Inconsistent values of k and num_missing_points; must be same value')
00328       endif
00329 #endif
00330 
00331 #ifdef DEBUG_TRACE
00332       if (ictl_req <= n_send) then
00333          ind_loc (:) = 0
00334          n = 0
00335          do j = 1, n_corners
00336 !cdir vector
00337             do i = 1, n_send
00338                if (missing_points (j,i)) then
00339                   n = n + 1
00340                   if (i == ictl_req) ind_loc (j) = n
00341                end if
00342             end do ! i
00343          end do ! j
00344 !
00345          print *, 'locs searched for indices_req', ibuf (4, ictl_req)
00346          do j = 1, n_corners
00347             n = ind_loc (j)
00348             if (n > 0) &
00349             print *, 'ictl_req', ictl_req, ', n ', n, &
00350                            ': locs', locs (1:ndim_3d, n)
00351          end do
00352       endif
00353 #endif
00354 
00355 !
00356 !===> Transform indices from global (virtual) 3d indices
00357 !                       into local  (virtual) 3d indices
00358 !
00359       locs(1,:) = psmile_gauss_3d_to_local_1d (grid_id, locs(:,:), &
00360                                                num_missing_points, outside)
00361       locs(2,:) = 1
00362       !locs(3,:) = locs(3,:)
00363 !
00364 !===> Create compact list of points to be sent and
00365 !     return hash value "hash" (index in fortran order) for each location
00366 !
00367       Allocate (hash (num_missing_points), stat = ierror)
00368       if (ierror /= 0) then
00369          ierrp (1) = num_missing_points
00370 
00371          ierror = PRISM_Error_Alloc
00372 
00373          call psmile_error ( ierror, 'hash', ierrp, 1, &
00374                  __FILE__, __LINE__ )
00375          return
00376       endif
00377 !
00378       call psmile_hash_extra (search, locs, hash, num_missing_points,                &
00379               mask_array, mask_shape, mask_available, grid_valid_shape, &
00380               ierror)
00381       if (ierror > 0) return
00382 !
00383 #ifdef DEBUGX
00384       print *, 'hash values and locs ', grid_valid_shape
00385       n = 0
00386       do j = 1, n_corners
00387 !cdir vector
00388          do i = 1, n_send
00389             if (missing_points (j,i)) then
00390                n = n + 1
00391                print *, 'i, j, n, hash(n), locs(:,n) ', &
00392                          i, j, n, hash(n), locs(:,n)
00393             end if
00394          end do ! i
00395       end do ! j
00396 #endif
00397 !
00398 !===> Save coded mask of points found in "ibuf"
00399 !     ??? Ob das so clever ist ?
00400 !
00401       if (search%n_liste > 0) then
00402          ibuf (5, 1:n_send) = 0
00403 !
00404          n = 0
00405          code = 1
00406          do j = 1, n_corners
00407 !cdir vector
00408             do i = 1, n_send
00409                if (missing_points (j,i)) then
00410 
00411                   n = n + 1
00412 !
00413                   if (hash (n) >= 0) then
00414 !
00415 !===> ...... Required "j-th" interpolation base was found
00416 !            (may be masked out (hash(n) == masked_out).
00417 !            Corresponding value is stored in position "index_found(n)".
00418 !
00419                      ibuf (5, i) = ibuf (5, i) + code
00420                   endif
00421 !
00422                endif
00423             end do ! i
00424 
00425             code = code * 2
00426          end do ! j
00427 
00428 #ifdef PRISM_ASSERTION
00429          if (n /= num_missing_points) then
00430             print *, 'num_missing_points, n', num_missing_points, n
00431             call psmile_assert ( __FILE__, __LINE__, &
00432                                 'n /= num_missing_points')
00433          endif
00434 #endif
00435 !
00436 #ifdef DEBUGX
00437          print *, 'code for locations found', n_send
00438          do i = 1, n_send
00439             print *, 'code', i, ibuf (5, i), missing_points(:, i)
00440          end do
00441 #endif
00442 !
00443 #ifdef DEBUG_TRACE
00444          if (ictl_req <= n_send) then
00445             print *, 'code for locations found for indices_req', ibuf (4, ictl_req)
00446             print *, 'ictl_req', ictl_req, ': code', ibuf (5, ictl_req), missing_points(:, ictl_req)
00447          endif
00448 #endif
00449 
00450       endif
00451 !
00452 !===> Deallocate memory allocated
00453 !
00454       Deallocate (locs, hash, neighbours_3d_extra)
00455 !
00456 !===> All done
00457 !
00458 #ifdef VERBOSE
00459       print 9980, trim(ch_id), ierror, search%n_found, n_send
00460 
00461       call psmile_flushstd
00462 #endif /* VERBOSE */
00463 !
00464       return
00465 !
00466 !  Formats:
00467 !
00468 #ifdef VERBOSE
00469 9990 format (1x, a, ': psmile_trili_gauss2_extra: comp_id =', i3)
00470 9980 format (1x, a, ': psmile_trili_gauss2_extra: eof', &
00471                     ', ierror =', i4, ', n_found =', i8, i8)
00472 #endif /* VERBOSE */
00473 
00474       end subroutine psmile_trili_gauss2_extra

Generated on 18 Mar 2011 for Oasis4 by  doxygen 1.6.1