psmile_neigh_global_points.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_Neigh_global_points
00008 !
00009 ! !INTERFACE:
00010 
00011       subroutine psmile_neigh_global_points (search, extra_search,     &
00012                       mask_array, mask_shape, mask_available, use_how, &
00013                       grid_id, grid_valid_shape,                       &
00014                       neighbors_3d, nloc, n_corners, len_cpl, ierror)
00015 !
00016 ! !USES:
00017 !
00018       use PRISM_constants
00019 !
00020       use PSMILe, dummy_interface => PSMILe_Neigh_global_points
00021 #ifdef DEBUG_TRACE
00022       use psmile_debug_trace
00023 #endif
00024 
00025       Implicit none
00026 !
00027 ! !INPUT PARAMETERS:
00028 !
00029       Type (Enddef_search), Intent (In) :: search
00030 
00031 !     Info's on coordinates to be searched
00032 !
00033       Integer,         Intent (In)    :: mask_shape (2, ndim_3d)
00034 
00035 !     Dimension of (method) mask array
00036 
00037       Logical,         Intent (In)    :: mask_array (mask_shape (1,1): 
00038                                                      mask_shape (2,1), 
00039                                                      mask_shape (1,2): 
00040                                                      mask_shape (2,2), 
00041                                                      mask_shape (1,3): 
00042                                                      mask_shape (2,3))
00043 !     Mask of the method
00044 
00045       Logical,         Intent (In)    :: mask_available
00046 
00047 !     Is mask specified in array "mask_array" ?
00048 !     mask_available = .false. : Mask is not available
00049 !                      .true.  : Mask is     available
00050 
00051       Integer,         Intent (In)    :: use_how
00052 
00053 !     Information about how to apply the mask
00054 !        PSMILE_novalue   : If one neighbor is unvalid reject all.
00055 !        PSMILE_tneighbour: Reject all unvalid neighbors but keep the valid.
00056 !        PSMILE_nneighbour: == PSMILE_undef
00057 !
00058       Integer,         Intent (In)    :: grid_id
00059 !
00060 !     Grid identifier of the source grid
00061 !     (on which the target points are searched)
00062 !
00063       Integer,         Intent (In)    :: grid_valid_shape (2, ndim_3d)
00064 
00065 !     Specifies the valid block shape for the "ndim_3d"-dimensional block
00066 !
00067       Integer,         Intent (In)    :: nloc
00068 !
00069 !     Total number of locations to be transferred.
00070 !     Number of locations for which extra points should be searched.
00071 !     Second dimension of neighbors array "neighbors_3d"
00072 !
00073       Integer,         Intent (In)    :: n_corners
00074 !
00075 !     Last dimension of neighbors array "neighbors_3d" and
00076 !     number of interpolation bases.
00077 !
00078       Integer, Intent (In)            :: len_cpl (search%search_data%npart)
00079 
00080 !     Number of points to be sent to the coupler for each partition.
00081 !
00082 ! !INPUT/OUTPUT PARAMETERS:
00083 !
00084       Type (Extra_search_info), Intent (InOut) :: extra_search
00085 !
00086 !     Number of locations where
00087 !       (*) required mask values were not true
00088 !
00089       Integer,         Intent (InOut) :: neighbors_3d (ndim_3d, nloc, n_corners)
00090 
00091 !     Indices of neighbor locations (interpolation bases)
00092 !
00093 ! !OUTPUT PARAMETERS:
00094 
00095       Integer,         Intent (Out)   :: ierror
00096 
00097 !     Returns the error code of PSMILE_Neigh_global_points;
00098 !             ierror = 0 : No error
00099 !             ierror > 0 : Severe error
00100 !
00101 ! !LOCAL VARIABLES
00102 !
00103 !     ... for grids
00104 !
00105       Integer                         :: grid_type
00106 !
00107 !     ... for locations searched
00108 !
00109       Integer                         :: i, j, n, nbeg, nend, nprev
00110 !
00111 !     ... for locations controlled
00112 !
00113       Integer                         :: code, nreq
00114       Integer                         :: outside
00115 
00116 !
00117       Integer, Pointer                :: required (:)
00118       Integer, Pointer                :: indices_req (:)
00119       Integer, Allocatable            :: mask_cell (:)
00120       Integer, Allocatable            :: search_required (:)
00121 !
00122 !     ... for partitions
00123 !
00124       Integer                         :: ipart
00125 
00126 !     ... for error handling
00127 !
00128       Integer, parameter              :: nerrp = 2
00129       Integer                         :: ierrp (nerrp)
00130 !
00131 ! !DESCRIPTION:
00132 !
00133 ! Subroutine "PSMILe_Neigh_global_points" determines the points (indices)
00134 ! which require global search.
00135 ! The extra points are searched the neighbour indices (interpolation
00136 ! bases) specified in
00137 !
00138 !      neighbour (1:ndim_3d, 1:nloc, n_corners).
00139 !
00140 ! !REVISION HISTORY:
00141 !
00142 !   Date      Programmer   Description
00143 ! ----------  ----------   -----------
00144 ! 15.03.06    H. Ritzdorf  created
00145 !
00146 !EOP
00147 !----------------------------------------------------------------------
00148 !
00149 !  $Id: psmile_neigh_global_points.F90 3174 2011-05-04 09:41:43Z hanke $
00150 !  $Author: hanke $
00151 !
00152    Character(len=len_cvs_string), save :: mycvs = 
00153        '$Id: psmile_neigh_global_points.F90 3174 2011-05-04 09:41:43Z hanke $'
00154 !
00155 !----------------------------------------------------------------------
00156 !
00157 !  Initialization
00158 !
00159 #ifdef VERBOSE
00160       print 9990, trim(ch_id)
00161 
00162       call psmile_flushstd
00163 #endif /* VERBOSE */
00164 !
00165 !===> Initialization
00166 !
00167       ierror  = 0
00168 !
00169 #ifdef PRISM_ASSERTION
00170 !
00171       if (nloc /= Sum(len_cpl)) then
00172          print *, "nloc, Sum(len_cpl)", nloc, Sum (len_cpl)
00173          call psmile_assert (__FILE__, &
00174                  __LINE__, "ncpl == SUM(len_cpl) expected")
00175       endif
00176 #endif
00177 !
00178       if (n_corners > 31) then
00179          ierror = PRISM_Error_internal
00180          ierrp (1) = n_corners
00181 
00182          call psmile_error ( ierror, &
00183                             'Number of corrners too large', &
00184                              ierrp, 1, __FILE__, __LINE__ )
00185          return
00186       endif
00187 !
00188 !------------------------------------------------------------------------
00189 !     Look for points required in global search
00190 !     Value of "search_required" contains a code (2*(n-1)) for the
00191 !     interpolation points to be searched in the global search.
00192 !
00193 !     search_required (i) = 0: No search required for i-th point
00194 !------------------------------------------------------------------------
00195 !
00196 ! NOTE: In the case of hyperplanes (length(j) == 1), 
00197 !       interpolation bases may be multiple requested since
00198 !       neighbors (:, i, n) may be the identical for 
00199 !       different corners.
00200 !       TODO: Remove multiple entries. Should be possibly done
00201 !             before sending the data to adjoining block.
00202 !
00203       Allocate (search_required (nloc), STAT = ierror)
00204 
00205       if (ierror > 0) then
00206          ierrp (1) = ierror
00207          ierrp (2) = nloc
00208 
00209          ierror = PRISM_Error_Alloc
00210 
00211          call psmile_error ( ierror, 'search_required', &
00212                              ierrp, 2, __FILE__, __LINE__ )
00213          return
00214       endif
00215 !
00216       search_required (:) = 0
00217 !
00218 !===> Code points for which global searched is required
00219 !
00220       grid_type = Grids(grid_id)%grid_type
00221 !
00222       if (grid_type == PRISM_Reglonlatvrt     .or. &
00223           grid_type == PRISM_Irrlonlat_Regvrt .or. &
00224           grid_type == PRISM_Irrlonlatvrt     .or. &
00225           grid_type == PRISM_Gaussreduced_Regvrt) then
00226 !
00227          code = 1
00228             do n = 1, n_corners
00229 !cdir vector
00230                do i = 1, nloc
00231                if (neighbors_3d(1, i, n) < grid_valid_shape(1,1) .or. &
00232                    neighbors_3d(1, i, n) > grid_valid_shape(2,1) .or. &
00233                    neighbors_3d(2, i, n) < grid_valid_shape(1,2) .or. &
00234                    neighbors_3d(2, i, n) > grid_valid_shape(2,2) .or. &
00235                    neighbors_3d(3, i, n) < grid_valid_shape(1,3) .or. &
00236                    neighbors_3d(3, i, n) > grid_valid_shape(2,3)) then
00237                   search_required (i) = search_required (i) + code
00238                end if
00239                end do
00240 !
00241 !===> ... next interpolation base (corner)
00242 !
00243             code = code * 2
00244             end do
00245 !
00246 !-----------------------------------------------------------------------
00247 !     Control Mask values
00248 !
00249 ! PSMILE_novalue  : If one neighbor is unvalid reject all.
00250 !                   This will cause the transformer to perform
00251 !                   bi/trilinear interpolation for those points
00252 !                   only for which all neighbors are valid.
00253 !
00254 ! PSMILE_tneighbour: Reject all unvalid neighbors but keep the valid.
00255 !                   This will cause the transformer to perform
00256 !                   bi/trilinear interpolation for those points
00257 !                   only for which all neighbors are valid.
00258 !                   Those for which less than "n_corners" valid neighbors
00259 !                   have been found will be calculated using weighted
00260 !                   distances.
00261 !
00262 ! PSMILE_nneighbour: == PSMILE_undef [default]
00263 !                   Bi/trilinear interpolation for those points for which
00264 !                   all "n_corners" points are valid.
00265 !                   For those for which less than "n_corners" valid
00266 !                   neighbors were found those neighbors are kept.
00267 !                   For the "n_extra" target points for which 0 valid
00268 !                   neighbors were found we invoke the search for
00269 !                   one single nearest neighbor.
00270 !-----------------------------------------------------------------------
00271 !
00272          if (mask_available .and. use_how == PSMILE_novalue) then
00273 !
00274 !===> ... Allocate and initialize work vector "mask_cell" with
00275 !         mask_cell (i) = Number of neighbour points of cell "i"
00276 !                         which are masked out.
00277 !
00278             Allocate (mask_cell (nloc), STAT = ierror)
00279             if (ierror > 0) then
00280                ierrp (1) = ierror
00281                ierrp (2) = nloc
00282 
00283                ierror = PRISM_Error_Alloc
00284 
00285                call psmile_error ( ierror, 'mask_cell', &
00286                                    ierrp, 2, __FILE__, __LINE__ )
00287                return
00288             endif
00289 !
00290             mask_cell (:) = 0
00291 
00292 !           Get corners which are flagged as false
00293 
00294             code = 1
00295 
00296             do n = 1, n_corners
00297 #ifdef DEBUG_TRACE
00298                if (ictl > 0 .and. ictl <= nloc) then
00299                   if (neighbors_3d(1, ictl, n) >= grid_valid_shape(1,1) .and. &
00300                       neighbors_3d(1, ictl, n) <= grid_valid_shape(2,1) .and. &
00301                       neighbors_3d(2, ictl, n) >= grid_valid_shape(1,2) .and. &
00302                       neighbors_3d(2, ictl, n) <= grid_valid_shape(2,2) .and. &
00303                       neighbors_3d(3, ictl, n) >= grid_valid_shape(1,3) .and. &
00304                       neighbors_3d(3, ictl, n) <= grid_valid_shape(2,3) ) then
00305                      print *, 'DEBUG_TRACE: psmile_neigh_global_points: ictl',   &
00306                               ictl, n, neighbors_3d(:, ictl, n),    &
00307                               mask_array (neighbors_3d(1, ictl, n), &
00308                                           neighbors_3d(2, ictl, n), &
00309                                           neighbors_3d(3, ictl, n))
00310                  endif
00311               endif
00312 #endif
00313 
00314 !cdir vector
00315                do i = 1, nloc
00316                if (IAND (search_required (i), code) == 0) then
00317 !
00318 !                 neighbors_3d (:, i, n) is within valid grid shape
00319 !                 See above
00320 !
00321                   if ( .not. mask_array (neighbors_3d(1, i, n), &
00322                                          neighbors_3d(2, i, n), &
00323                                          neighbors_3d(3, i, n)) ) &
00324                      mask_cell(i) = mask_cell (i) + 1
00325                endif
00326                end do
00327 !
00328 !===> ... next interpolation base (corner)
00329 !
00330             code = code * 2
00331             end do ! n
00332 !
00333 !     Note: "outside" must be greater than
00334 !           "grid_valid_shape (2,1) + maximal with of interpolation stencil"
00335 !           in order to enable global search.
00336 !               
00337           if ((grid_type == PRISM_Gaussreduced_Regvrt) .and. &
00338               associated(grids(grid_id)%reduced_gauss_data%remote_index)) then
00339             outside = grid_valid_shape(2,1) + &
00340                       size(Grids(grid_id)%reduced_gauss_data%remote_index) + 11
00341           else
00342             outside = grid_valid_shape(2,1) + 11
00343           endif
00344 !
00345 !===> How should masked values be handled ?
00346 !
00347 !       if ( use_how == PSMILE_novalue ) then
00348 !
00349 !       Ignore cells with one or more neighbors flagged as false 
00350 !       by moving all neighbors out of the valid range
00351 !       (see psmile_compact_neighbors_3d)
00352 !
00353                do n = 1, n_corners
00354 !cdir vector
00355                   do i = 1, nloc
00356                   if ( mask_cell(i) > 0 ) then
00357                      neighbors_3d(1, i, n) = outside
00358                   endif
00359                   enddo
00360                enddo
00361 !
00362 !===>          Remove all points from global search for which
00363 !              already a masked out value was found.
00364 !
00365                do i = 1, nloc
00366                   if ( mask_cell(i) > 0) then
00367                      search_required (i) = 0
00368                   endif
00369                end do
00370 !
00371 !           endif ! if (use_how == PSMILE_novalue)
00372 !
00373             Deallocate (mask_cell)
00374 
00375          endif
00376 
00377       else 
00378 
00379          ierrp (1) = grid_type
00380          ierror = PRISM_Error_Internal
00381 
00382          call psmile_error ( ierror, 'unknown grid generation type', &
00383                              ierrp, 1, __FILE__, __LINE__ )
00384          return
00385 
00386       endif
00387 !
00388 !===> Store cells/points which require global search
00389 !     Note: The index in the entire (!) vector "neighbors_3d" is stored
00390 !           and not the relative index in the partition "ipart"
00391 !     ??? Lohnt es sich das fuer jede Partition abzuspeichern ?
00392 !     ??? Geht das nicht fuer alle Punkte ?
00393 !
00394       nprev = 0
00395 !
00396       do ipart = 1, search%search_data%npart
00397          if (len_cpl (ipart) > 0) then
00398             nbeg = nprev + 1
00399             nend = nprev + len_cpl (ipart)
00400 !
00401             nreq = 0
00402 !cdir vector
00403             do i = nbeg, nend
00404                if (search_required(i) /= 0) nreq = nreq + 1
00405             end do
00406 
00407             if (nreq > 0) then
00408                Allocate (indices_req (nreq), required (nreq), stat = ierror)
00409                if (ierror > 0) then
00410                   ierrp (1) = ierror
00411                   ierrp (2) = nreq * 2
00412 
00413                   ierror = PRISM_Error_Alloc
00414 
00415                   call psmile_error ( ierror, 'indices_req, required', &
00416                                       ierrp, 2, __FILE__, __LINE__ )
00417                   return
00418                endif
00419 !
00420                j = 0
00421 !cdir vector
00422                do i = nbeg, nend
00423                   if (search_required(i) /= 0) then
00424                      j = j + 1
00425                      indices_req (j) = i
00426                      required (j) = search_required (i)
00427                   endif
00428                end do
00429 !
00430 !===> ...... Save global search data in structure "extra_search"
00431 !
00432                extra_search%indices_req(ipart)%vector => indices_req
00433                extra_search%required   (ipart)%vector => required
00434                extra_search%len_req    (ipart)        = nreq
00435 !
00436                extra_search%n_req = extra_search%n_req + nreq
00437 
00438 #ifdef DEBUG_TRACE
00439                do j = 1, nreq
00440                   if (ictl == indices_req (j)) exit
00441                end do
00442 !
00443                if (j <= nreq) then
00444                   print *, 'DEBUG_TRACE: psmile_neigh_global_points: ipart, ictl', &
00445                              ipart, ictl
00446                   print *, 'DEBUG_TRACE: index in indices_req :', j, &
00447                               ', required:', required(j)
00448 !
00449                   do n = 1, n_corners
00450                      print *, 'DEBUG_TRACE: ng', neighbors_3d(:, ictl, n)
00451                   end do
00452                endif
00453 #endif 
00454 !
00455 #ifdef DEBUGX
00456                print *, 'ipart, nreq ', ipart, nreq
00457                do j = 1, nreq
00458                   i = indices_req (j)
00459                   print *, 'j, i, required', j, i, required(j)
00460 !
00461                   do n = 1, n_corners
00462                      print *, 'ng', neighbors_3d(:, i, n)
00463                   end do
00464                end do
00465 #endif
00466             endif ! nreq > 0
00467 !
00468 !===> ... next partition
00469 !
00470          nprev = nend
00471          endif ! len_cpl  > 0
00472       end do ! ipart
00473 !
00474 !===> All done
00475 !
00476 #ifdef VERBOSE
00477       print 9980, trim(ch_id), extra_search%n_req
00478 
00479       call psmile_flushstd
00480 #endif /* VERBOSE */
00481 !
00482 !  Formats:
00483 !
00484 9990 format (1x, a, ': psmile_neigh_global_points:')
00485 9980 format (1x, a, ': psmile_neigh_global_points: eof, nreq', i6)
00486 
00487 #ifdef PRISM_ASSERTION
00488 #endif
00489 
00490       end subroutine psmile_neigh_global_points

Generated on 1 Dec 2011 for Oasis4 by  doxygen 1.6.1