psmile_neigh_nearx_sub_irr_real.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_nearx_sub_irr_real
00008 !
00009 ! !INTERFACE:
00010 
00011       subroutine psmile_neigh_nearx_sub_irr_real ( grid_id,  &
00012                            x_coords, y_coords, z_coords,     &
00013                            coords_shape,                     &
00014                            mask_array, mask_shape, mask_available, &
00015                            sin_values, cos_values,           &
00016                            grid_valid_shape, search_mode,    &
00017                            neighbors_3d, num_neigh, nloc,    &
00018                            extra_search, ijk,                &
00019                            sin_search, cos_search, z_search, &
00020                            jbeg, jend, width, ierror)
00021 !
00022 ! !USES:
00023 !
00024       use PRISM_constants
00025 !
00026       use PSMILe, dummy_interface => PSMILe_Neigh_nearx_sub_irr_real
00027 
00028       implicit none
00029 !
00030 ! !DEFINED PARAMETERS:
00031 !
00032 !  NREF_3D = Number of locations in 3d to be controlled
00033 !          = 4 ** ndim_3d
00034 !  NREF_2D = Number of locations in 2d to be controlled
00035 !          = 4 ** ndim_2d
00036 !
00037 !  lon   = Index of Longitudes in arrays "sin_values" and "cos_values"
00038 !  lat   = Index of Latitudes  in arrays "sin_values" and "cos_values"
00039 !  real_earth = Earth radius in meter
00040 !
00041       Integer, Parameter              :: nref_3d = 4 * 4 * 4
00042       Integer, Parameter              :: nref_2d = 4 * 4
00043       Integer, Parameter              :: lon = 1
00044       Integer, Parameter              :: lat = 2
00045       Integer, Parameter              :: maxlen = 64
00046 !
00047       Real, Parameter                 :: real_earth = 6400000.0
00048 !
00049       Real, Parameter                 :: tol = 1d-6 ! muss argument werden
00050       Real, Parameter                 :: eps = 1d-6
00051       Real, Parameter                 :: acosp1 =  1.0
00052       Real, Parameter                 :: acosm1 = -1.0
00053 !
00054 ! !INPUT PARAMETERS:
00055 !
00056       Integer,          Intent (In)   :: grid_id
00057 
00058 !     Info on the component in which the donor cells
00059 !     should be searched.
00060 
00061       Integer,          Intent (In)   :: nloc
00062 !
00063 !     Total number of locations to be transferred
00064 !
00065       Integer,          Intent (In)            :: coords_shape (2, ndim_3d)
00066 
00067 !     Dimension of coordinates (method) x_coords, ...
00068 
00069       Real, Intent (In)               :: x_coords(coords_shape(1,1): 
00070                                                   coords_shape(2,1), 
00071                                                   coords_shape(1,2): 
00072                                                   coords_shape(2,2))
00073       Real, Intent (In)               :: y_coords(coords_shape(1,1): 
00074                                                   coords_shape(2,1), 
00075                                                   coords_shape(1,2): 
00076                                                   coords_shape(2,2))
00077       Real, Intent (In)               :: z_coords(coords_shape(1,3): 
00078                                                   coords_shape(2,3))
00079 
00080 !     Coordinates of the method
00081 
00082       Integer,          Intent (In)   :: mask_shape (2, ndim_3d)
00083 
00084 !     Dimension of (method) mask array
00085 
00086       Logical,          Intent (In)   :: mask_array (mask_shape (1,1): 
00087                                                      mask_shape (2,1), 
00088                                                      mask_shape (1,2): 
00089                                                      mask_shape (2,2), 
00090                                                      mask_shape (1,3): 
00091                                                      mask_shape (2,3))
00092 !     Mask of the method
00093 
00094       Logical,          Intent (In)   :: mask_available
00095 
00096 !     Is mask specified in array "mask_array" ?
00097 !     mask_available = .false. : Mask is not available
00098 !                      .true.  : Mask is     available
00099 
00100       Integer,          Intent (In)   :: grid_valid_shape (2, ndim_3d)
00101 
00102 !     Specifies the valid block shape for the "ndim_3d"-dimensional block
00103 
00104       Real, Intent (In)               :: sin_values (grid_valid_shape(1,1): 
00105                                                      grid_valid_shape(2,1), 
00106                                                      grid_valid_shape(1,2): 
00107                                                      grid_valid_shape(2,2), 
00108                                                      2)
00109 !
00110 !     Sin values of Longitudes and Latitudes (x_coords, y_coords)
00111 !
00112       Real, Intent (In)               :: cos_values (grid_valid_shape(1,1): 
00113                                                      grid_valid_shape(2,1), 
00114                                                      grid_valid_shape(1,2): 
00115                                                      grid_valid_shape(2,2), 
00116                                                      2)
00117 !    
00118 !     Cos values of Longitudes and Latitudes (x_coords, y_coords)
00119 !
00120       Integer,          Intent (In)   :: search_mode
00121 !
00122 !     Specifies the search mode for nearest neigbours with
00123 !        search_mode = 3 : Full 3d-search
00124 !        search_mode = 2 : Search in 2d-hyperplane (1st 2 direction lon, lat)
00125 
00126       Integer,          Intent (In)   :: num_neigh
00127 !
00128 !     Last dimension of neighbors array "neighbors_3d" and
00129 !     number of neighbors to be searched.
00130 !
00131       Integer,          Intent (In)   :: jbeg, jend
00132 !
00133 !     Shape of input arrays
00134 !
00135       Integer,          Intent (In)   :: ijk (ndim_3d, jbeg:jend)
00136 !
00137 !     Coarse grid index on level nlev-2 (for dimensions specified 
00138 !     by search mode). Coarsening factor had to be 4.
00139 
00140       Real, Intent (In)               :: sin_search (jbeg:jend, lat)
00141 !
00142 !     Sin values of the points for which the nearest neighbours
00143 !     should be searched.
00144 !
00145       Real, Intent (In)               :: cos_search (jbeg:jend, lat)
00146 !
00147 !     Cos values of the points for which the nearest neighbours
00148 !     should be searched.
00149 !
00150       Real, Intent (In)               :: z_search (jbeg:jend)
00151 !
00152 !     Z values of the points for which the nearest neighbours
00153 !     should be searched.
00154 !
00155       Integer,          Intent (In)   :: width (ndim_3d)
00156 !
00157 ! !INPUT/OUTPUT PARAMETERS:
00158 !
00159       Type (Extra_search_info), Intent(InOut) :: extra_search
00160 !
00161 !     Number of locations where
00162 !       (*) required mask values were not true
00163 !
00164 ! !OUTPUT PARAMETERS:
00165 !
00166       Integer,          Intent (Out)  :: neighbors_3d (ndim_3d, nloc, num_neigh)
00167 
00168 !     Indices of neighbor locations (interpolation bases)
00169 !
00170       Integer,          Intent (Out)  :: ierror
00171 
00172 !     Returns the error code of PSMILE_Neigh_nearx_sub_irr_real;
00173 !             ierror = 0 : No error
00174 !             ierror > 0 : Severe error
00175 !
00176 ! !LOCAL VARIABLES
00177 !
00178 !     ... For locations controlled
00179 !
00180       Integer                         :: nrefv (2:ndim_3d)
00181       Integer                         :: dim1 (2)
00182       Logical                         :: global_search
00183       Real, Pointer                   :: dist_real (:, :)
00184 !
00185 !     ... (1d) Indices in (entire) data to be extra searched
00186 !
00187       Integer                         :: i, j, k, jpart
00188       Integer                         :: len, leni, lenj, lenk, lenij
00189 !
00190       Integer, Pointer                :: indices (:)
00191 !
00192 !     ... 3d Indices in local data to be extra searched
00193 !
00194       Integer                         :: ii, jj, kk
00195       Integer                         :: n, nref, nrefd
00196 !
00197       Integer                         :: ijkdst (ndim_3d, nref_3d)
00198       Integer                         :: ijkctl (ndim_3d, nref_3d)
00199       Integer                         :: irange (2, ndim_3d)
00200 !
00201 !     ... auxiliary arrays
00202 !
00203       Integer                         :: itemp (ndim_3d)
00204 !
00205 !     ... for mask values
00206 !
00207       Logical                         :: mask_dist (nref_3d)
00208       Logical                         :: mask_ind  (jbeg:jend)
00209 !
00210 !     ... for nearest neighbour control
00211 !
00212       Integer                         :: nmin (1)
00213       Integer                         :: nfound
00214 !
00215       Real                            :: real_huge
00216       Real                            :: distance (nref_3d), dist, fac, val
00217       Real                            :: dist2 (4), dist3 (2*2*2)
00218       Real                            :: val2 (4)
00219 
00220       Integer                         :: nlev
00221       Type (Extra_search_real)        :: arrays
00222       Type (Grid), Pointer            :: grid_info
00223       Type (Enddef_mg_real), Pointer :: my_arrays
00224 !
00225 !     ... for error handling
00226 !
00227       Integer, Parameter              :: nerrp = 2
00228       Integer                         :: ierrp (nerrp)
00229 !
00230 !
00231 ! !DESCRIPTION:
00232 !
00233 ! Subroutine "PSMILe_Neigh_nearx_sub_irr_real" searches the next "num_neigh"
00234 ! nearest neighbours on the method-grid (x_coords, y_coords, z_coords)
00235 ! for the extra indices specified in "extra_search%indices".
00236 !
00237 ! There are 2 different of search modes supported by the routine:
00238 ! search_mode = 3: The nearest neighbours are searched are searched
00239 !                  within the 3d region.
00240 ! search_mode = 2: The nearest neighbours are searched only in the
00241 !                  2d hyperplane (lon- and lat-direction).
00242 !
00243 ! Subroutine "PSMILe_Neigh_nearx_sub_irr_real" is designed for grids of
00244 ! of type "PRISM_Irrlonlat_regvrt".
00245 !
00246 ! !REVISION HISTORY:
00247 !
00248 !   Date      Programmer   Description
00249 ! ----------  ----------   -----------
00250 ! 17.02.05    H. Ritzdorf  created
00251 !
00252 !EOP
00253 !----------------------------------------------------------------------
00254 !
00255 !  $Id: psmile_neigh_nearx_sub_irr_real.F90 2687 2010-10-28 15:15:52Z coquart $
00256 !  $Author: coquart $
00257 !
00258    Character(len=len_cvs_string), save :: mycvs = 
00259        '$Id: psmile_neigh_nearx_sub_irr_real.F90 2687 2010-10-28 15:15:52Z coquart $'
00260 !
00261 !----------------------------------------------------------------------
00262 !
00263 !  Relative control indices 
00264 !      
00265 ! Schoener waere eine liste, die weniger sortierung nachher verlangt
00266 ! (dh. die nach den Summe der relativen Indices sortiert ist).
00267 ! Vielleicht sollte man immer annehmen, dass ijk in der "Mitte" liegt
00268 !
00269       data ((ijkctl (i, n), i=1,ndim_3d), n = 1,nref_3d) &
00270             /  0, 0, 0,   1, 0, 0,   2, 0, 0,   3, 0, 0, &
00271                0, 1, 0,   1, 1, 0,   2, 1, 0,   3, 1, 0, &
00272                0, 2, 0,   1, 2, 0,   2, 2, 0,   3, 2, 0, &
00273                0, 3, 0,   1, 3, 0,   2, 3, 0,   3, 3, 0, &
00274                0, 0, 1,   1, 0, 1,   2, 0, 1,   3, 0, 1, &
00275                0, 1, 1,   1, 1, 1,   2, 1, 1,   3, 1, 1, &
00276                0, 2, 1,   1, 2, 1,   2, 2, 1,   3, 2, 1, &
00277                0, 3, 1,   1, 3, 1,   2, 3, 1,   3, 3, 1, &
00278                0, 0, 2,   1, 0, 2,   2, 0, 2,   3, 0, 2, &
00279                0, 1, 2,   1, 1, 2,   2, 1, 2,   3, 1, 2, &
00280                0, 2, 2,   1, 2, 2,   2, 2, 2,   3, 2, 2, &
00281                0, 3, 2,   1, 3, 2,   2, 3, 2,   3, 3, 2, &
00282                0, 0, 3,   1, 0, 3,   2, 0, 3,   3, 0, 3, &
00283                0, 1, 3,   1, 1, 3,   2, 1, 3,   3, 1, 3, &
00284                0, 2, 3,   1, 2, 3,   2, 2, 3,   3, 2, 3, &
00285                0, 3, 3,   1, 3, 3,   2, 3, 3,   3, 3, 3/
00286 !
00287       data nrefv /nref_2d, nref_3d/
00288 !                            
00289 !----------------------------------------------------------------------
00290 !
00291 !  Initialization
00292 !
00293 !----------------------------------------------------------------------
00294 !
00295 #ifdef VERBOSE
00296       print 9990, trim(ch_id)
00297 
00298       call psmile_flushstd
00299 #endif /* VERBOSE */
00300 !
00301       ierror = 0
00302 !
00303       grid_info => Grids(grid_id)
00304       indices   => extra_search%indices
00305       global_search = extra_search%global_search
00306 !
00307       real_huge = huge (distance(1))
00308       mask_ind  = .true.
00309 !
00310 !===> Allocate vector to store the distances found if required
00311 !
00312       if (global_search) then
00313          dist_real => extra_search%dist_real
00314          dim1 (1) = 1
00315          dim1 (2) = extra_search%n_extra
00316       else
00317          dim1 (1) = jbeg
00318          dim1 (2) = jend
00319 !
00320          Allocate (dist_real (jbeg:jend, num_neigh), stat = ierror)
00321 
00322          if (ierror /= 0) then
00323             ierrp (1) = ierror
00324             ierrp (2) = num_neigh * (jend-jbeg+1)
00325 
00326             ierror = PRISM_Error_Alloc
00327             call psmile_error ( ierror, 'dist_real', ierrp, 2, &
00328         __FILE__, __LINE__ )
00329             return
00330          endif
00331       endif
00332 !
00333 #ifdef PRISM_ASERTION
00334       if (global_search) then
00335          if (.not. Associated (extra_search%dist_real)) then
00336             call psmile_assert (__FILE__, &
00337         __LINE__, 'extra_search%dist_real was not allocated')
00338          endif
00339       endif
00340 #endif
00341 
00342 !
00343 !===> Get number of reference points
00344 !
00345       nrefd = nrefv (search_mode)
00346 !
00347 !===> Compute distances for each point in (jbeg:jend)
00348 !
00349       do jpart = jbeg, jend, 5000
00350 
00351 !cdir vector loopcnt=5000
00352       do j = jpart, min (jend, jpart+5000-1)
00353          i = indices(j)
00354 !
00355 !===> ... Get standard range to be controlled
00356 !
00357          irange (1, :) = max (ijk(:, j),          grid_valid_shape (1, :))
00358          irange (2, :) = min (ijk(:, j)+width(:), grid_valid_shape (2, :))
00359 !
00360          nref = (irange (2,1) - irange (1,1) + 1) * &
00361                 (irange (2,2) - irange (1,2) + 1) * &
00362                 (irange (2,3) - irange (1,3) + 1)
00363 !
00364 #ifdef PRISM_ASSERTION
00365 !
00366          if (nref > nrefd) then
00367             print *, trim(ch_id), " nref, nredfd", nref, nrefd
00368             call psmile_assert (__FILE__, &
00369         __LINE__, 'nref > nrefd ')
00370          endif
00371 #endif
00372 !
00373 !===> ... Set indices to be controlled
00374 !
00375          if (nref == nrefd) then
00376                do n = 1, nrefd
00377                ijkdst (:, n) = ijk (:, j) + ijkctl (:, n)
00378                end do
00379          else
00380 ! 
00381             leni  =  irange (2, 1) - irange (1, 1) + 1
00382             lenij = (irange (2, 2) - irange (1, 2) + 1) * leni 
00383 !
00384                do kk = 1, irange (2,3)-irange(1,3) + 1
00385                n = (kk-1)*lenij
00386                   do jj = 1, irange (2,2)-irange(1,2) + 1
00387 
00388 !cdir vector
00389                      do ii = 1, leni
00390                      ijkdst (1, n+ii) = irange(1,1) + ii - 1
00391                      end do ! ii
00392 
00393                   ijkdst (2, n+1:n+leni) = irange (1,2) + jj - 1
00394                   n = n + leni
00395                   end do ! jj
00396 
00397                ijkdst (3, (kk-1)*lenij+1:kk*lenij) = irange (1,3) + kk - 1
00398                end do ! kk
00399          endif
00400 !
00401 !====> ... Get Mask values if necessary
00402 !
00403          if (mask_available) then
00404 !cdir vector
00405                do n = 1, nref
00406                mask_dist (n) = mask_array (ijkdst (1,n), ijkdst (2,n), &
00407                                            ijkdst (3,n))
00408                end do
00409 !
00410             n = count (mask_dist(1:nref))
00411 !
00412             if (n == 0) then
00413 !              no value available
00414 !
00415                nref = 0
00416                go to 10
00417             endif
00418 !
00419             if (n < nref) then
00420                n = 0
00421                   do ii = 1, nref
00422                   if (mask_dist (ii)) then
00423                       n = n + 1
00424                       if (n /= ii) ijkdst (:, n) = ijkdst (:, ii)
00425                   endif
00426                   end do
00427                nref = n
00428             endif
00429          endif
00430 !
00431 !===> ... Compute distances to points
00432 !
00433          fac = real_earth + z_search (j)
00434 !
00435 !cdir vector
00436             do n = 1, nref
00437             val   = (  sin_values(ijkdst (1,n),                              &
00438                                   ijkdst (2,n), lat) * sin_search(j, lat)    &
00439                     +  cos_values(ijkdst (1,n),                              &
00440                                   ijkdst (2,n), lat) * cos_search(j, lat)    &
00441                     * (cos_values(ijkdst (1,n),                              &
00442                                   ijkdst (2,n), lon) * cos_search(j, lon)    &
00443                       +sin_values(ijkdst (1,n),                              &
00444                                   ijkdst (2,n), lon) * sin_search(j, lon)) )
00445 #ifdef PRISM_ASSERTION
00446             if (val < acosm1 - eps .or. val > acosp1 + eps) then
00447                print *, i, j, val
00448                call psmile_assert (__FILE__, __LINE__, &
00449                                    'invalid value for acos')
00450             endif
00451 #endif
00452             val = min (acosp1, val)
00453             val = max (acosm1, val)
00454 
00455             dist = fac * acos (val)
00456 
00457             distance (n) = dist*dist +                                 &
00458                            ( z_search (j)-z_coords(ijkdst (3,n)))**2
00459 #ifdef DEBUGX
00460             if (i == 1387) then
00461                print *, 'dist, diff', dist, &
00462                         z_search (j)-z_coords(ijkdst (3,n))
00463             endif
00464 #endif
00465             end do ! n
00466 !
00467          nmin = minloc (distance(1:nref))
00468 #ifdef MINLOCFIX
00469          if (nmin(1).eq.0) nmin=1
00470 #endif /* MINLOCFIX */
00471 !
00472 #ifdef DEBUGX
00473          if (i == 1387) then
00474             print *, 'psmile_neigh_nearx_sub_irr_real: ictl =', i
00475             print *, 'ijkdst and distance:'
00476                do n = 1, nref
00477                print *, ijkdst (:, n), distance (n)
00478                end do
00479          endif
00480 #endif
00481 !
00482 !===> ... Special case: Minimal distance == 0
00483 !         Move other neighbours to "outside" of region.
00484 !
00485          if (distance(nmin(1)) <= tol) then
00486             neighbors_3d (:, i, 1) = ijkdst (:, nmin(1))
00487 !
00488                do n = 2, num_neigh
00489                neighbors_3d (:, i, n) = grid_valid_shape (1, :) - 1
00490                end do
00491 !
00492             dist_real (j, 1:num_neigh) = 0.0
00493 !
00494             cycle
00495          endif
00496 !
00497 !===> ... Sort distances (silly sort)
00498 !         Da muss noch etwas besseres her !
00499 !
00500 10       continue
00501 !
00502          nfound = min (num_neigh, nref)
00503 !
00504             do n = 1, nfound
00505 !
00506             nmin = minloc (distance(n:nref))
00507 #ifdef MINLOCFIX
00508             if (nmin(1).eq.0) nmin=1
00509 #endif /* MINLOCFIX */
00510 !
00511             if (nmin(1) /= 1) then
00512                jj = n + nmin (1) - 1
00513 !
00514                itemp  (:)    = ijkdst (:, n)
00515                ijkdst (:, n) = ijkdst (:, jj)
00516                ijkdst (:, jj) = itemp  (:)
00517 !
00518                dist = distance (n)
00519                distance (n) = distance (jj)
00520                distance (jj) = dist
00521             endif
00522             end do ! n
00523 !
00524 #ifdef PRISM_ASSERTION
00525             do n = 1, nfound-1
00526             if (distance(n) > distance (n+1)) exit
00527             end do
00528 !
00529          if (n <= nfound-1) then
00530             print *, 'n =' , n
00531             print *, 'distance (n)  ', distance (n)
00532             print *, 'distance (n+1)', distance (n+1)
00533             print *, 'distance', distance (1:nfound)
00534             call psmile_assert (__FILE__, __LINE__, &
00535                                 'incorrect sort')
00536          endif
00537 #endif
00538 !
00539 !===> ... End of local search;
00540 !         fill neighbors_3d and
00541 !         store distances for global search if necessary
00542 !
00543 ! Brauche ich die sqrt ?
00544 !
00545          dist_real (j, 1:nfound) = sqrt (distance (1:nfound))
00546          if (nfound < num_neigh) then
00547             dist_real (j, nfound+1:num_neigh) = real_huge
00548 
00549 ! das sollte man nicht machen (fuer nlev > 2)
00550 ! um mg suche einen startpunkt zu geben !
00551 !
00552                do n = nfound+1, num_neigh
00553                ijkdst (:, n) = grid_valid_shape (1, :) - 1
00554                end do
00555          endif
00556 !
00557          do n = 1, num_neigh
00558             neighbors_3d (:, i, n) = ijkdst (:, n)
00559          end do
00560 
00561 ! HR: Mein alter kommentar war falsch; man ist noch nicht fertig;
00562 ! Besser sollte man die lokale suche mit der originalen Zelle statt
00563 ! mit der groben Zelle machen.
00564 ! Trotzdem ist der jetzt gefundene Punkt schon eine gute
00565 ! Start-Loesung. Habe Derzeit keine Zeit weiter zu machen.
00566 !        mask_ind(j) = .false.
00567 
00568       end do ! j
00569       end do ! jpart
00570 
00571       !
00572       !----------------------------------------------------------------------
00573       !
00574       ! 3rd) Do a wider search for those targets that are still missing data
00575       !
00576       !----------------------------------------------------------------------
00577       !
00578       if ( count(mask_ind) > 0 ) then
00579 #define DEBUG_MG_EXTRA_SEARCH
00580 #ifdef DEBUG_MG_EXTRA_SEARCH
00581          !-------------------------------------------------------------------
00582          !     Use a brut force for search in other regions
00583          !     A replacement for PSMILe_MG_srch_nneigh_irr_real 
00584          !     as this requires further debugging
00585          !     Ref. ticket 47 with grid_medundemiT_cicle.nc as target
00586          !     and extra nneighbour search for bilinear interpolation. 
00587          !-------------------------------------------------------------------
00588          !
00589          call psmile_srch_nneigh_irreg2_real (grid_id,   &
00590               search_mode, mask_ind,                     &
00591               sin_values, cos_values,                    &
00592               grid_valid_shape,                          &
00593               z_coords, coords_shape,                    &
00594               neighbors_3d, nloc, num_neigh,             &
00595               sin_search, cos_search, z_search,          &
00596               dist_real, dim1, extra_search, jbeg, jend, &
00597               mask_array, mask_shape, mask_available,    &
00598               ierror)
00599 #else
00600          !
00601          !----------------------------------------------------------------------
00602          !     Use multigrid info for search in other regions
00603          !
00604          !     What about points in boundary cells?
00605          !     For those we have to apply the additional search as well.
00606          !     corresponding to mask == .true. ?!!!!
00607          !----------------------------------------------------------------------
00608          !         
00609          if ( grid_info%nlev > 2 ) then
00610             !
00611             !===> Allocate memory and calculate distances on the coarsest level
00612             !     to begin the search for all points.
00613             !
00614             nlev = max(grid_info%nlev-3,2)
00615             !
00616             leni = grid_info%mg_infos(nlev)%levdim(1) + 1
00617             lenj = grid_info%mg_infos(nlev)%levdim(2) + 1
00618             lenk = grid_info%mg_infos(nlev)%levdim(3) + 1
00619 
00620             len  = leni*lenj*lenk
00621 
00622             ii = 0
00623 
00624             Allocate(arrays%radius(leni*lenj*lenk), STAT=jj); ii = ii + jj
00625 
00626             do kk = 1, 4
00627                Allocate(arrays%sin_ccorner_lon(kk)%vector(len), &
00628                         arrays%cos_ccorner_lon(kk)%vector(len), &
00629                         arrays%sin_ccorner_lat(kk)%vector(len), &
00630                         arrays%cos_ccorner_lat(kk)%vector(len), STAT=jj); ii = ii + jj
00631             enddo
00632 
00633             Allocate(arrays%sin_cmidp_lon%vector(len), &
00634                      arrays%cos_cmidp_lon%vector(len), &
00635                      arrays%sin_cmidp_lat%vector(len), &
00636                      arrays%cos_cmidp_lat%vector(len), STAT=jj); ii = ii + jj
00637 
00638             Allocate(arrays%sin_fmidp_lon%vector(maxlen), &
00639                      arrays%cos_fmidp_lon%vector(maxlen), &
00640                      arrays%sin_fmidp_lat%vector(maxlen), &
00641                      arrays%cos_fmidp_lat%vector(maxlen), STAT=jj); ii = ii + jj
00642 
00643             if ( ii /= 0 ) then
00644                ierrp (1) = ierror
00645                ierrp (2) = ii
00646 
00647                ierror = PRISM_Error_Alloc
00648                call psmile_error ( ierror, 'arrays%...%vector', ierrp, 2, &
00649                     __FILE__, __LINE__ )
00650                return
00651 
00652             endif
00653 
00654             my_arrays => grid_info%mg_infos(nlev)%real_arrays
00655 
00656             arrays%sin_ccorner_lon(1)%vector(1:len) = sin(my_arrays%chmin(1)%vector(1:len)*real_deg2rad)
00657             arrays%cos_ccorner_lon(1)%vector(1:len) = cos(my_arrays%chmin(1)%vector(1:len)*real_deg2rad)
00658             arrays%sin_ccorner_lat(1)%vector(1:len) = sin(my_arrays%chmin(2)%vector(1:len)*real_deg2rad)
00659             arrays%cos_ccorner_lat(1)%vector(1:len) = cos(my_arrays%chmin(2)%vector(1:len)*real_deg2rad)
00660 
00661             arrays%sin_ccorner_lon(2)%vector(1:len) = sin(my_arrays%chmin(1)%vector(1:len)*real_deg2rad)
00662             arrays%cos_ccorner_lon(2)%vector(1:len) = cos(my_arrays%chmin(1)%vector(1:len)*real_deg2rad)
00663             arrays%sin_ccorner_lat(2)%vector(1:len) = sin(my_arrays%chmax(2)%vector(1:len)*real_deg2rad)
00664             arrays%cos_ccorner_lat(2)%vector(1:len) = cos(my_arrays%chmax(2)%vector(1:len)*real_deg2rad)
00665 
00666             arrays%sin_ccorner_lon(3)%vector(1:len) = sin(my_arrays%chmax(1)%vector(1:len)*real_deg2rad)
00667             arrays%cos_ccorner_lon(3)%vector(1:len) = cos(my_arrays%chmax(1)%vector(1:len)*real_deg2rad)
00668             arrays%sin_ccorner_lat(3)%vector(1:len) = sin(my_arrays%chmax(2)%vector(1:len)*real_deg2rad)
00669             arrays%cos_ccorner_lat(3)%vector(1:len) = cos(my_arrays%chmax(2)%vector(1:len)*real_deg2rad)
00670 
00671             arrays%sin_ccorner_lon(4)%vector(1:len) = sin(my_arrays%chmax(1)%vector(1:len)*real_deg2rad)
00672             arrays%cos_ccorner_lon(4)%vector(1:len) = cos(my_arrays%chmax(1)%vector(1:len)*real_deg2rad)
00673             arrays%sin_ccorner_lat(4)%vector(1:len) = sin(my_arrays%chmin(2)%vector(1:len)*real_deg2rad)
00674             arrays%cos_ccorner_lat(4)%vector(1:len) = cos(my_arrays%chmin(2)%vector(1:len)*real_deg2rad)
00675 
00676             arrays%sin_cmidp_lon%vector(1:len) = sin(my_arrays%midp(1)%vector(1:len)*real_deg2rad)
00677             arrays%cos_cmidp_lon%vector(1:len) = cos(my_arrays%midp(1)%vector(1:len)*real_deg2rad)
00678             arrays%sin_cmidp_lat%vector(1:len) = sin(my_arrays%midp(2)%vector(1:len)*real_deg2rad)
00679             arrays%cos_cmidp_lat%vector(1:len) = cos(my_arrays%midp(2)%vector(1:len)*real_deg2rad)
00680 
00681             n = 0
00682 
00683             if ( search_mode == 2 ) then
00684                !
00685                !===> ... 2d search mode
00686                !
00687                do k = 1, lenk
00688                   fac = real_earth + my_arrays%midp(3)%vector(k)
00689                   !
00690                   do j = 1, lenj
00691                      !cdir vector
00692                      do i = 1, leni
00693                         n = n + 1
00694 
00695                         do ii = 1, 4
00696                            val2(ii) = ( arrays%sin_ccorner_lat(ii)%vector(n) *  &
00697                                         arrays%sin_cmidp_lat%vector(n)          &
00698                                       + arrays%cos_ccorner_lat(ii)%vector(n) *  &
00699                                         arrays%cos_cmidp_lat%vector(n)          &
00700                                       *(arrays%cos_ccorner_lon(ii)%vector(n) *  &
00701                                         arrays%cos_cmidp_lon%vector(n)          &
00702                                       + arrays%sin_ccorner_lon(ii)%vector(n) *  &
00703                                         arrays%sin_cmidp_lon%vector(n)) )
00704                            val2(ii) = min (acosp1, val2(ii))
00705                            val2(ii) = max (acosm1, val2(ii))
00706 
00707                         end do
00708 
00709                         dist2 = fac * acos (val2)
00710                         dist2 = dist2 * dist2
00711 
00712                         arrays%radius(n) = maxval (dist2)
00713                      enddo ! i
00714                   enddo
00715                enddo ! k
00716 
00717             else if ( search_mode == 3 ) then
00718                !
00719                !===> ... 3d search mode
00720                !
00721                do k = 1, lenk
00722                   fac = real_earth + my_arrays%midp(3)%vector(k)
00723                   !
00724                   do j = 1, lenj
00725                      !cdir vector
00726                      do i = 1, leni
00727                         n = n + 1
00728 
00729                         do ii = 1, 4
00730                            val2(ii) = ( arrays%sin_ccorner_lat(ii)%vector(n) * &
00731                                         arrays%sin_cmidp_lat%vector(n)         &
00732                                       + arrays%cos_ccorner_lat(ii)%vector(n) * &
00733                                         arrays%cos_cmidp_lat%vector(n)         &
00734                                      * (arrays%cos_ccorner_lon(ii)%vector(n) * &
00735                                         arrays%cos_cmidp_lon%vector(n)         &
00736                                       + arrays%sin_ccorner_lon(ii)%vector(n) * &
00737                                         arrays%sin_cmidp_lon%vector(n)) )
00738                            val2(ii) = min (acosp1, val2(ii))
00739                            val2(ii) = max (acosm1, val2(ii))
00740                         end do
00741 
00742                         dist2 = fac * acos (val2)
00743                         dist2 = dist2 * dist2
00744                         !
00745                         dist3(1:4) = dist2 + (my_arrays%midp (3)%vector(k) - &
00746                                               my_arrays%chmin(3)%vector(k))**2
00747 
00748                         dist3(5:8) = dist2 + (my_arrays%midp (3)%vector(k) - &
00749                                               my_arrays%chmax(3)%vector(k))**2
00750 
00751                         arrays%radius(n) = maxval(dist3)
00752 
00753                      enddo ! i
00754                   enddo
00755                enddo ! k
00756             endif
00757             !
00758             ! werden die sqrt's wirklich gebraucht !?!?!
00759             ! Sehe ich nicht. a < b => sqrt (a) < sqrt (b)
00760             !
00761             arrays%radius(:) = sqrt (arrays%radius(:))
00762             !
00763             !===> ... Multigrid search
00764             !
00765             call psmile_mg_srch_nneigh_irr_real (grid_id,   &
00766                  arrays, search_mode, nref_3d,              &
00767                  sin_values, cos_values, grid_valid_shape,  &
00768                  z_coords, coords_shape,                    &
00769                  neighbors_3d, nloc, num_neigh,             &
00770                  sin_search, cos_search, z_search,          & 
00771                  dist_real, dim1, indices, jbeg, jend,      &
00772                  mask_ind,                                  &
00773                  mask_array, mask_shape, mask_available,    &
00774                  tol, ierror)
00775             if (ierror > 0) return
00776             !
00777             !===> ... Deallocate memory
00778             !
00779             Deallocate(arrays%sin_fmidp_lon%vector, arrays%cos_fmidp_lon%vector, &
00780                        arrays%sin_fmidp_lat%vector, arrays%cos_fmidp_lat%vector)
00781 
00782             Deallocate(arrays%sin_cmidp_lon%vector, arrays%cos_cmidp_lon%vector, &
00783                        arrays%sin_cmidp_lat%vector, arrays%cos_cmidp_lat%vector)
00784 
00785             do kk = 1, 4
00786                Deallocate(arrays%sin_ccorner_lon(kk)%vector, &
00787                           arrays%cos_ccorner_lon(kk)%vector, &
00788                           arrays%sin_ccorner_lat(kk)%vector, &
00789                           arrays%cos_ccorner_lat(kk)%vector)
00790             end do
00791 
00792             Deallocate(arrays%radius)
00793 
00794          endif ! grid_info%nlev > 2
00795 #endif
00796       endif ! count(mask_ind) > 0
00797 
00798       if (.not. global_search) Deallocate (dist_real)
00799 !
00800 !===> All done
00801 !
00802 #ifdef VERBOSE
00803       print 9980, trim(ch_id), ierror
00804 
00805       call psmile_flushstd
00806 #endif /* VERBOSE */
00807 !
00808 !  Formats:
00809 !
00810 9990 format (1x, a, ': psmile_neigh_nearx_sub_irr_real')
00811 9980 format (1x, a, ': psmile_neigh_nearx_sub_irr_real: eof, ierror =', i3)
00812 
00813       end subroutine PSMILe_Neigh_nearx_sub_irr_real

Generated on 18 Mar 2011 for Oasis4 by  doxygen 1.6.1