psmile_bbcells_pole_dble.F90

Go to the documentation of this file.
00001 !-----------------------------------------------------------------------
00002 ! Copyright 2010, DKRZ, Hamburg, Germany.
00003 ! All rights reserved. Use is subject to OASIS4 license terms.
00004 !-----------------------------------------------------------------------
00005 !BOP
00006 !
00007 ! !ROUTINE: psmile_bbcells_pole_dble
00008 !
00009 ! !INTERFACE:
00010 
00011       subroutine psmile_bbcells_pole_dble (              &
00012                      coords_shape, coords_x, coords_y,   &
00013                      corner_shape, sub_range,            &
00014                      chmin_x, chmax_x, chmin_y, chmax_y, &
00015                      midp_x, midp_y, pole_array, period, &
00016                      ierror)
00017 !
00018 ! !USES:
00019 !
00020       use psmile, dummy_interface => psmile_bbcells_pole_dble
00021       use psmile_reallocate
00022       use psmile_common, only : ndim_2d, ndim_3d
00023       use psmile_grid, only : psmile_transform_cell_cyclic
00024       use prism, only : prism_undefined
00025 
00026       implicit none
00027 !
00028 ! !INPUT PARAMETERS:
00029 !
00030       integer,           intent (in)  :: coords_shape (2, ndim_2d)
00031 !     Dimension of (method/grid) coordinate "coords"
00032       double precision,  intent (in)  :: 
00033          coords_x(coords_shape(1,1):coords_shape(2,1),  
00034                   coords_shape(1,2):coords_shape(2,2)), 
00035          coords_y(coords_shape(1,1):coords_shape(2,1),  
00036                   coords_shape(1,2):coords_shape(2,2))
00037 !     Coordinates of the method
00038       integer,           intent (in)    :: corner_shape (2, ndim_3d)
00039 !     Dimension of the array "corners" containing the corner points
00040 !     of the control volume (for a single coordinate).
00041       integer,           intent (in)    :: sub_range (2, ndim_2d)
00042 !     Definintion of the subgrid for which the (bounding) cells should
00043 !     be computed.
00044       integer,           intent (in)    :: pole_array(:)
00045 !     List of corner cells covering the poles
00046       double precision, intent(in)      :: period
00047 !     period of grid coordinate range (typically 360 degree)
00048 
00049 !
00050 ! !INOUTPUT PARAMETERS:
00051 !
00052       double precision,  intent (inout) :: chmin_x (sub_range(1,1)-1:sub_range(2,1), 
00053                                                     sub_range(1,2)-1:sub_range(2,2))
00054 !     Minimum value of bounding box of method cell
00055       double precision,  intent (inout) :: chmax_x (sub_range(1,1)-1:sub_range(2,1), 
00056                                                     sub_range(1,2)-1:sub_range(2,2))
00057 !     Maximum value of bounding box of method cell
00058       double precision,  intent (inout) :: chmin_y (sub_range(1,1)-1:sub_range(2,1), 
00059                                                     sub_range(1,2)-1:sub_range(2,2))
00060 !     Minimum value of bounding box of method cell
00061       double precision,  intent (inout) :: chmax_y (sub_range(1,1)-1:sub_range(2,1), 
00062                                                     sub_range(1,2)-1:sub_range(2,2))
00063 !     Maximum value of bounding box of method cell
00064       double precision,  intent (inout) :: midp_x(sub_range(1,1)-1:sub_range(2,1), 
00065                                                   sub_range(1,2)-1:sub_range(2,2))
00066 !     Mid point of bounding box of method cell
00067       double precision,  intent (inout) :: midp_y(sub_range(1,1)-1:sub_range(2,1), 
00068                                                   sub_range(1,2)-1:sub_range(2,2))
00069 !     Mid point of bounding box of method cell
00070 
00071 !
00072 ! !OUTPUT PARAMETERS:
00073 !
00074       integer,           intent (out)   :: ierror
00075 
00076 !     Returns the error code of psmile_bbcells_pole_dble
00077 !             ierror = 0 : No error
00078 !             ierror > 0 : Severe error
00079 !
00080 ! !DEFINED PARAMETERS:
00081 !
00082 ! Loop variable
00083       integer                      :: n, i, j
00084 ! Index for accessing arrays
00085       integer                      :: ijk(3)
00086 ! For computation of a new midpoint
00087       type(point_dble)             :: cell(4), temp_cell(4), midpoint
00088 ! Method grid pole array
00089       integer, pointer             :: method_pole_array_x(:), method_pole_array_y(:)
00090       integer                      :: method_pole_array_size
00091       integer                      :: method_pole_array_allocated_size
00092 ! Error parameters
00093       integer, parameter           :: nerrp = 2
00094       integer                      :: ierrp (nerrp)
00095 !
00096 !
00097 ! !DESCRIPTION:
00098 !
00099 ! Subroutine "psmile_bbcells_pole_dble" extents the bounding boxes
00100 ! of cells covering the north or south pole to 90 or -90
00101 ! respectively
00102 !
00103 ! !REVISION HISTORY:
00104 !
00105 !   Date      Programmer   Description
00106 ! ----------  ----------   -----------
00107 ! 14.09.10    M. Hanke     created
00108 !
00109 !EOP
00110 !----------------------------------------------------------------------
00111 !
00112 !  $Id: psmile_bbcells_pole_dble.F90 2661 2010-10-25 08:39:13Z coquart $
00113 !  $Author: coquart $
00114 !
00115    Character(len=len_cvs_string), save :: mycvs = 
00116        '$Id: psmile_bbcells_pole_dble.F90 2661 2010-10-25 08:39:13Z coquart $'
00117 !
00118 !----------------------------------------------------------------------
00119 !
00120 #ifdef VERBOSE
00121       print 9990, trim(ch_id)
00122 
00123       call psmile_flushstd
00124 #endif /* VERBOSE */
00125 
00126 !
00127 !  Initialization
00128 !
00129 !  MoHa: do I have to take z into account?
00130       ierror = 0
00131       method_pole_array_size = 0
00132       method_pole_array_allocated_size = size(pole_array)
00133       allocate(method_pole_array_x(method_pole_array_allocated_size))
00134       allocate(method_pole_array_y(method_pole_array_allocated_size))
00135       method_pole_array_x = prism_undefined
00136       method_pole_array_y = prism_undefined
00137 !
00138 !  Detect pole cells, the pole_array contains the corner cells which cover the pole,
00139 !  but we are working with method cells, which are related to the corners cells but not identical
00140 !
00141 #ifdef DEBUG
00142       PRINT *, TRIM(ch_id), 'number of points at pole found in set_corners :', &
00143                SIZE(pole_array)
00144       call psmile_flushstd
00145 #endif
00146       do n = 1, size(pole_array)
00147 
00148          ijk = psmile_transform_index_1d_to_3d (pole_array(n), corner_shape)
00149 
00150          do i = max (ijk(1)-1, coords_shape(1,1)), min (ijk(1)+1, coords_shape(2,1)-1)
00151 
00152             do j = max (ijk(2)-1, coords_shape(1,2)), min (ijk(2)+1, coords_shape(2,2)-1)
00153                cell(1)%x = coords_x(i  , j  )
00154                cell(2)%x = coords_x(i+1, j  )
00155                cell(3)%x = coords_x(i+1, j+1)
00156                cell(4)%x = coords_x(i  , j+1)
00157 
00158                cell(1)%y = coords_y(i  , j  )
00159                cell(2)%y = coords_y(i+1, j  )
00160                cell(3)%y = coords_y(i+1, j+1)
00161                cell(4)%y = coords_y(i  , j+1)
00162 
00163                call psmile_transform_cell_cyclic ( cell(:)%x, period, ierror )
00164 
00165                if (psmile_cell_covers_pole(cell(:)%x, cell(:)%y, 4)) then
00166 
00167                   !if the cell is already in the pole array
00168                   if (.not. any((method_pole_array_x == i) .and. (method_pole_array_y == j))) then
00169 
00170                      if (method_pole_array_size == method_pole_array_allocated_size) then
00171 
00172                         method_pole_array_allocated_size = method_pole_array_allocated_size + 8
00173                         method_pole_array_x => psmile_realloc(method_pole_array_x, &
00174                                                             method_pole_array_allocated_size)
00175                         method_pole_array_y => psmile_realloc(method_pole_array_y, &
00176                                                             method_pole_array_allocated_size)
00177                      endif
00178 
00179 #if defined(VERBOSE) && defined(DEBUG)
00180                      print *, trim(ch_id), ": found pole method cell at", i, j
00181                      print "(a, ': x', /, 2f8.2, /, 2f8.2, /, 2f8.2, /, 2f8.2)", trim(ch_id)
00182                      PRINT*, 'cell x :',cell(1)%x,cell(2)%x,cell(3)%x,cell(4)%x
00183                      PRINT*, 'cell y :',cell(1)%y,cell(2)%y,cell(3)%y,cell(4)%y
00184 #endif
00185 
00186                      method_pole_array_size = method_pole_array_size + 1
00187                      method_pole_array_x(method_pole_array_size) = i
00188                      method_pole_array_y(method_pole_array_size) = j
00189                   endif
00190                endif
00191             enddo
00192          enddo
00193       enddo
00194 !
00195 !  Main part
00196 !
00197       do n = 1, method_pole_array_size
00198 
00199          i = method_pole_array_x(n)
00200          j = method_pole_array_y(n)
00201 
00202          ! extending longitude bouding box
00203          chmax_x(i, j) = 180.0d0
00204          chmin_x(i, j) = -180.0d0
00205 
00206          ! extent chmin/max to -90 or 90 respectively and adjust midpoint
00207          if (chmax_y(i, j) > 0) then
00208              chmax_y(i, j) = 90.0d0
00209 
00210 #if defined(VERBOSE) && defined(DEBUG)
00211          print *, trim(ch_id), ': extending chmax_x to 90'
00212 #endif /* VERBOSE */
00213 
00214          else
00215             chmin_y(i, j) = -90.0d0
00216 
00217 #if defined(VERBOSE) && defined(DEBUG)
00218          print *, trim(ch_id), ': extending chmin_y to -90'
00219 #endif /* VERBOSE */
00220          endif
00221 
00222          cell(1)%x = coords_x(i  , j  )
00223          cell(2)%x = coords_x(i+1, j  )
00224          cell(3)%x = coords_x(i+1, j+1)
00225          cell(4)%x = coords_x(i  , j+1)
00226 
00227          cell(1)%y = coords_y(i  , j  )
00228          cell(2)%y = coords_y(i+1, j  )
00229          cell(3)%y = coords_y(i+1, j+1)
00230          cell(4)%y = coords_y(i  , j+1)
00231 
00232          call compute_midpoint(cell, &
00233             midp_x(i, j), midp_y(i, j))
00234 
00235       enddo
00236 !
00237 !  cleaning up
00238 !
00239    deallocate (method_pole_array_x, method_pole_array_y)
00240 !
00241 !===> All done
00242 !
00243 #ifdef VERBOSE
00244       print 9980, trim(ch_id), ierror
00245 
00246       call psmile_flushstd
00247 #endif /* VERBOSE */
00248 !
00249 !  Formats:
00250 !
00251 9990 format (1x, a, ': psmile_bbcells_pole_dble')
00252 9980 format (1x, a, ': psmile_bbcells_pole_dble: eof ierror =', i3)
00253 !
00254 
00255       contains
00256 
00257          subroutine compute_midpoint(cell, midp_x, midp_y)
00258             type(point_dble), intent(in)  :: cell(4)
00259             double precision, intent(out) :: midp_x, midp_y
00260             type(point_dble)              :: temp_cell(4), temp_midp
00261 
00262 #ifdef VERBOSE
00263             print 9970, trim(ch_id), cell(1)%x,cell(1)%y
00264             print 9971, trim(ch_id), cell(2)%x,cell(2)%y
00265             print 9972, trim(ch_id), cell(3)%x,cell(3)%y
00266             print 9973, trim(ch_id), cell(4)%x,cell(4)%y
00267             call psmile_flushstd
00268 #endif /* VERBOSE */
00269 
00270             call psmile_transrot_dble(cell(1)%x, cell(1)%y, temp_cell(1)%x, temp_cell(1)%y)
00271             call psmile_transrot_dble(cell(2)%x, cell(2)%y, temp_cell(2)%x, temp_cell(2)%y)
00272             call psmile_transrot_dble(cell(3)%x, cell(3)%y, temp_cell(3)%x, temp_cell(3)%y)
00273             call psmile_transrot_dble(cell(4)%x, cell(4)%y, temp_cell(4)%x, temp_cell(4)%y)
00274 
00275             temp_midp%x = sum(temp_cell(:)%x) / 4.0d0
00276             temp_midp%y = sum(temp_cell(:)%y) / 4.0d0
00277 
00278             call psmile_transrot_back_dble(midp_x, midp_y, &
00279                                            temp_midp%x, temp_midp%y)
00280 
00281 #ifdef VERBOSE
00282             print 9960, trim(ch_id), midp_x, midp_y
00283             call psmile_flushstd
00284 #endif /* VERBOSE */
00285 9970 format (1x, a, ': psmile_bbcells_pole_dble: computing new midpoint for cell(1) =', 2f8.2)
00286 9971 format (1x, a, ': psmile_bbcells_pole_dble: computing new midpoint for cell(2) =', 2f8.2)
00287 9972 format (1x, a, ': psmile_bbcells_pole_dble: computing new midpoint for cell(3) =', 2f8.2)
00288 9973 format (1x, a, ': psmile_bbcells_pole_dble: computing new midpoint for cell(4) =', 2f8.2)
00289 9960 format (1x, a, ': psmile_bbcells_pole_dble: new midpoint =', 2f8.2)
00290 
00291          end subroutine compute_midpoint
00292 
00293          function psmile_cell_covers_pole (corners_x, corners_y, num_corners)
00294             double precision, intent(in) :: corners_x(4), corners_y(4)
00295             integer, intent(in) :: num_corners
00296             logical :: psmile_cell_covers_pole
00297             double precision :: angle
00298             integer :: sense, i
00299 
00300             ! tests if any corner is directly on the pole
00301             if (any(abs(corners_y) == 90)) then
00302                psmile_cell_covers_pole = .true.
00303                return
00304             endif
00305 
00306             sense = 0
00307             ! for all edges
00308             do i = 1, num_corners - 1
00309                angle = corners_x(i+1) - corners_x(i)
00310                sense = sense + sign(1.0d0,mod(angle-180.0d0,360.0d0)+180.0d0)
00311             enddo
00312 
00313             angle = corners_x(1) - corners_x(num_corners)
00314             sense = sense + sign(1.0d0,mod(angle-180.0d0,360.0d0)+180.0d0)
00315 
00316             psmile_cell_covers_pole = abs(sense) == num_corners
00317          end function psmile_cell_covers_pole
00318 
00319       end subroutine psmile_bbcells_pole_dble

Generated on 18 Mar 2011 for Oasis4 by  doxygen 1.6.1