psmile_mg_first_level_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_MG_first_level_real
00008 !
00009 ! !INTERFACE:
00010 
00011       subroutine psmile_mg_first_level_real (grid_id, range, &
00012                       mg_info, tol, simplified_grid, ierror)
00013 !
00014 ! !USES:
00015 !
00016       use PRISM_constants
00017       use psmile_grid, only : common_grid_range
00018       use PSMILe, dummy_interface => PSMILe_MG_first_level_real
00019 
00020       implicit none
00021 !
00022 ! !INPUT PARAMETERS:
00023 !
00024       Integer,                  Intent (In) :: grid_id
00025 
00026 !     Specifies the handle to the grid information.
00027 
00028       Integer,                  Intent (In) :: range (2, ndim_3d)
00029 
00030 !     Range for which MG sequence should be setup
00031 
00032       Real (PSMILe_float_kind), Intent (In) :: tol
00033 
00034 !     Search tolerance
00035 !
00036       Logical,                  Intent (In) :: simplified_grid
00037 !
00038 !     Should the simplified grids for grids of type
00039 !     "PRISM_Gaussreduced_regvrt" be used ?
00040 !
00041 ! !INPUT/OUTPUT PARAMETERS:
00042 !
00043       Type (Enddef_mg),      Intent (InOut) :: mg_info
00044 
00045 !     Structure returning the data on the first multigrid level
00046 !     which is created by this routine.
00047 !
00048 ! !OUTPUT PARAMETERS:
00049 !
00050       Integer,               Intent (Out)   :: ierror
00051 
00052 !     Returns the error code of PSMILe_MG_first_level_real;
00053 !             ierror = 0 : No error
00054 !             ierror > 0 : Severe error
00055 !
00056 ! !DEFINED PARAMETERS:
00057 !
00058       Integer, Parameter                  :: nc_reg = 2
00059 
00060 !     Number of corners for regular directions
00061 
00062       Integer, Parameter                  :: nd_cyclic = 2
00063 
00064 !     Number of possible cylic coordinates (lon lat)
00065 !
00066 ! !LOCAL VARIABLES
00067 !
00068       Type (Grid), Pointer                :: gp
00069       Type (Corner_Block), Pointer        :: corner_pointer
00070       Type (Enddef_mg_real), Pointer    :: arrays
00071 !
00072       Integer                             :: grid_type
00073 !
00074 !  ... for dimensions
00075 !
00076       integer                             :: index_c ! index in corner shape
00077       integer                             :: index_g ! index in grid   shape
00078       integer                             :: i, ii, jj, kk
00079       integer                             :: leni, lenij
00080       integer                             :: dim_i, dim_ij
00081       integer                             :: dim (ndim_3d)
00082 !
00083 !  ... for lonlat periods
00084 !
00085       Real                                :: len_cyclic (nd_cyclic)
00086       Real                                :: bounds_lon (2)
00087 !
00088 !  ... for error parameters
00089 !
00090       Integer, Parameter                  :: nerrp = 2
00091       Integer                             :: ierrp (nerrp)
00092 !
00093 ! !DESCRIPTION:
00094 !
00095 ! Subroutine "PSMILe_MG_first_level_real" creates the multi-grid
00096 ! information for the first level of the multigrid sequence.
00097 !
00098 ! !REVISION HISTORY:
00099 !
00100 !   Date      Programmer   Description
00101 ! ----------  ----------   -----------
00102 ! 03.06.05    H. Ritzdorf  created
00103 !
00104 !EOP
00105 !----------------------------------------------------------------------
00106 !
00107 !  $Id: psmile_mg_first_level_real.F90 2687 2010-10-28 15:15:52Z coquart $
00108 !  $Author: coquart $
00109 !
00110    Character(len=len_cvs_string), save :: mycvs = 
00111        '$Id: psmile_mg_first_level_real.F90 2687 2010-10-28 15:15:52Z coquart $'
00112 !
00113 !----------------------------------------------------------------------
00114 
00115 #ifdef VERBOSE
00116       print *, trim(ch_id), ': psmile_mg_first_level_real: grid_id', grid_id
00117 
00118       call psmile_flushstd
00119 #endif /* VERBOSE */
00120 !
00121 !  Initialization
00122 !
00123       ierror = 0
00124       gp => Grids(grid_id)
00125 !
00126       if ( gp%grid_type == PRISM_Gaussreduced_regvrt .and. &
00127            simplified_grid) then
00128 
00129 !        use the simplified corner volumes
00130 
00131          corner_pointer => gp%gcorner_pointer
00132          grid_type = PRISM_Reglonlatvrt
00133 
00134       else
00135 
00136 !        use the real corner volumes
00137 
00138          corner_pointer => gp%corner_pointer
00139          grid_type = gp%grid_type
00140 
00141       endif
00142 !
00143 !     lon lat range for cyclic indices is 360 or 180 degrees, respectively.
00144 !
00145       len_cyclic (1:nd_cyclic) = common_grid_range(2,1:nd_cyclic) - &
00146                                  common_grid_range(1,1:nd_cyclic)
00147 !
00148 #ifdef PRISM_ASSERTION
00149 
00150      if (corner_pointer%corner_datatype /= MPI_REAL) then
00151         call psmile_assert ( __FILE__, __LINE__, &
00152                             'Corner type is not MPI_REAL')
00153 
00154      endif
00155 
00156 !    Internal control: Is the data really available
00157 
00158       if (.not. Associated(corner_pointer%corners_real(1)%vector) ) then
00159          call psmile_assert ( __FILE__, __LINE__, &
00160                 'Pointer corners_real(1)%vector is not set')
00161       endif
00162 
00163       if (.not. Associated(corner_pointer%corners_real(2)%vector) ) then
00164          call psmile_assert ( __FILE__, __LINE__, &
00165                 'Pointer corners_real(2)%vector is not set')
00166       endif
00167 
00168       if (.not. Associated(corner_pointer%corners_real(3)%vector) ) then
00169          call psmile_assert ( __FILE__, __LINE__, &
00170                 'Pointer corners_real(3)%vector is not set')
00171       endif
00172 #endif /* PRISM_ASSERTION */
00173 !
00174 !   Allocate pointer to real arrays
00175 !
00176       Allocate (mg_info%real_arrays, STAT = ierror)
00177       if ( ierror > 0 ) then
00178          ierrp (1) = ierror
00179          ierrp (2) = 1
00180          ierror = PRISM_Error_Alloc
00181          call psmile_error ( ierror, 'mg_info%real_arrays', &
00182                              ierrp, 2, __FILE__, __LINE__ )
00183          return
00184       endif
00185 !
00186       arrays => mg_info%real_arrays
00187 !
00188 ! ====================================================================
00189 !     Get dimensions of arrays to be allocated and
00190 !     allocate the arrays.
00191 !
00192 !     "levdim" specifies the dimension of the grid level to be created.
00193 !     The dimension is (0:levdim(i)) for each direction.
00194 ! ====================================================================
00195 
00196       select case ( grid_type )
00197 
00198 ! -----------------------------------------------------------------------
00199 !         Regular in all directions
00200 !         ===> Number of corners in all directions = 2
00201 !              (cf. prism_set_corners_3d_real.F90)
00202 ! -----------------------------------------------------------------------
00203 !
00204       case (PRISM_Reglonlatvrt)
00205 !
00206          dim(1) = mg_info%levdim(1) + 1
00207          dim(2) = mg_info%levdim(2) + 1
00208          dim(3) = mg_info%levdim(3) + 1
00209 !
00210 ! -----------------------------------------------------------------------
00211 !       Irregular in lonlat   direction
00212 !         Regular in vertical direction
00213 !         ===> Number of corners in vertical direction = 2
00214 !              (cf. prism_set_corners_3d_real.F90)
00215 ! -----------------------------------------------------------------------
00216 !
00217       case (PRISM_Irrlonlat_regvrt)
00218 
00219          dim(1) = (mg_info%levdim(1)+1) * (mg_info%levdim(2)+1)
00220          dim(2) = dim(1)
00221          dim(3) = mg_info%levdim (3) + 1
00222 !
00223 ! -----------------------------------------------------------------------
00224 !       Gaussreduced in lonlat   direction
00225 !         Regular in vertical direction
00226 !         ===> Number of corners in vertical direction = 2
00227 !              (cf. prism_set_corners_3d_real.F90)
00228 ! -----------------------------------------------------------------------
00229 !
00230       case (PRISM_Gaussreduced_regvrt)
00231 
00232          dim(1) = mg_info%levdim(1) + 1
00233          dim(2) = dim (1)
00234          dim(3) = mg_info%levdim(3) + 1
00235 !
00236 ! -----------------------------------------------------------------------
00237 !       Irregular in lonlat   and vertical direction
00238 ! -----------------------------------------------------------------------
00239 !
00240       case (PRISM_Irrlonlatvrt)
00241 
00242          dim(1) = (mg_info%levdim(1)+1) * (mg_info%levdim(2)+1) * &
00243                   (mg_info%levdim(3)+1)
00244          dim(2) = dim(1)
00245          dim(3) = dim(2)
00246 !
00247 ! -----------------------------------------------------------------------
00248 !     Error: unsupported grid type
00249 ! -----------------------------------------------------------------------
00250 !
00251       case DEFAULT
00252 !
00253           ierrp (1) = grid_type
00254 
00255           ierror = PRISM_Error_Internal
00256 
00257           call psmile_error ( ierror, 'unsupported grid generation type', &
00258                               ierrp, 1, __FILE__, __LINE__ )
00259 
00260       end select
00261 !
00262 #ifdef DEBUG
00263       print *, trim(ch_id), ': psmile_mg_first_level_dble: dim(1:3)', dim(1:3)
00264       call psmile_flushstd
00265 #endif
00266 !  ... Allocate arrays
00267 !
00268          do i = 1, ndim_3d
00269 
00270          Allocate (arrays%chmin(i)%vector(dim(i)), &
00271                    arrays%chmax(i)%vector(dim(i)), &
00272                    arrays%midp (i)%vector(dim(i)), STAT = ierror)
00273          if ( ierror > 0 ) then
00274             ierrp (1) = ierror
00275             ierrp (2) = dim (i) * 3
00276             ierror = PRISM_Error_Alloc
00277             call psmile_error ( ierror, 'mg_info%{chmin,chmax,midp}(i)%vector', &
00278                                 ierrp, 2, __FILE__, __LINE__ )
00279             return
00280          endif
00281 
00282          end do
00283 !
00284 ! ====================================================================
00285 !  Now, the multi-grid informations has to be generated depending
00286 !  on the grid type "grid_type". 
00287 !
00288 !  Waere es nicht sinnvoller, immer die 3d Routine zu verwenden
00289 !  und die anderen Dimensionen auf 1 zu setzen.
00290 ! ====================================================================
00291 
00292       select case ( grid_type )
00293 
00294 ! -----------------------------------------------------------------------
00295 !         Regular in all directions
00296 !         ===> Number of corners in all directions = 2
00297 !              (cf. prism_set_corners_3d_real.F90)
00298 !
00299 !         Note: This case is also used for
00300 !               (*) grids of type "PRISM_Gaussreduced_regvrt"
00301 !                   simplified corner volumes.
00302 !                
00303 ! -----------------------------------------------------------------------
00304 !
00305       case (PRISM_Reglonlatvrt)
00306 !
00307             do i = 1, ndim_3d
00308             call psmile_mg_first_subgrid_1d_real (   &
00309                 corner_pointer%corners_real(i)%vector,     &
00310                 corner_pointer%corner_shape(1,i), &
00311                 corner_pointer%corner_shape(2,i), &
00312                 nc_reg,                           &
00313                 range (1, i),                     &
00314                 arrays%chmin(i)%vector, arrays%chmax(i)%vector, &
00315                 arrays%midp(i)%vector, &
00316                 mg_info%levdim (i), ierror)
00317             if (ierror > 0) return
00318             end do
00319 !
00320 !           ... Control multigrid requirements for lonlat directions
00321 !
00322             do i = 1, nd_cyclic
00323             call psmile_mg_ctrl_subgrid_1d_real (          &
00324                 corner_pointer%corners_real(i)%vector,     &
00325                 corner_pointer%corner_shape(:,i), nc_reg,  &
00326                 range (:, i),                              &
00327                 arrays%chmin(i)%vector, arrays%chmax(i)%vector, &
00328                 mg_info%levdim (i),                        &
00329                 len_cyclic(i), grid_id, i, ierror)
00330             if (ierror > 0) return
00331             end do
00332 !
00333 ! -----------------------------------------------------------------------
00334 !       Irregular in lonlat   direction
00335 !         Regular in vertical direction
00336 !         ===> Number of corners in vertical direction = 2
00337 !              (cf. prism_set_corners_3d_real.F90)
00338 ! -----------------------------------------------------------------------
00339 !
00340       case (PRISM_Irrlonlat_regvrt)
00341 !
00342          do i = 1, ndim_2d
00343          call psmile_mg_first_subgrid_2d_real (   &
00344              corner_pointer%corners_real(i)%vector,       &
00345              corner_pointer%corner_shape(1,1),   &
00346              corner_pointer%corner_shape(2,1),   &
00347              corner_pointer%corner_shape(1,2),   &
00348              corner_pointer%corner_shape(2,2),   &
00349              corner_pointer%nbr_corners/nc_reg,  &
00350              range (1, 1),                     &
00351              arrays%chmin(i)%vector, arrays%chmax(i)%vector, &
00352              arrays%midp(i)%vector, &
00353              mg_info%levdim (1), mg_info%levdim (2), ierror)
00354          if (ierror > 0) return
00355          end do
00356 !
00357          call psmile_mg_first_subgrid_1d_real (   &
00358              corner_pointer%corners_real(3)%vector,     &
00359              corner_pointer%corner_shape(1,3), &
00360              corner_pointer%corner_shape(2,3), &
00361              nc_reg,                           &
00362              range (1, 3),                     &
00363              arrays%chmin(3)%vector, arrays%chmax(3)%vector, arrays%midp(3)%vector, &
00364              mg_info%levdim (3), ierror)
00365          if (ierror > 0) return
00366 !
00367 !           ... Control multigrid requirements for lonlat directions
00368 !
00369             do i = 1, nd_cyclic
00370             call psmile_mg_ctrl_subgrid_2d_real (          &
00371                 corner_pointer%corners_real(i)%vector,     &
00372                 corner_pointer%corner_shape(:,1:2),        &
00373                 corner_pointer%nbr_corners/nc_reg,         &
00374                 range (:, 1:2),                            &
00375                 arrays%chmin(i)%vector, arrays%chmax(i)%vector, &
00376                 mg_info%levdim (1:2), &
00377                 len_cyclic(i), grid_id, i, ierror)
00378             if (ierror > 0) return
00379             end do
00380 !
00381 ! -----------------------------------------------------------------------
00382 !    GaussReduced in lonlat   direction
00383 !         Regular in vertical direction
00384 !         ===> Number of corners in all directions = 2
00385 !              (cf. prism_set_corners_3d_real.F90)
00386 !
00387 !    The lonlat direction is handled as 1--dimensional vector with
00388 !    the same dimension in all lon and lat direction.
00389 !                
00390 ! -----------------------------------------------------------------------
00391 !
00392       case (PRISM_Gaussreduced_regvrt)
00393 !
00394             do i = 1, ndim_2d
00395             call psmile_mg_first_subgrid_1d_real (     &
00396                 corner_pointer%corners_real(i)%vector, &
00397                 corner_pointer%corner_shape(1,1),      &
00398                 corner_pointer%corner_shape(2,1),      &
00399                 nc_reg,                                &
00400                 range (1, 1),                          &
00401                 arrays%chmin(i)%vector, arrays%chmax(i)%vector, &
00402                 arrays%midp(i)%vector,                 &
00403                 mg_info%levdim (1), ierror)
00404             if (ierror > 0) return
00405             end do
00406 !
00407          call psmile_mg_first_subgrid_1d_real (       &
00408                corner_pointer%corners_real(3)%vector, &
00409                corner_pointer%corner_shape(1,3),      &
00410                corner_pointer%corner_shape(2,3),      &
00411                nc_reg, range (1, 3),                  &
00412                arrays%chmin(3)%vector, arrays%chmax(3)%vector, &
00413                arrays%midp(3)%vector,                 &
00414                mg_info%levdim (3), ierror)
00415           if (ierror > 0) return
00416 !
00417 !           ... Control multigrid requirements for lonlat directions
00418 !
00419             do i = 1, nd_cyclic
00420             call psmile_mg_ctrl_subgrid_1d_real (          &
00421                 corner_pointer%corners_real(i)%vector,     &
00422                 corner_pointer%corner_shape(:,1), nc_reg,  &
00423                 range (:, 1),                              &
00424                 arrays%chmin(i)%vector, arrays%chmax(i)%vector, &
00425                 mg_info%levdim (i),                        &
00426                 len_cyclic(i), grid_id, i, ierror)
00427             if (ierror > 0) return
00428             end do
00429 !
00430 ! -----------------------------------------------------------------------
00431 !       Irregular in lonlat   and vertical direction
00432 ! -----------------------------------------------------------------------
00433 !
00434       case (PRISM_Irrlonlatvrt)
00435 
00436             do i = 1, ndim_3d
00437             call psmile_mg_first_subgrid_3d_real ( &
00438                 corner_pointer%corners_real(i)%vector,       &
00439                 corner_pointer%corner_shape(1,1),   &
00440                 corner_pointer%corner_shape(2,1),   &
00441                 corner_pointer%corner_shape(1,2),   &
00442                 corner_pointer%corner_shape(2,2),   &
00443                 corner_pointer%corner_shape(1,3),   &
00444                 corner_pointer%corner_shape(2,3),   &
00445                 corner_pointer%nbr_corners,         &
00446                 range,                              &
00447                 arrays%chmin(i)%vector, arrays%chmax(i)%vector, &
00448                 arrays%midp(i)%vector, &
00449                 mg_info%levdim (1), mg_info%levdim (2), mg_info%levdim (3), ierror)
00450             if (ierror > 0) return
00451             end do
00452 !
00453 !           ... Control multigrid requirements for lonlat directions
00454 !
00455             do i = 1, nd_cyclic
00456             call psmile_mg_ctrl_subgrid_3d_real (      &
00457                 corner_pointer%corners_real(i)%vector, &
00458                 corner_pointer%corner_shape,           &
00459                 corner_pointer%nbr_corners,            &
00460                 range,                                 &
00461                 arrays%chmin(i)%vector,                &
00462                 arrays%chmax(i)%vector,                &
00463                 mg_info%levdim, &
00464                 len_cyclic(i), grid_id, i, ierror)
00465             if (ierror > 0) return
00466             end do
00467 !
00468 ! -----------------------------------------------------------------------
00469 !     Error: unsupported grid type
00470 ! -----------------------------------------------------------------------
00471 !
00472       case DEFAULT
00473 !
00474           ierrp (1) = grid_type
00475 
00476           ierror = PRISM_Error_Internal
00477 
00478           call psmile_error ( ierror, 'unsupported grid generation type', &
00479                               ierrp, 1, __FILE__, __LINE__ )
00480 
00481       end select
00482 
00483 ! -----------------------------------------------------------------------
00484 !        ... extent cell over the pole onto the pole point
00485 !     HUHU: Why no pole cells for PRISM_Reglonlatvrt ?
00486 ! -----------------------------------------------------------------------
00487 
00488       if ( gp%grid_type == PRISM_Irrlonlat_regvrt .or. &
00489            gp%grid_type == PRISM_Irrlonlatvrt) then
00490 
00491          bounds_lon(1) = -180.0
00492          bounds_lon(2) =  180.0
00493 
00494          if ( associated ( corner_pointer%pole_array ) ) then
00495 
00496             leni  = corner_pointer%corner_shape(2,1) - &
00497                     corner_pointer%corner_shape(1,1) + 1
00498             lenij = leni * & 
00499                    (corner_pointer%corner_shape(2,2) - &
00500                     corner_pointer%corner_shape(1,2) + 1)
00501 
00502             dim_i  = (mg_info%levdim(1)+1)
00503             dim_ij = dim_i * (mg_info%levdim(2)+1)
00504 
00505             do i = 1, size(corner_pointer%pole_array)
00506 
00507                index_c = corner_pointer%pole_array(i)
00508 
00509 !              Transfer 1-dimensional index into 3-dimensional index 
00510 !              within the corner shape
00511 
00512                kk =  (index_c-1) / lenij
00513                jj = ((index_c-1) -kk*lenij) / leni
00514                ii =  (index_c-1) -kk*lenij -jj*leni
00515 !
00516                ii = corner_pointer%corner_shape(1,1) + ii
00517                jj = corner_pointer%corner_shape(1,2) + jj
00518                kk = corner_pointer%corner_shape(1,3) + kk
00519 
00520 !              Transfer 3-dimensional index into 1-dimensional index 
00521 !              in chmin, chmax and midp
00522 
00523                index_g = (kk-gp%ijk0(3)) * dim_ij &
00524                        + (jj-gp%ijk0(2)) * dim_i  &
00525                        +  ii-gp%ijk0(1)  + 1
00526 !
00527 !              Extent chmin and chmax only when the pole is included in the subsection
00528 !
00529                if ( index_g < dim(1) .and. index_g < dim(2) ) then
00530 #ifdef DEBUG
00531                   print *, trim(ch_id), ': psmile_mg_first_level_real: chmax extended to pole'
00532                   print *, trim(ch_id), '   for index in valid_shape:'
00533                   print *, trim(ch_id), '   i ', ii, ' j ', jj, ' k ', kk
00534                   call psmile_flushstd
00535 #endif /* DEBUG */
00536 
00537                   if ( corner_pointer%corners_real(2)%vector(index_c) > 0.0 ) then
00538                      ! HUHU: TODO: Improve setting of lon extension; edge on pole; more than 1 cell
00539                      !       There seems to be a problem in nearest neighbour search
00540                      !       setting to -360:360 changes the result of nearest neighbour search
00541                      !       in example cicle_1 using 1 proc
00542                      !
00543                      arrays%chmin(1)%vector(index_g) =  min (bounds_lon(1), &
00544                           arrays%chmin(1)%vector(index_g))
00545                      arrays%chmax(1)%vector(index_g) =  max (bounds_lon(2), &
00546                           arrays%chmax(1)%vector(index_g))
00547                      !                 arrays%midp (1)%vector(index_g) =     0.0
00548 
00549                      arrays%chmax(2)%vector(index_g) =  90.0
00550                      arrays%midp (2)%vector(index_g) =  90.0
00551 
00552                   else if ( corner_pointer%corners_real(2)%vector(index_c) < 0.0 ) then
00553                      arrays%chmin(1)%vector(index_g) =  min (bounds_lon(1), &
00554                           arrays%chmin(1)%vector(index_g))
00555                      arrays%chmax(1)%vector(index_g) =  max (bounds_lon(2), &
00556                           arrays%chmax(1)%vector(index_g))
00557                      !                 arrays%midp (1)%vector(index_g) =     0.0
00558 
00559                      arrays%chmin(2)%vector(index_g) = -90.0
00560                      arrays%midp(2)%vector(index_g)  = -90.0
00561                   endif
00562 
00563                endif
00564 
00565             enddo
00566 
00567          endif
00568 
00569       endif
00570 !
00571 !===> All done
00572 !
00573 #ifdef VERBOSE
00574       print *, trim(ch_id), ': psmile_mg_first_level_real eof: grid_id',&
00575                              grid_id, ', ierror =', ierror
00576 
00577       call psmile_flushstd
00578 #endif /* VERBOSE */
00579 !
00580       end subroutine PSMILe_MG_first_level_real

Generated on 18 Mar 2011 for Oasis4 by  doxygen 1.6.1