psmile_neigh_extra_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_extra_points
00008 !
00009 ! !INTERFACE:
00010 
00011       subroutine psmile_neigh_extra_points (search, extra_search, &
00012                mask_array, mask_shape, mask_available, use_how,   &
00013                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_extra_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(3)
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_valid_shape (2, ndim_3d)
00059 
00060 !     Specifies the valid block shape for the "ndim_3d"-dimensional block
00061 !
00062       Integer,         Intent (In)    :: nloc
00063 !
00064 !     Total number of locations to be transferred.
00065 !     Number of locations for which extra points should be searched.
00066 !     Second dimension of neighbors array "neighbors_3d"
00067 !
00068       Integer,         Intent (In)    :: n_corners
00069 !
00070 !     Last dimension of neighbors array "neighbors_3d" and
00071 !     number of interpolation bases.
00072 !
00073       Integer, Intent (In)            :: len_cpl (search%npart)
00074 
00075 !     Number of points to be sent to the coupler for each partition.
00076 !
00077 ! !INPUT/OUTPUT PARAMETERS:
00078 !
00079       Type (Extra_search_info), Intent (InOut) :: extra_search
00080 !
00081 !     Number of locations where
00082 !       (*) required mask values were not true
00083 !
00084       Integer,         Intent (InOut) :: neighbors_3d (ndim_3d, nloc, n_corners)
00085 
00086 !     Indices of neighbor locations (interpolation bases)
00087 !
00088 ! !OUTPUT PARAMETERS:
00089 
00090       Integer,         Intent (Out)   :: ierror
00091 
00092 !     Returns the error code of PSMILE_Neigh_extra_points;
00093 !             ierror = 0 : No error
00094 !             ierror > 0 : Severe error
00095 !
00096 ! !LOCAL VARIABLES
00097 !
00098 !     ... for locations searched
00099 !
00100       Integer                         :: grid_id
00101       Integer, Pointer                :: recv_list(:)
00102       Integer                         :: search_mode
00103       Integer                         :: i, j, n, nbeg, nend
00104 !
00105 !     ... for locations controlled
00106 !
00107       Integer                         :: n_extra, outside
00108 !
00109       Integer, Pointer                :: indices (:)
00110       Logical, Allocatable            :: mask_cell (:)
00111 !
00112 !     ... for partitions
00113 !
00114       Integer                         :: ipart
00115 !
00116 !     ... for error handling
00117 !
00118       Integer, parameter              :: nerrp = 2
00119       Integer                         :: ierrp (nerrp)
00120 !
00121 !
00122 ! !DESCRIPTION:
00123 !
00124 ! Subroutine "PSMILe_Neigh_extra_points" determines the points (indices)
00125 ! which require extra search (nearest neighbour search).
00126 ! The extra points are searched the neighbour indices (interpolation
00127 ! bases) specified in
00128 !
00129 !      neighbour (1:ndim_3d, 1:nloc, n_corners).
00130 !
00131 ! !REVISION HISTORY:
00132 !
00133 !   Date      Programmer   Description
00134 ! ----------  ----------   -----------
00135 ! 15.03.06    H. Ritzdorf  created
00136 !
00137 !EOP
00138 !----------------------------------------------------------------------
00139 !
00140 !  $Id: psmile_neigh_extra_points.F90 2991 2011-02-25 08:34:51Z hanke $
00141 !  $Author: hanke $
00142 !
00143    Character(len=len_cvs_string), save :: mycvs = 
00144        '$Id: psmile_neigh_extra_points.F90 2991 2011-02-25 08:34:51Z hanke $'
00145 !
00146 !----------------------------------------------------------------------
00147 !
00148 !  Initialization
00149 !
00150 #ifdef VERBOSE
00151       print 9990, trim(ch_id)
00152 
00153       call psmile_flushstd
00154 #endif /* VERBOSE */
00155 !
00156 !===> Initialization
00157 !
00158       ierror  = 0
00159       search_mode = use_how(1)
00160       grid_id = use_how(3)
00161 !
00162 !     Note: "outside" must be greater than
00163 !           "grid_valid_shape (2,1) + maximal with of interpolation stencil"
00164 !            in order to enable global search.
00165 !
00166       if (associated(Grids(grid_id)%recv_list)) then
00167           !
00168           ! in particular for Gauss-reduced grids
00169           !
00170           recv_list => Grids(grid_id)%recv_list
00171           outside   = grid_valid_shape(2,1) + sum(recv_list) + 11
00172       else
00173           outside   = grid_valid_shape(2,1) + 11
00174       endif
00175 !
00176 #ifdef PRISM_ASSERTION
00177 !
00178       if (nloc /= Sum(len_cpl)) then
00179          print *, "nloc, Sum(len_cpl)", nloc, Sum (len_cpl)
00180          call psmile_assert (__FILE__, &
00181               __LINE__, "ncpl == SUM(len_cpl) expected")
00182       endif
00183 
00184       if (extra_search%n_extra /= 0) then
00185          call psmile_assert (__FILE__, &
00186               __LINE__, "extra_search%n_extra /= 0")
00187       endif
00188 #endif
00189 !
00190 !-----------------------------------------------------------------------
00191 !     Control Mask values
00192 !
00193 !     The searched point is located in donor cell
00194 !     (srcloc(:,i), srcloc(:,i)+1).
00195 !-----------------------------------------------------------------------
00196 !
00197 ! PSMILE_novalue  : If one neighbor is unvalid reject all.
00198 !                   This will cause the transformer to perform
00199 !                   bi/trilinear interpolation for those points
00200 !                   only for which all neighbors are valid.
00201 !
00202 ! PSMILE_tneighbour: Reject all unvalid neighbors but keep the valid.
00203 !                    This will cause the transformer to perform
00204 !                    bi/trilinear interpolation for those points
00205 !                    only for which all neighbors are valid.
00206 !                    Those for which less than "n_corners" valid neighbors
00207 !                    have been found will be calculated using weighted
00208 !                    distances.
00209 !
00210 ! PSMILE_nneighbour: == PSMILE_undef [default]
00211 !                    Bi/trilinear interpolation for those points for which
00212 !                    all "n_corners" points are valid.
00213 !                    For those for which less than "n_corners" valid
00214 !                    neighbors were found those neighbors are kept.
00215 !                    For the "n_extra" target points for which 0 valid
00216 !                    neighbors were found we invoke the search for
00217 !                    one single nearest neighbor.
00218 !
00219 ! NOTE: If a interpolation base is outside of the physical boundary,
00220 !       the base points is handled such as the mask would be false.
00221 !
00222 !-----------------------------------------------------------------------
00223 !
00224 !     set search mode PSMILE_nneighbour to default
00225 !
00226 #ifdef DEBUG
00227 8990  format (1x, a, ': psmile_neigh_extra_points: search_mode', i8, &
00228               '; mask_available ', l1)
00229       print 8990, trim(ch_id), search_mode, mask_available
00230 #endif
00231 !
00232       if ( search_mode == PSMILE_nneighbour ) search_mode = PSMILe_Undef
00233 
00234 #ifdef DEBUG_TRACE
00235          if ( ictl > 0 .and. ictl <= nloc ) then
00236             print *, ' ictl neigh 1', neighbors_3d(1,ictl,:)
00237             print *, ' ictl neigh 2', neighbors_3d(2,ictl,:)
00238             print *, ' ictl neigh 3', neighbors_3d(3,ictl,:)
00239          endif
00240 #endif
00241  if (mask_available) then
00242 
00243 !        Ignore corners of (method) cells flagged as false by moving them
00244 !        out of the valid range (see psmile_compact_neighbors_3d)
00245 
00246          do n = 1, n_corners
00247 !cdir vector
00248             do i = 1, nloc
00249 
00250               if (neighbors_3d(1, i, n) /= extra_search%global_marker) then
00251 !
00252 !             search_mode == vneighbour, not implemented !
00253 !
00254 !             If the point was not found in regular domain,
00255 !             mark it by "outside".
00256 !
00257                   if ( neighbors_3d(1, i, n) < grid_valid_shape(1,1) .or. &
00258                        neighbors_3d(1, i, n) > grid_valid_shape(2,1) .or. &
00259                        neighbors_3d(2, i, n) < grid_valid_shape(1,2) .or. &
00260                        neighbors_3d(2, i, n) > grid_valid_shape(2,2) .or. &
00261                        neighbors_3d(3, i, n) < grid_valid_shape(1,3) .or. &
00262                        neighbors_3d(3, i, n) > grid_valid_shape(2,3) ) then
00263 !
00264                        neighbors_3d(1, i, n) = outside
00265 !
00266 !             This corresponds to "search_mode == tneighbour".
00267 !             Only the actual neighour point is moved outside
00268 !             since the mask is .false..
00269 !
00270                   else if ( neighbors_3d(1, i, n) >= mask_shape(1,1) .and. &
00271                             neighbors_3d(1, i, n) <= mask_shape(2,1) .and. &
00272                             neighbors_3d(2, i, n) >= mask_shape(1,2) .and. &
00273                             neighbors_3d(2, i, n) <= mask_shape(2,2) .and. &
00274                             neighbors_3d(3, i, n) >= mask_shape(1,3) .and. &
00275                             neighbors_3d(3, i, n) <= mask_shape(2,3) ) then
00276 #ifdef DEBUG_TRACE
00277                      if ( i == ictl ) then
00278                           print *, ' ictl neigh & mask ', i, n, neighbors_3d(:, i, n), &
00279                                                     mask_array (neighbors_3d(1, i, n), &
00280                                                                 neighbors_3d(2, i, n), &
00281                                                                 neighbors_3d(3, i, n))
00282                      endif
00283 #endif
00284                      if ( .not. mask_array (neighbors_3d(1, i, n),   &
00285                                             neighbors_3d(2, i, n),   &
00286                                             neighbors_3d(3, i, n)) ) &
00287                        neighbors_3d(1, i, n) = outside
00288                   endif
00289 
00290                endif
00291             enddo ! i
00292          enddo ! n
00293 !
00294 !    search_mode == tneighbour is already treated above. Now we check whether
00295 !    additional neighbours have to be marked as not valid (outside) for
00296 !        search_mode == novalue
00297 !        search_mode == nneighbour | undef [default]  
00298 !
00299          if ( search_mode == PSMILE_novalue .or. &
00300               search_mode == PSMILe_undef ) then
00301 !
00302 !===> ... Allocate and initialize work vector "mask_cell" with
00303 !         mask_cell (i) = .true. : Mask of first point is .false.
00304 !                                  ==> First index is out of range
00305 !
00306             Allocate (mask_cell (nloc), STAT = ierror)
00307             if (ierror > 0) then
00308                ierrp (1) = ierror
00309                ierrp (2) = nloc
00310 
00311                ierror = PRISM_Error_Alloc
00312 
00313                call psmile_error ( ierror, 'mask_cell', &
00314                     ierrp, 2, __FILE__, __LINE__ )
00315                return
00316             endif
00317 !
00318 !cdir vector
00319             do i = 1, nloc
00320                mask_cell (i) = neighbors_3d(1, i, 1) == outside
00321             end do
00322 !
00323             if ( search_mode == PSMILE_novalue ) then
00324 !
00325 !           Ignore cells with one or more neighbors flagged as false 
00326 !           by moving all neighbors out of the valid range
00327 !           (see psmile_compact_neighbors_3d)
00328 !
00329 !           mask_cell (i) = .true. : A mask entry of (method) cell is .false.
00330 !
00331                do n = 2, n_corners
00332 !cdir vector
00333                   do i = 1, nloc
00334                      mask_cell (i) = mask_cell (i) .or. &
00335                           neighbors_3d(1, i, n) == outside
00336                   end do
00337                end do
00338 
00339                do n = 1, n_corners
00340                   !cdir vector
00341                   do i = 1, nloc
00342                      if ( mask_cell(i) ) &
00343                         neighbors_3d(1, i, n) = outside
00344                   enddo
00345                enddo
00346 !
00347             else ! if ( search_mode == PSMILe_undef ) then
00348 !
00349 !               mask_cell (i) = .true. : All mask entries of (method) cell
00350 !                                        are .false.
00351 !
00352                do n = 2, n_corners
00353 !cdir vector
00354                   do i = 1, nloc
00355                      mask_cell (i) = mask_cell (i) .and. &
00356                           neighbors_3d(1, i, n) == outside
00357                   end do
00358                end do
00359 !
00360 #ifdef TEST_EXTRA_SEARCH
00361                print *, '### psmile_neigh_extra_points: Extra-Search for testing enabled'
00362                mask_cell(:) = .true.
00363 #endif
00364 !
00365 !===> Store cells/points which require extra search
00366 !     Note: The index in the entire vector "neighbors_3d" is stored
00367 !           and not the relative index in the partition "ipart"
00368 !
00369 !===> ... Get number of points to be searched extra
00370 !
00371                n_extra = count (mask_cell (:))
00372 !
00373                if (n_extra > 0) then
00374 !
00375 !===> ...... Allocate memory required to store the indices and
00376 !            code for the points required.
00377 !            Note: The indices are stored as index in entire (!) 
00378 !                  array "neighbors"
00379 !
00380                   Allocate (indices (n_extra), stat = ierror)
00381                   if (ierror > 0) then
00382                      ierrp (1) = ierror
00383                      ierrp (2) = n_extra
00384 
00385                      ierror = PRISM_Error_Alloc
00386 
00387                      call psmile_error ( ierror, 'extra_search%indices', &
00388                           ierrp, 2, __FILE__, __LINE__ )
00389                      return
00390 endif
00391 !
00392 !===> ...... Generate indices
00393 !
00394 #ifdef USE_PACK
00395                   indices (1: n_extra) = &
00396                        PACK ((/ (i, i=1,nloc) /), mask_cell)
00397 #else
00398                   j = 0
00399 !cdir vector
00400                   do i = 1, nloc
00401                      if (mask_cell (i)) then
00402                         j = j + 1
00403                         indices (j) = i
00404                      endif
00405                   end do
00406 #endif /* USE_PACK */
00407 !
00408 !===> ...... Generate length per partition
00409 !
00410                   nend = 0
00411                   do ipart = 1, search%npart
00412                      if (len_cpl (ipart) > 0) then
00413                         nbeg = nend + 1
00414                         nend = nend + len_cpl (ipart)
00415 !
00416                         extra_search%len_extra (ipart) = &
00417                              count (mask_cell(nbeg:nend))
00418 !
00419                      endif ! len_cpl > 0
00420                   end do ! ipart
00421 !
00422 #ifdef DEBUGX
00423                   do i = 1, nloc
00424                      if (mask_cell (i)) then
00425                         print *, 'i', i, neighbors_3d(:, i, 1)
00426                         do n = 1, n_corners
00427                            print *, 'ng', neighbors_3d(:, i, n), &
00428                                 mask_array (neighbors_3d(1, i, n), &
00429                                 neighbors_3d(2, i, n), &
00430                                 neighbors_3d(3, i, n))
00431                         end do
00432                      endif
00433                   end do
00434 #endif
00435 !
00436 !===> ...... Save extra search data in structure "extra_search"
00437 !
00438                   extra_search%indices => indices
00439 !
00440                   extra_search%n_extra = n_extra
00441 
00442                endif ! (n_extra > 0)
00443             endif ! if (earch_mode == PSMILE_novalue)
00444 !
00445             Deallocate (mask_cell)
00446             !
00447          endif ! if (search_mode == PSMILE_novalue .or. ...
00448 
00449       endif ! if (mask_available)
00450 !
00451 !===> All done
00452 !
00453 #ifdef VERBOSE
00454       print 9980, trim(ch_id), extra_search%n_extra
00455 
00456 !     print *, extra_search%len_extra (:)
00457       call psmile_flushstd
00458 #endif /* VERBOSE */
00459 !
00460 !  Formats:
00461 !
00462 9990  format (1x, a, ': psmile_neigh_extra_points:')
00463 9980  format (1x, a, ': psmile_neigh_extra_points: eof, n_extra', i6)
00464 
00465     end subroutine psmile_neigh_extra_points

Generated on 18 Mar 2011 for Oasis4 by  doxygen 1.6.1