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%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 2983 2011-02-24 12:49:29Z hanke $
00150 !  $Author: hanke $
00151 !
00152    Character(len=len_cvs_string), save :: mycvs = 
00153        '$Id: psmile_neigh_global_points.F90 2983 2011-02-24 12:49:29Z 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)%recv_list)) then
00339             outside = grid_valid_shape(2,1) + sum(grids(grid_id)%recv_list) + 11
00340           else
00341             outside = grid_valid_shape(2,1) + 11
00342           endif
00343 !
00344 !===> How should masked values be handled ?
00345 !
00346 !       if ( use_how == PSMILE_novalue ) then
00347 !
00348 !       Ignore cells with one or more neighbors flagged as false 
00349 !       by moving all neighbors out of the valid range
00350 !       (see psmile_compact_neighbors_3d)
00351 !
00352                do n = 1, n_corners
00353 !cdir vector
00354                   do i = 1, nloc
00355                   if ( mask_cell(i) > 0 ) then
00356                      neighbors_3d(1, i, n) = outside
00357                   endif
00358                   enddo
00359                enddo
00360 !
00361 !===>          Remove all points from global search for which
00362 !              already a masked out value was found.
00363 !
00364                do i = 1, nloc
00365                   if ( mask_cell(i) > 0) then
00366                      search_required (i) = 0
00367                   endif
00368                end do
00369 !
00370 !           endif ! if (use_how == PSMILE_novalue)
00371 !
00372             Deallocate (mask_cell)
00373 
00374          endif
00375 
00376       else 
00377 
00378          ierrp (1) = grid_type
00379          ierror = PRISM_Error_Internal
00380 
00381          call psmile_error ( ierror, 'unknown grid generation type', &
00382                              ierrp, 1, __FILE__, __LINE__ )
00383          return
00384 
00385       endif
00386 !
00387 !===> Store cells/points which require global search
00388 !     Note: The index in the entire (!) vector "neighbors_3d" is stored
00389 !           and not the relative index in the partition "ipart"
00390 !     ??? Lohnt es sich das fuer jede Partition abzuspeichern ?
00391 !     ??? Geht das nicht fuer alle Punkte ?
00392 !
00393       nprev = 0
00394 !
00395       do ipart = 1, search%npart
00396          if (len_cpl (ipart) > 0) then
00397             nbeg = nprev + 1
00398             nend = nprev + len_cpl (ipart)
00399 !
00400             nreq = 0
00401 !cdir vector
00402             do i = nbeg, nend
00403                if (search_required(i) /= 0) nreq = nreq + 1
00404             end do
00405 
00406             if (nreq > 0) then
00407                Allocate (indices_req (nreq), required (nreq), stat = ierror)
00408                if (ierror > 0) then
00409                   ierrp (1) = ierror
00410                   ierrp (2) = nreq * 2
00411 
00412                   ierror = PRISM_Error_Alloc
00413 
00414                   call psmile_error ( ierror, 'indices_req, required', &
00415                                       ierrp, 2, __FILE__, __LINE__ )
00416                   return
00417                endif
00418 !
00419                j = 0
00420 !cdir vector
00421                do i = nbeg, nend
00422                   if (search_required(i) /= 0) then
00423                      j = j + 1
00424                      indices_req (j) = i
00425                      required (j) = search_required (i)
00426                   endif
00427                end do
00428 !
00429 !===> ...... Save global search data in structure "extra_search"
00430 !
00431                extra_search%indices_req(ipart)%vector => indices_req
00432                extra_search%required   (ipart)%vector => required
00433                extra_search%len_req    (ipart)        = nreq
00434 !
00435                extra_search%n_req = extra_search%n_req + nreq
00436 
00437 #ifdef DEBUG_TRACE
00438                do j = 1, nreq
00439                   if (ictl == indices_req (j)) exit
00440                end do
00441 !
00442                if (j <= nreq) then
00443                   print *, 'DEBUG_TRACE: psmile_neigh_global_points: ipart, ictl', &
00444                              ipart, ictl
00445                   print *, 'DEBUG_TRACE: index in indices_req :', j, &
00446                               ', required:', required(j)
00447 !
00448                   do n = 1, n_corners
00449                      print *, 'DEBUG_TRACE: ng', neighbors_3d(:, ictl, n)
00450                   end do
00451                endif
00452 #endif 
00453 !
00454 #ifdef DEBUGX
00455                print *, 'ipart, nreq ', ipart, nreq
00456                do j = 1, nreq
00457                   i = indices_req (j)
00458                   print *, 'j, i, required', j, i, required(j)
00459 !
00460                   do n = 1, n_corners
00461                      print *, 'ng', neighbors_3d(:, i, n)
00462                   end do
00463                end do
00464 #endif
00465             endif ! nreq > 0
00466 !
00467 !===> ... next partition
00468 !
00469          nprev = nend
00470          endif ! len_cpl  > 0
00471       end do ! ipart
00472 !
00473 !===> All done
00474 !
00475 #ifdef VERBOSE
00476       print 9980, trim(ch_id), extra_search%n_req
00477 
00478       call psmile_flushstd
00479 #endif /* VERBOSE */
00480 !
00481 !  Formats:
00482 !
00483 9990 format (1x, a, ': psmile_neigh_global_points:')
00484 9980 format (1x, a, ': psmile_neigh_global_points: eof, nreq', i6)
00485 
00486 #ifdef PRISM_ASSERTION
00487 #endif
00488 
00489       end subroutine psmile_neigh_global_points

Generated on 18 Mar 2011 for Oasis4 by  doxygen 1.6.1