psmile_mg_method_gauss2_dble.F90

Go to the documentation of this file.
00001 !-----------------------------------------------------------------------
00002 ! Copyright 2006-2010, NEC Europe Ltd., London, UK.
00003 ! Copyright 2011, DKRZ, Hamburg, Germany.
00004 ! All rights reserved. Use is subject to OASIS4 license terms.
00005 !-----------------------------------------------------------------------
00006 !BOP
00007 !
00008 ! !ROUTINE: psmile_mg_method_gauss2_dble
00009 !
00010 ! !INTERFACE:
00011       subroutine psmile_mg_method_gauss2_dble (method_id, search_range,     &
00012                                                tgt_shape, tgt_coords_x,     &
00013                                                tgt_coords_y, loc_fnd_shape, &
00014                                                found, loc, virtual_cell,    &
00015                                                ierror)
00016 !
00017 ! !USES:
00018 !
00019       use PRISM_constants
00020       use psmile, dummy => psmile_mg_method_gauss2_dble
00021       use psmile_geometry, only : point_is_in_quadrangle
00022       use psmile_grid, only : common_grid_range, psmile_transform_cell_cyclic
00023       use psmile_grid_reduced_gauss
00024 #ifdef DEBUG_TRACE
00025       use psmile_debug_trace
00026 #endif
00027 
00028       implicit none
00029 !
00030 ! !INPUT PARAMETERS:
00031 !
00032       integer, intent (in)            :: method_id
00033 !
00034       integer, intent (in)            :: search_range (2, ndim_3d)
00035 
00036 !
00037       integer, intent (in)            :: loc_fnd_shape (2, ndim_3d)
00038 
00039 !     Dimension of loc and found
00040 
00041       integer, intent (in)            :: tgt_shape (2, ndim_3d)
00042 
00043 !     Dimension of coordinate arrays "coord1", "coord2"
00044 !     which contain the coordinates to be searched.
00045 !
00046       double precision, intent (in)   :: tgt_coords_x (tgt_shape(1,1):tgt_shape(2,1),  
00047                                                        tgt_shape(1,2):tgt_shape(2,2),  
00048                                                        tgt_shape(1,3):tgt_shape(2,3)), 
00049                                          tgt_coords_y (tgt_shape(1,1):tgt_shape(2,1),  
00050                                                        tgt_shape(1,2):tgt_shape(2,2),  
00051                                                        tgt_shape(1,3):tgt_shape(2,3))
00052 
00053 !     Coordinates to be searched
00054 !
00055 ! !INPUT/OUTPUT PARAMETERS:
00056 !
00057       integer, intent (inout)         :: found (loc_fnd_shape(1,1):loc_fnd_shape(2,1), 
00058                                                 loc_fnd_shape(1,2):loc_fnd_shape(2,2), 
00059                                                 loc_fnd_shape(1,3):loc_fnd_shape(2,3))
00060 
00061 !     Finest level number on which a grid cell was found for point i,j,k.
00062 !     Input :
00063 !     Level number < -1: Point was not found and
00064 !                        and last level number was (-found(i,j,k))
00065 !     Level number = -(nlev+1): Never found
00066 !     Output :
00067 !     found(i,j,k) = +1: Point (i,j,k) is located on a point
00068 !                        of the method grid.
00069 !     found(i,j,k) = -1: Point (i,j,k) is located in a cell
00070 !                        of the method grid.
00071 !     found(,j,k) = -(nlev+2): Not located in the method grid.
00072 
00073       integer, intent (inout)         :: loc   (loc_fnd_shape(1,1):loc_fnd_shape(2,1), 
00074                                                 loc_fnd_shape(1,2):loc_fnd_shape(2,2), 
00075                                                 loc_fnd_shape(1,3):loc_fnd_shape(2,3))
00076 !
00077 !     Indices of the grid cell in which the point was found.
00078 !     The indices are relative to "shape".
00079 !     Note: The indices are indices in the Gauss Reduced Grid.
00080 !
00081 ! !OUTPUT PARAMETERS:
00082 !
00083       integer, intent (out)           :: virtual_cell (loc_fnd_shape(1,1):loc_fnd_shape(2,1), 
00084                                                        loc_fnd_shape(1,2):loc_fnd_shape(2,2), 
00085                                                        loc_fnd_shape(1,3):loc_fnd_shape(2,3))
00086 
00087 !     Is the searched point (i,j,k) located in a virtual cell ?
00088 !     virtual_cell (i,j,k) returns a code for the location in
00089 !     the virtual cell (outside the local method grid)
00090 !     virtual_cell (i,j,k) = 0 : Not located in a virtual cell
00091 !     virtual_cell (i,j,k) > 0 :     Located in a virtual cell
00092 !                          = 1 : (-1,-1) direction
00093 !                          = 2 : ( 0,-1) direction
00094 !                          = 3 : ( 1,-1) direction
00095 !                          = 4 : (-1, 0) direction
00096 !                          = 6 : ( 1, 0) direction
00097 !                          = 7 : (-1, 1) direction
00098 !                          = 8 : ( 0, 1) direction
00099 !                          = 9 : ( 1, 1) direction
00100 
00101       integer, intent (out)           :: ierror
00102 
00103 !     Returns the error code of psmile_mg_method_gauss2_dble;
00104 !             ierror = 0 : No error
00105 !             ierror > 0 : Severe error
00106 !
00107 ! !DEFINED PARAMETERS:
00108 !
00109 !  val_coupler = Code for locations which should to be transferred
00110 !                to the coupler process.
00111 !
00112       integer, parameter              :: val_coupler = -1
00113 !
00114 ! !LOCAL VARIABLES
00115 !
00116       integer, pointer                :: local_1d_stencil_lookup(:,:)
00117 
00118       integer                         :: i, j, k, n, n_end
00119 
00120       integer                         :: not_found
00121 
00122       double precision, pointer       :: src_coords_x(:), 
00123                                          src_coords_y(:) ! coordinates of the method points
00124                                                          ! these can also contain data of
00125                                                          ! remote points
00126 
00127       integer, pointer                :: local_coords_shape(:,:)
00128       integer                         :: num_local_points, num_remote_points, num_global_lats
00129 
00130       integer, pointer                :: curr_stencil(:)
00131       integer                         :: curr_stencil_idx
00132       integer                         :: curr_3d_base_idx(ndim_3d)
00133       type(point_dble)                :: method_cell (4), point
00134       double precision                :: grid_extent
00135       integer                         :: grid_id
00136 
00137       integer, allocatable            :: loc_3d(:,:,:,:)
00138 
00139       integer, parameter              :: n_to_stencil_base_idx(9) = (/1,2,3, 5,6,7, 
00140                                                                       9,10,11/)
00141       integer, parameter              :: stencil_idx_to_virtual_cell(16) = (/1,2,3,-1, 
00142                                                                              4,5,6,-1, 
00143                                                                              7,8,9,-1, 
00144                                                                              -1,-1,-1,-1/)
00145 !
00146 #ifdef DEBUG_TRACE
00147 !
00148 !     ... for debugging
00149 !
00150       logical                         :: debug_trace
00151       type(point_dble)                :: debug_point
00152       character (len=*), parameter    :: out_prefix = "ictl psmile_mg_method_gauss2_dble:"
00153 #endif
00154 !
00155 ! !DESCRIPTION:
00156 !
00157 ! Subroutine "psmile_mg_method_gauss2_dble" gets a list of target points and the matching
00158 ! local source cell (grid cells). The routine searches for corresponding method cells. If
00159 ! a found method cell is not on the local process, it is indicated through the virtual_cell
00160 ! array
00161 !
00162 !
00163 ! !REVISION HISTORY:
00164 !
00165 !   Date      Programmer   Description
00166 ! ----------  ----------   -----------
00167 ! 03.07.05    H. Ritzdorf  created
00168 ! 06.01.11    M. Hanke     rewritten
00169 ! 21.02.11    M. Hanke     introduced module psmile_grid_reduced_gauss
00170 !
00171 !EOP
00172 !----------------------------------------------------------------------
00173 !
00174 !  $Id: psmile_mg_method_gauss2_dble.F90 3011 2011-03-10 17:50:02Z hanke $
00175 !  $Author: hanke $
00176 !
00177    Character(len=len_cvs_string), save :: mycvs = 
00178        '$Id: psmile_mg_method_gauss2_dble.F90 3011 2011-03-10 17:50:02Z hanke $'
00179 
00180 !----------------------------------------------------------------------
00181 #ifdef VERBOSE
00182       print 9990, trim(ch_id)
00183 
00184       call psmile_flushstd
00185 #endif /* VERBOSE */
00186 !
00187 !  Initialization
00188 !
00189       ierror = 0
00190 
00191       grid_id = methods(method_id)%grid_id
00192       local_1d_stencil_lookup => &
00193          grids(grid_id)%reduced_gauss_data%local_1d_stencil_lookup
00194       num_global_lats = &
00195          size (grids(grid_id)%reduced_gauss_data%nbr_points_per_lat)
00196       not_found = - (grids(grid_id)%nlev + 2)
00197       local_coords_shape => Methods(method_id)%coords_pointer%coords_shape
00198 
00199       ! get the number of remote point that have a local copy
00200       num_local_points  = local_coords_shape(2,1) - local_coords_shape(1,1)
00201       if (associated (grids(grid_id)%remote_index)) then
00202          num_remote_points = size (grids(grid_id)%remote_index)
00203       else
00204          num_remote_points = 0
00205       endif
00206 
00207       ! set the local source coordinate pointer
00208       ! if there are no remote points that have local copy
00209       if (num_remote_points <= 0) then
00210 
00211          src_coords_x => Methods(method_id)%coords_pointer%coords_dble(1)%vector
00212          src_coords_y => Methods(method_id)%coords_pointer%coords_dble(2)%vector
00213       else
00214 
00215          ! allocate memory of an array that contains the local and remote source coordinate  data
00216          allocate (src_coords_x(local_coords_shape(1,1):local_coords_shape(2,1)+num_remote_points), &
00217                    src_coords_y(local_coords_shape(1,1):local_coords_shape(2,1)+num_remote_points), &
00218                    stat = ierror)
00219 
00220          if ( ierror > 0 ) then
00221             call psmile_error (PRISM_Error_Alloc, 'src_coords_x and src_coords_y', (/ierror, &
00222                                2*(local_coords_shape(2,1)-local_coords_shape(1,1)+1+num_remote_points)/), &
00223                                2, __FILE__, __LINE__ )
00224             return
00225          endif
00226 
00227          src_coords_x(local_coords_shape(1,1):local_coords_shape(2,1)) = &
00228             Methods(method_id)%coords_pointer%coords_dble(1)%vector
00229          src_coords_y(local_coords_shape(1,1):local_coords_shape(2,1)) = &
00230             Methods(method_id)%coords_pointer%coords_dble(2)%vector
00231 
00232          src_coords_x(local_coords_shape(2,1)+1:local_coords_shape(2,1)+num_remote_points) = &
00233              Methods(method_id)%gauss2_dble(1)%vector
00234          src_coords_y(local_coords_shape(2,1)+1:local_coords_shape(2,1)+num_remote_points) = &
00235              Methods(method_id)%gauss2_dble(2)%vector
00236       endif ! (num_remote_points == 0)
00237 
00238       ! initialise with default value (no virtual cell)
00239       virtual_cell(:,:,:) = 0
00240 
00241       ! this should normally be 360
00242       grid_extent = common_grid_range(2,1) - common_grid_range(1,1)
00243       
00244       ! some optimisation
00245       allocate (loc_3d(ndim_3d, loc_fnd_shape(1,1):loc_fnd_shape(2,1), &
00246                                 loc_fnd_shape(1,2):loc_fnd_shape(2,2), &
00247                                 loc_fnd_shape(1,3):loc_fnd_shape(2,3)))
00248 
00249       loc_3d(:,:,:,:) = reshape (psmile_gauss_local_1d_to_3d(grid_id,                     &
00250                                                              reshape(loc, (/size(loc)/)), &
00251                                                              size(loc)),                  &
00252                                  (/ndim_3d, size(loc,1), size(loc,2), size(loc,3)/))
00253       ! for all tgt points
00254       do i = search_range(1, 1), search_range(2,1)
00255          do j = search_range(1, 2), search_range(2,2)
00256             do k = search_range(1, 3), search_range(2,3)
00257 #ifdef DEBUG_TRACE
00258                if (i == ictl_ind(1) .and. j == ictl_ind(2)) then
00259                   print *, out_prefix, ' ictl_ind', &
00260                      ictl_ind (1:ndim_2d), ' old found = ', &
00261                      found (ictl_ind(1),ictl_ind(2),search_range(1,3)), &
00262                      ', old loc =', loc   (ictl_ind(1),ictl_ind(2),search_range(1,3))
00263                   debug_trace = .true.
00264                else
00265                   debug_trace = .false.
00266                endif
00267 #endif
00268                ! if we have a valid location for the given point
00269                if (found (i,j,k) == 1) then
00270 
00271                   point%x = tgt_coords_x (i,j,k)
00272                   point%y = tgt_coords_y (i,j,k)
00273 
00274                   curr_stencil => local_1d_stencil_lookup(:, loc (i,j,k))
00275                   curr_3d_base_idx(:) = loc_3d (:,i,j,k)
00276 
00277 #ifdef DEBUG_TRACE
00278                   if (debug_trace) then
00279                      print '(2(1x,a),2f8.2)', out_prefix, 'point to be searched: ', point
00280                      debug_point = point
00281                   endif
00282 #endif
00283 
00284                   ! skip the southern points if the base point is already in the most southern latitude
00285                   if (curr_3d_base_idx(2) == 1) then
00286                      n = 4
00287                   else
00288                      n = 1
00289                   endif
00290 
00291                   ! skip the northern points if we are 1 row below the most northern row
00292                   if (curr_3d_base_idx(2) == num_global_lats - 1) then
00293                      n_end = 6
00294                   else
00295                      n_end = 9
00296                   endif
00297 
00298                   ! for all points in the current stencil of the src point associated with the current tgt point
00299                   do n = n, n_end
00300 
00301                      curr_stencil_idx = n_to_stencil_base_idx(n)
00302 
00303                      ! generate method cell
00304                      method_cell = get_method_cell (curr_stencil_idx, curr_stencil, &
00305                                                     curr_3d_base_idx(2))
00306 
00307                      ! move the point into the x range of the cell
00308                      do while (point%x < minval (method_cell(:)%x))
00309                         point%x = point%x + grid_extent
00310                      enddo
00311                      do while (point%x > maxval (method_cell(:)%x))
00312                         point%x = point%x - grid_extent
00313                      enddo
00314 
00315 #ifdef DEBUG_TRACE
00316                      if (debug_trace) then
00317                         if (debug_point%x /= point%x) then
00318                            print '(2(1x,a),/,2f8.2)', out_prefix, &
00319                                  "point coordinates were adjusted to method cell range:", point
00320                            debug_point = point
00321                         endif
00322                      endif
00323 #endif
00324 
00325                      ! check point in cell
00326                      if (point_is_in_quadrangle (point, method_cell)) then
00327 
00328                         found (i,j,k) = val_coupler
00329                         exit
00330                      endif
00331                   enddo ! n
00332 
00333                   ! if a suitable method cell was found
00334                   if (found (i,j,k) == val_coupler) then
00335 #ifdef DEBUG_TRACE
00336                      if (debug_trace) then
00337                         print *, out_prefix, ' found matching cell'
00338                      endif
00339 #endif
00340                      ! if the point is located in the local grid
00341                      if (curr_stencil(curr_stencil_idx) <= local_coords_shape(2,1)) then
00342 
00343                         loc (i,j,k) = curr_stencil(curr_stencil_idx)
00344 #ifdef DEBUG_TRACE
00345                         if (debug_trace) then
00346                            print *, out_prefix, ' new loc =', loc (i,j,k)
00347                         endif
00348 #endif
00349                      else
00350 
00351                         virtual_cell (i,j,k) = &
00352                            stencil_idx_to_virtual_cell(curr_stencil_idx)
00353 #ifdef DEBUG_TRACE
00354                         if (debug_trace) then
00355                            print *, out_prefix, ' cell is virtual cell at stencil idx', &
00356                                     curr_stencil_idx, 'virt. cell idx', virtual_cell (i,j,k)
00357                         endif
00358 #endif
00359                      endif ! (loc (i,j,k) > local_coords_shape(2,1))
00360                   else
00361                      found (i,j,k) = not_found
00362                   endif ! (found (i,j,k) == val_coupler)
00363                endif ! (found (i,j,k) == 1)
00364             enddo ! k = search_range(1, 3), search_range(2,3)
00365          enddo ! j = search_range(1, 2), search_range(2,2)
00366       enddo ! i = search_range(1, 1), search_range(2,1)
00367 
00368       ! free memory if necessary
00369       deallocate (loc_3d)
00370       if (num_remote_points > 0) deallocate (src_coords_x, src_coords_y)
00371 
00372 #ifdef VERBOSE
00373       print 9980, trim(ch_id)
00374 
00375       call psmile_flushstd
00376 #endif /* VERBOSE */
00377 !
00378 !  Formats:
00379 !
00380 9990 format (1x, a, ': psmile_mg_method_gauss2_dble:')
00381 9980 format (1x, a, ': psmile_mg_method_gauss2_dble: eof')
00382 
00383       contains
00384 
00385 !-----------------------------------------------------------------------------------
00386 
00387          ! this function generates a method cell based on the point index in the
00388          ! given stencil array of the lower left corner of the cell
00389          function get_method_cell(idx, stencil, g_latitude_idx)
00390 
00391             integer, intent (in) :: idx, stencil(16), g_latitude_idx
00392 
00393             type (point_dble)    :: get_method_cell(4)
00394 
00395             type (point_dble)    :: method_cell(4)
00396             integer, parameter   :: neighbours(3,16) = 
00397                                        reshape ((/ 2, 6, 5,  3, 7, 6,  4, 8, 7, -1,-1,-1,   
00398                                                    6,10, 9,  7,11,10,  8,12,11, -1,-1,-1,   
00399                                                   10,14,13, 11,15,14, 12,16,15, -1,-1,-1,   
00400                                                   -1,-1,-1, -1,-1,-1, -1,-1,-1, -1,-1,-1/), 
00401                                                 (/3,16/)) ! (see definition of the stencil in
00402                                                           !  psmile_grid_reduced_gauss)
00403             integer, parameter   :: latitude_off(16) = (/-1,-1,-1, 0, 
00404                                                           0, 0, 0, 0, 
00405                                                           1, 1, 1, 0, 
00406                                                           0, 0, 0, 0/)
00407 
00408 #ifdef DEBUG_TRACE
00409             if (debug_trace) then
00410                print *, out_prefix, ' stencil     =', stencil
00411                print *, out_prefix, ' stencil idx =', idx
00412                print *, out_prefix, ' generating method cell with indices:', &
00413                         stencil(idx), stencil(neighbours(:,idx))
00414             endif
00415 #endif
00416             ! get method point of current point
00417             method_cell(1)%x = src_coords_x(stencil(idx))
00418 
00419             ! get method point of right neighbour
00420             ! (see definition of stencil in psmile_grid_reduced_gauss)
00421             method_cell(2)%x = src_coords_x(stencil(neighbours(1,idx)))
00422 
00423             ! get method point of right-upper neighbour
00424             method_cell(3)%x = src_coords_x(stencil(neighbours(2,idx)))
00425 
00426             ! get method point of upper neighbour
00427             method_cell(4)%x = src_coords_x(stencil(neighbours(3,idx)))
00428 
00429             ! method cell is extended to the pole
00430             if (g_latitude_idx + latitude_off(idx) == 1) then
00431 
00432                method_cell(1:2)%y = dsign (90.d0, src_coords_y(stencil(idx)))
00433 
00434 #ifdef DEBUG_TRACE
00435                if (debug_trace) then
00436                   print *, out_prefix, ' extending method cell to pole'
00437                endif
00438 #endif
00439             else
00440 
00441                method_cell(1)%y = src_coords_y(stencil(idx))
00442                method_cell(2)%y = src_coords_y(stencil(neighbours(1,idx)))
00443             endif
00444 
00445             ! method cell is extended to the pole
00446             if (g_latitude_idx + latitude_off(idx) == num_global_lats - 1) then
00447 
00448                method_cell(3:4)%y = dsign (90.d0, src_coords_y(stencil(idx)))
00449 
00450 #ifdef DEBUG_TRACE
00451                if (debug_trace) then
00452                   print *, out_prefix, ' extending method cell to pole'
00453                endif
00454 #endif
00455             else
00456 
00457                method_cell(3)%y = src_coords_y(stencil(neighbours(2,idx)))
00458                method_cell(4)%y = src_coords_y(stencil(neighbours(3,idx)))
00459             endif
00460 
00461 #ifdef DEBUG_TRACE
00462             if (debug_trace) then
00463                print "(2(1x,a),4(/,2f8.2))", out_prefix, 'generated method cell:', &
00464                                              method_cell
00465             endif
00466 #endif
00467 
00468             ! apply cyclic coordinate handling
00469             call psmile_transform_cell_cyclic(method_cell(:)%x, grid_extent, ierror)
00470 
00471 #ifdef DEBUG_TRACE
00472             if (debug_trace) then
00473                print "(2(1x,a),4(/,2f8.2))", &
00474                      out_prefix, 'after cyclic transformation:', method_cell
00475             endif
00476 #endif
00477 
00478             get_method_cell = method_cell
00479 
00480          end function get_method_cell
00481 
00482       end subroutine psmile_mg_method_gauss2_dble

Generated on 18 Mar 2011 for Oasis4 by  doxygen 1.6.1