psmile_hash_extra.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_Hash_extra
00008 !
00009 ! !INTERFACE:
00010 
00011       subroutine psmile_hash_extra (search, locs, hash, nlocs, &
00012                     mask_array, mask_shape, mask_available,    &
00013                     grid_valid_shape, ierror)
00014 !
00015 ! !USES:
00016 !
00017       use PRISM
00018 !
00019       use PSMILe, dummy_interface => PSMILe_Hash_extra
00020 
00021       Implicit none
00022 !
00023 ! !INPUT PARAMETERS:
00024 !
00025       Integer,            Intent (in) :: nlocs
00026 !
00027 !     Number of points (interpolation bases) found
00028 !
00029       Integer,            Intent (In) :: locs (ndim_3d, nlocs)
00030 !
00031 !     Info on the component in which the donor cells
00032 !     should be searched.
00033 
00034       Integer, Intent (In)            :: mask_shape (2, ndim_3d)
00035 
00036 !     Dimension of (method) mask array
00037 
00038       Logical, Intent (In)            :: mask_array (mask_shape (1,1): 
00039                                                      mask_shape (2,1), 
00040                                                      mask_shape (1,2): 
00041                                                      mask_shape (2,2), 
00042                                                      mask_shape (1,3): 
00043                                                      mask_shape (2,3))
00044 !     Mask of the method
00045 
00046       Logical, Intent (In)            :: mask_available
00047 
00048 !     Is mask specified in array "mask_array" ?
00049 !     mask_available = .false. : Mask is not available
00050 !                      .true.  : Mask is     available
00051 
00052       Integer,                     Intent (In)    :: grid_valid_shape (2, 
00053                                                              ndim_3d)
00054 !
00055 !     Specifies the valid block shape for the "ndim_3d"-dimensional block
00056 !     (without halo/overlap regions) with
00057 !
00058 !     grid_valid_shape (1,i) = Lowest  "i"-th index of block
00059 !     grid_valid_shape (2,i) = Highest "i"-th index of block
00060 !
00061 ! !INPUT/OUTPUT PARAMETERS:
00062 !
00063       Type (Enddef_global_search), Intent (InOut) :: search
00064 
00065 !     Data on the points to be searched
00066 
00067 ! !OUTPUT PARAMETERS:
00068 !
00069       Integer,                     Intent (Out)   :: hash (nlocs)
00070 !
00071 !     Hash value used (can be used as masked for further computations)
00072 !     with
00073 !     hash (i) > 0  : Point "locs(:, i)" was put into list of points
00074 !                     to be sent.
00075 !     hash (i) == 0 : Point "locs(:, i)" is masked out
00076 !     hash (i) == -1: Point "locs(:, i)" is outside
00077 !
00078       Integer,                     Intent (Out)   :: ierror
00079 
00080 !     Returns the error code of PSMILe_Search_donor_extra_off;
00081 !             ierror = 0 : No error
00082 !             ierror > 0 : Severe error
00083 !
00084 ! !LOCAL PARAMETERS:
00085 !
00086 ! outside_ng   = Hash value for a point which is outside the block region
00087 ! masked_out   = Hash value for a point which is masked out
00088 !
00089       Integer, Parameter           :: nd_hliste = 1024
00090 !
00091       Integer, Parameter           :: outside_ng = -1
00092       Integer, Parameter           :: masked_out = 0
00093 !
00094 ! !LOCAL VARIABLES
00095 !
00096 !     ... loop variables
00097 !
00098       Integer                      :: i, k, l, n, nf
00099       Integer                      :: nbeg, nend
00100 !
00101 !     ... 
00102 !
00103       Integer                      :: length (ndim_3d)
00104 !
00105 !     ... For searched points of control volume
00106 !
00107       Integer, Allocatable         :: locs2liste (:)
00108       Integer, Allocatable         :: hash_liste (:)
00109       Integer, Allocatable         :: liste (:)
00110       Integer, Allocatable         :: next (:)
00111 !
00112 !     ... Stored in search
00113 !
00114       Integer                      :: n_liste, n_found
00115 !
00116       Integer, Pointer             :: neigh (:, :)
00117       Integer, Pointer             :: index_found (:)
00118 !
00119 !     ... for error parameters
00120 !
00121       Integer, parameter           :: nerrp = 1
00122       Integer                      :: ierrp (nerrp)
00123 !
00124 ! !DESCRIPTION:
00125 !
00126 ! Subroutine "PSMILe_Hash_extra" creates compact list of points
00127 ! which were found in the extra global search (i.e. which have to be sent
00128 ! to the requesting process) and stores the corresponding
00129 ! data in "search".
00130 !
00131 ! Points which are outside the valid shape "grid_valid_shape" are
00132 ! not included to the compact list. Points which are masked out
00133 ! (if "mask_available" is true) are transferred and the corresponding
00134 ! hash value "hash(*) = masked_out = 0" is returned.
00135 !
00136 ! The routine creates
00137 ! (*) a vector "index_found (1:n_found) which maps the sequence of 
00138 !     "n_found" points to the compact list "1:n_liste" which contains
00139 !     each found point only once.
00140 ! (*) the compact list "neigh_3d(1:n_liste)" which contains the
00141 !     3d logical indices of the compact list.
00142 ! 
00143 ! !REVISION HISTORY:
00144 !
00145 !   Date      Programmer   Description
00146 ! ----------  ----------   -----------
00147 ! 03.11.06    H. Ritzdorf  created
00148 !
00149 !EOP
00150 !----------------------------------------------------------------------
00151 !
00152 ! $Id: psmile_hash_extra.F90 2082 2009-10-21 13:31:19Z hanke $
00153 ! $Author: hanke $
00154 !
00155    Character(len=len_cvs_string), save :: mycvs = 
00156        '$Id: psmile_hash_extra.F90 2082 2009-10-21 13:31:19Z hanke $'
00157 !
00158 !----------------------------------------------------------------------
00159 !
00160 !  Initialization
00161 !
00162 #ifdef VERBOSE
00163       print 9990, trim(ch_id)
00164 
00165       call psmile_flushstd
00166 #endif /* VERBOSE */
00167 !
00168       ierror = 0
00169 !
00170       length (1:ndim_3d) = grid_valid_shape(2,1:ndim_3d) - &
00171                            grid_valid_shape(1,1:ndim_3d) + 1
00172 !
00173 #ifdef PRISM_ASSERTION
00174 !
00175 !===> Internal control
00176 !
00177       if (nlocs <= 0) then
00178          call psmile_assert ( __FILE__, __LINE__, &
00179                              'Number of points to be searched == 0 ?!?')
00180       endif
00181 !
00182       if (mask_available) then
00183          if (grid_valid_shape (1,1) < mask_shape (1,1) .or. &
00184              grid_valid_shape (2,1) > mask_shape (2,1) .or. &
00185              grid_valid_shape (1,2) < mask_shape (1,2) .or. &
00186              grid_valid_shape (2,2) > mask_shape (2,2) .or. &
00187              grid_valid_shape (1,3) < mask_shape (1,3) .or. &
00188              grid_valid_shape (2,3) > mask_shape (2,3)) then
00189             print *, "grid_valid_shape", grid_valid_shape
00190             print *, "mask_shape      ", mask_shape
00191 
00192             call psmile_assert ( __FILE__, __LINE__, &
00193                     'grid_valid_shape must be in mask_shape')
00194 
00195          endif
00196       endif
00197 #endif
00198 !
00199 !===> Compute hash value (index in fortran order) for each location
00200 !     to be searched.
00201 !     The hash value is always greater than 0.
00202 !
00203 !cdir vector
00204          do n = 1, nlocs
00205          hash(n) = ((locs (3,n) - grid_valid_shape(1,3))  * length(2) + &
00206                     (locs (2,n) - grid_valid_shape(1,2))) * length(1) + &
00207                     (locs (1,n) - grid_valid_shape(1,1)) + 1
00208          end do
00209 !
00210 !===> Remove points which are outside of block.
00211 !     Set hash value to negative value in this case.
00212 !
00213 !cdir vector
00214          do n = 1, nlocs
00215          if (locs(1,n) < grid_valid_shape(1,1) .or. &
00216              locs(1,n) > grid_valid_shape(2,1) .or. &
00217              locs(2,n) < grid_valid_shape(1,2) .or. &
00218              locs(2,n) > grid_valid_shape(2,2) .or. &
00219              locs(3,n) < grid_valid_shape(1,3) .or. &
00220              locs(3,n) > grid_valid_shape(2,3)) then
00221             hash (n) = outside_ng
00222          endif
00223          end do
00224 !
00225 !===> Control Mask values
00226 !     If mask value if not true, set hash value to 0 = masked_out.
00227 !
00228       if (mask_available) then
00229 !cdir vector
00230             do n = 1, nlocs
00231             if (hash (n) > 0) then
00232                if (.not. mask_array (locs(1, n), &
00233                                      locs(2, n), &
00234                                      locs(3, n)) ) then
00235                   hash (n) = masked_out
00236                endif
00237             endif
00238             end do
00239       endif
00240 !
00241 #ifdef DEBUGX
00242       print *, 'hash values and locs ', grid_valid_shape
00243          do n = 1, nlocs
00244          print *, 'n, hash(n), locs(:,n) ', &
00245                    n, hash(n), locs(:,n)
00246          end do
00247 #endif
00248 !
00249 !------------------------------------------------------------------------
00250 !     Collapse Points
00251 !
00252 ! hash_liste(i) contains the last index "n" of "hash" 
00253 !               with "hash (n) = i"
00254 ! next (n)      contains the next index "k" with "hash(k) = i"
00255 !
00256 ! liste(1:n)    is a compact list of all indices of "hash"
00257 !               which contain a significant point (not duplicated)
00258 ! locs2liste    contains the transformation
00259 !               from an index in "locs" (or "hash")
00260 !               into an index in "liste".
00261 !------------------------------------------------------------------------
00262 !
00263       Allocate (hash_liste (nd_hliste), stat = ierror)
00264       if (ierror /= 0) then
00265          ierrp (1) = nd_hliste
00266 
00267          ierror = PRISM_Error_Alloc
00268 
00269          call psmile_error ( ierror, 'nd_hliste', ierrp, 1, &
00270                  __FILE__, __LINE__ )
00271          return
00272       endif
00273 !
00274       Allocate (next (nlocs), liste (nlocs), locs2liste (nlocs), &
00275                 stat = ierror)
00276       if (ierror /= 0) then
00277          ierrp (1) = nlocs * 3
00278 
00279          ierror = PRISM_Error_Alloc
00280 
00281          call psmile_error ( ierror, 'next, liste, locs2liste', ierrp, 1, &
00282                  __FILE__, __LINE__ )
00283          return
00284       endif
00285 !
00286       next (:) = 0
00287       hash_liste (:) = 0
00288 !
00289 #ifdef PRISM_ASSERTION
00290       locs2liste (:) = -11
00291 #endif
00292 !
00293 !===> ... Map locations in locs to hash range
00294 !         hash_liste (i) = Last index "n" in "locs" with
00295 !         "mod (hash (n), nd_hliste) + 1 = i"
00296 !
00297 !cdir vector
00298          do n = 1, nlocs
00299          if (hash (n) > 0) then
00300             i = mod (hash(n), nd_hliste) + 1
00301             if (hash_liste(i) > 0) then
00302                next (n) = hash_liste(i)
00303             endif
00304 
00305             hash_liste(i) = n
00306          endif
00307          end do
00308 !
00309 #ifdef DEBUGX
00310          print *, 'length', length (:)
00311          print *, 'hash', hash (1:nlocs)
00312          print *, 'hashliste', hash_liste (1:nd_hliste)
00313 #endif
00314 !
00315 !===> ... Create compact list "liste" of indices (in "locs")
00316 !         of different "hash" values.
00317 !         Create mapping "locs2liste" from "locs" to "liste"
00318 !
00319 ! n_liste = Number of points to be sent to requesting process
00320 !
00321       n = 0
00322 !cdir vector
00323          do i = 1, nd_hliste
00324          if (hash_liste (i) > 0) then
00325             n = n + 1
00326 !
00327 !===> ... Store first index for hash value "hash_liste(i)"
00328 !
00329             liste (n) = hash_liste (i)
00330             locs2liste (hash_liste (i)) = n
00331 
00332             nbeg = n
00333             nend = n
00334 !
00335             k = hash_liste (i)
00336               do while (next (k) > 0) 
00337 !
00338 !===> ... Was the location "hash(k)" already stored in "liste" ?
00339 !         If not, add index of location to "liste".
00340 !         Otherwise, store mapping from "locs" to index in "liste"
00341 !
00342               k = next (k)
00343                  do l = nbeg, nend
00344                  if (hash (k) == hash (liste(l))) exit
00345                  end do
00346 
00347               if (l > nend) then
00348                  n = n + 1
00349 !
00350                  liste (n) = k
00351                  locs2liste (k) = n
00352                  nend = nend + 1
00353               else
00354                  locs2liste(k) = l
00355               endif
00356               end do
00357 !
00358          endif
00359          end do
00360 !
00361       n_liste = n
00362 !
00363 #ifdef PRISM_ASSERTION
00364 !
00365 !===> Check assertions
00366 !
00367 !cdir vector
00368          do n = 1, nlocs
00369          if (hash (n) > 0 .and. &
00370              (locs2liste (n) <= 0 .or. locs2liste(n) > n_liste)) exit
00371          end do
00372 !
00373       if (n < nlocs) then
00374          print *, 'n, nlocs, locs2liste (n)', n, nlocs, locs2liste (n)
00375          call psmile_assert ( __FILE__, __LINE__, &
00376                              'locs2liste is not totally filled')
00377       endif
00378 #endif
00379 !
00380 !===> Remove arrays which are not further required
00381 !
00382       Deallocate (hash_liste, next)
00383 !
00384 !===> Store data on locations found
00385 !
00386       if (n_liste > 0) then
00387 #if 0
00388 !
00389 !===> ... Get number of points found
00390 !
00391          n = 0
00392          n_found = 0
00393             do j = 1, n_corners
00394 !cdir vector
00395                do i = 1, n_send
00396                if (ijkmsk (i,j)) then
00397                   n = n + 1
00398                   if (hash(n) >= 0) n_found = n_found + 1
00399                endif 
00400                end do
00401             end do
00402 !
00403 #ifdef PRISM_ASSERTION
00404          if (n /= nlocs) then
00405             print *, 'nlocs, n', nlocs, n
00406             call psmile_assert ( __FILE__, __LINE__, &
00407                                 'n /= nlocs')
00408          endif
00409 !
00410          if (n_found > nlocs) then
00411             print *, 'nlocs, n_found', nlocs, n_found
00412             call psmile_assert ( __FILE__, __LINE__, &
00413                                 'n_found > nlocs')
00414          endif
00415 #endif
00416 #else
00417          n_found = Count (hash(:) >= 0)
00418 !cdir vector
00419 !        n_found = 0
00420 !           do n = 1, nlocs
00421 !           if (hash(n) >= 0) n_found = n_found + 1
00422 !           end do
00423 #endif
00424 !
00425 !===> ... Allocate vectors required for other routines ...
00426 !
00427          Allocate (neigh (ndim_3d, n_liste), index_found (n_found), &
00428                    stat = ierror)
00429          if (ierror /= 0) then
00430             ierrp (1) = n_liste * ndim_3d + n_found
00431 
00432             ierror = PRISM_Error_Alloc
00433 
00434             call psmile_error ( ierror, 'n_liste', ierrp, 1, &
00435                     __FILE__, __LINE__ )
00436             return
00437          endif
00438 !
00439 !===> ... and store indices of points to be transferred to
00440 !         the destination process
00441 !
00442 !cdir vector
00443             do n = 1, n_liste
00444             neigh (1, n) = locs (1, liste(n))
00445             neigh (2, n) = locs (2, liste(n))
00446             neigh (3, n) = locs (3, liste(n))
00447             end do
00448 !
00449 #ifdef DEBUGX
00450         print *, 'locations to be sent: nd_liste', n_liste
00451             do n = 1, n_liste
00452             print *, 'neigh', neigh (:, n)
00453             end do
00454 #endif
00455 !
00456 !===> ... 
00457 !         Store indices to "neigh" in corresponding sequence
00458 !         of locations found.
00459 !
00460          nf = 0
00461 !cdir vector
00462             do n = 1, nlocs
00463             if (hash (n) >= 0) then
00464 !
00465 !===> ...... Required interpolation base was found
00466 !            (may be masked out (hash(n) == masked_out).
00467 !            Corresponding value is stored in position "index_found(n)".
00468 !
00469                nf = nf + 1
00470 !
00471                if (hash(n) > 0) then
00472                   index_found (nf) = locs2liste (n)
00473                else
00474                   index_found (nf) = masked_out
00475                endif
00476             endif
00477 !
00478             end do ! n
00479 
00480 #ifdef PRISM_ASSERTION
00481         if (nf /= n_found) then
00482            print *, 'nf, n_found, index', nf, n_found
00483            call psmile_assert ( __FILE__, __LINE__, &
00484                    'nf /= n_found')
00485         endif
00486 !
00487            do i = 1, n_found
00488            if (index_found(i) /= masked_out .and. &
00489               (index_found(i) < 1 .or. index_found(i) > n_liste)) exit
00490            end do
00491 !
00492         if (i < n_found) then
00493            print *, 'i, n_found, index', i, n_found, index_found (i)
00494            call psmile_assert ( __FILE__, __LINE__, &
00495                    'invalid found index generated')
00496         endif
00497 #endif
00498 !
00499 #ifdef DEBUGX
00500         print *, 'index_found', n_found
00501             do i = 1, n_found
00502             print *, 'i', i, index_found (i)
00503             end do
00504 #endif 
00505 
00506       else
00507 !
00508 !===> No point found
00509 !
00510          NULLIFY (neigh)
00511          NULLIFY (index_found)
00512 
00513          n_found = 0
00514 
00515       endif
00516 !
00517 !===> Deallocate memory allocated
00518 !
00519       Deallocate (locs2liste)
00520 !
00521 !===> Set return info
00522 !
00523       search%n_liste  = n_liste
00524       search%neigh_3d => neigh
00525 !
00526       search%n_found  = n_found
00527       search%index_found => index_found
00528 !
00529 !===> All done
00530 !
00531 #ifdef VERBOSE
00532       print 9980, trim(ch_id), ierror, n_found, nlocs
00533 
00534       call psmile_flushstd
00535 #endif /* VERBOSE */
00536 !
00537       return
00538 !
00539 !  Formats:
00540 !
00541 #ifdef VERBOSE
00542 9990 format (1x, a, ': psmile_hash_extra')
00543 9980 format (1x, a, ': psmile_hash_extra: eof', &
00544                     ', ierror =', i4, ', n_found =', i8, i8)
00545 #endif /* VERBOSE */
00546 
00547       end subroutine PSMILe_Hash_extra

Generated on 18 Mar 2011 for Oasis4 by  doxygen 1.6.1