psmile_mg_setup.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_setup
00008 !
00009 ! !INTERFACE:
00010 
00011       subroutine psmile_mg_setup (grid_id, range, tol, ierror)
00012 !
00013 ! !USES:
00014 !
00015       use PRISM_constants
00016 !
00017       use PSMILe, dummy_interface => PSMILe_MG_setup
00018 
00019       implicit none
00020 
00021 !
00022 ! !INPUT PARAMETERS:
00023 !
00024       Integer, Intent (In)               :: grid_id
00025 
00026 !     Grid Id for which the multigrid sequence is generated
00027 
00028       Integer, Intent (In)               :: range (2, ndim_3d)
00029 
00030 !     Range for which MG sequence should be setup
00031 
00032       Double precision, Intent (In)      :: tol
00033 
00034 !     Tolerance for search
00035 !
00036 ! !OUTPUT PARAMETERS:
00037 !
00038       Integer, Intent (Out)              :: ierror
00039 !
00040 !     Returns the error code of PSMILe_MG_setup;
00041 !             ierror = 0 : No error
00042 !             ierror > 0 : Severe error
00043 !
00044 ! !LOCAL VARIABLES
00045 !
00046 !  ... for components
00047 !
00048       integer                            :: comp_id
00049 
00050 !  ... for grids
00051 
00052       integer                            :: lev, levf, ndlev
00053       integer                            :: levbeg
00054       integer, allocatable               :: levdim (:, :)
00055       integer                            :: icoarse (ndim_3d)
00056       Integer                            :: my_range (2, ndim_3d)
00057 
00058       integer                            :: j, len, n
00059 !
00060       logical                            :: simplified_grid
00061 
00062       Type(Grid), Pointer                :: gp
00063 
00064 !  ... for error parameters
00065 
00066       integer, parameter                 :: nerrp = 2
00067       integer                            :: ierrp (nerrp)
00068 !
00069 ! !DESCRIPTION:
00070 !
00071 ! Subroutine "PSMILe_MG_setup" sets up the multigrid sequence for
00072 ! searching the neighbourhood information. The multigrid sequence is
00073 ! setup for the grid with grid id "grid_id" and restricted to subgrid
00074 ! "range".
00075 !
00076 ! !REVISION HISTORY:
00077 !
00078 !   Date      Programmer   Description
00079 ! ----------  ----------   -----------
00080 ! 03.06.20    H. Ritzdorf  created
00081 !
00082 !EOP
00083 !----------------------------------------------------------------------
00084 !
00085 !  $Id: psmile_mg_setup.F90 3016 2011-03-14 15:17:02Z hanke $
00086 !  $Autor$
00087 !
00088    Character(len=len_cvs_string), save :: mycvs = 
00089        '$Id: psmile_mg_setup.F90 3016 2011-03-14 15:17:02Z hanke $'
00090 !
00091 !----------------------------------------------------------------------
00092 
00093 #ifdef VERBOSE
00094       print 9990, trim(ch_id), Grids(grid_id)%comp_id, range
00095 
00096       call psmile_flushstd
00097 #endif /* VERBOSE */
00098 
00099 #ifdef PRISM_ASSERTION
00100       if (Associated (Grids(grid_id)%mg_infos)) then
00101          call psmile_assert (__FILE__, __LINE__, &
00102                              "Multigrid info's already created for this grid")
00103       endif
00104 #endif
00105 !
00106 !  Initialization
00107 !
00108       ierror = 0
00109       gp => Grids(grid_id)
00110       my_range = range
00111 !
00112       comp_id = gp%comp_id
00113 !     gp%cyclic = .false.
00114 !
00115 ! Define maximal number of multigrid levels
00116 ! ndlev = 1: Fertig ?
00117 !
00118 
00119 !
00120 !  Special section for Gaussian reduced grids
00121 !
00122 !     The assumption is that each latitude band is described as a block on its own
00123 !     and that there is only one block per latitude.
00124 !
00125       simplified_grid = gp%grid_type == PRISM_Gaussreduced_regvrt
00126 !
00127       if ( gp%grid_type == PRISM_Gaussreduced_regvrt ) then
00128 
00129          my_range(1:2,1:2) = gp%gcorner_pointer%corner_shape(1:2,1:2)
00130          my_range(1:2,3)   = range(1:2,3)
00131 
00132 !        Add an extra level for psmile_mg_final_gauss2
00133 
00134          levbeg = 0
00135 
00136       else
00137 
00138 !        Generate multigrid sequence for really defined grids
00139 
00140          levbeg = 1
00141 
00142          if (gp%grid_type == PRISM_Irrlonlat_regvrt) then
00143 !           Full range is required for definition of virtual cells
00144             my_range (1:2, 1:ndim_2d) = gp%grid_shape (1:2, 1:ndim_2d)
00145          endif
00146 
00147       endif
00148 !
00149 !     Get number of levels to be generated
00150 
00151       len = MAXVAL (my_range(2,1:ndim_3d)-my_range(1,1:ndim_3d)+1)
00152 !
00153       ndlev = log (dble(len)) / log (2.0d0)
00154       if (2**ndlev .lt. len) ndlev = ndlev + 1
00155       ndlev = ndlev + 1
00156 
00157 #ifdef DEBUG
00158          PRINT *, TRIM(ch_id), ': psmile_mg_setup: we have ndlev', ndlev, 'to be generated'
00159          call psmile_flushstd
00160 #endif /* DEBUG */
00161 !
00162       Allocate (levdim(levbeg:ndim_3d, 1:ndlev), STAT = ierror)
00163       if ( ierror > 0 ) then
00164          ierrp (1) = ierror
00165          ierrp (2) = ndim_3d * (ndlev + (levbeg-1))
00166          ierror = PRISM_Error_Alloc
00167          call psmile_error ( ierror, 'levdim', &
00168                              ierrp, 2, __FILE__, __LINE__ )
00169          return
00170       endif
00171 !
00172       Allocate (gp%mg_infos(levbeg:ndlev), STAT = ierror)
00173       if ( ierror > 0 ) then
00174          ierrp (1) = ierror
00175          ierrp (2) = ndlev + (levbeg-1)
00176          ierror = PRISM_Error_Alloc
00177          call psmile_error ( ierror, 'gp%mg_infos', &
00178                              ierrp, 2, __FILE__, __LINE__ )
00179          return
00180       endif
00181 !
00182 !  Initialize Pointers in structure Grids(grid_id)%mg_infos
00183 !
00184       do lev = levbeg, ndlev
00185          Nullify (gp%mg_infos(lev)%real_arrays)
00186          Nullify (gp%mg_infos(lev)%double_arrays)
00187 #if defined ( PRISM_QUAD_TYPE )
00188          Nullify (gp%mg_infos(lev)%quad_arrays)
00189 #endif
00190       end do
00191 
00192       gp%nlev = ndlev
00193       gp%ijk0 (:) = my_range(1,:)
00194 !
00195 !-----------------------------------------------------------------------
00196 !     Allocate and generate grid functions of first level "1"
00197 !     using the corner volumes.
00198 !     The coarse levels "2:ndlev" are generated using the data of
00199 !     the previously generated multigrid level.
00200 !-----------------------------------------------------------------------
00201 !
00202 !     Create first level
00203 !
00204       lev = 1
00205 !
00206       levdim (1:ndim_3d, lev) = my_range(2,1:ndim_3d)-my_range(1,1:ndim_3d)
00207       gp%mg_infos(lev)%levdim = levdim (1:ndim_3d, lev)
00208 !
00209       call psmile_mg_first_level (grid_id, my_range, &
00210                                   gp%mg_infos(lev),  &
00211                                   tol, simplified_grid, ierror)
00212       if (ierror /= 0) return
00213 !
00214 !     For all coarser levels
00215 
00216          do lev = 2, ndlev
00217          levf = lev - 1
00218 
00219 !     ... Compute dimensions of coarser level "lev"
00220 !
00221          icoarse (:) = 2
00222 !
00223             do j = 1, ndim_3d
00224             n = levdim(j,levf) + 1
00225 !
00226             if (n .eq. 1) then
00227                icoarse (j) = 1
00228                levdim (j,lev) = levdim (j,levf)
00229             else if ((n/2) * 2 == n) then
00230                levdim (j,lev) = n/2 - 1
00231             else
00232 !              add a dummy line
00233                levdim (j,lev) = n/2
00234             endif
00235             end do
00236 !
00237 !     ... Create level "lev" from finer level "levf" = "lev-1"
00238 !
00239             gp%mg_infos(lev)%levdim = levdim (1:ndim_3d, lev)
00240 
00241             call psmile_mg_coars_level (grid_id,           &
00242                                         gp%mg_infos(levf), &
00243                                         gp%mg_infos(lev),  &
00244                                         icoarse, ierror)
00245             if (ierror /= 0) return
00246 !
00247 !     if (levdim (*, lev) = 0 break
00248 
00249          end do ! for all levels
00250 
00251 #ifdef PRISM_ASSERTION
00252       if (levdim (1, ndlev) /= 0 .or. &
00253           levdim (2, ndlev) /= 0 .or. &
00254           levdim (3, ndlev) /= 0) then
00255          print *, 'ndlev', ndlev
00256          print *, 'levdim(:, 1)', levdim (:, 1)
00257          print *, 'levdim(:, n)', levdim (:, ndlev)
00258          call psmile_assert (__FILE__, __LINE__, &
00259                              "incorrect coarsest levdim")
00260       endif
00261 #endif
00262 
00263       Deallocate (levdim)
00264 !
00265 !=======================================================================
00266 !     Allocate MG info for final grid in Gaussreduced storage.
00267 !     This final level is stored as level 0 and the data is
00268 !     computed using the really defined corner volumes.
00269 !
00270 !     Note: Since the face info "gp%face" has to be used
00271 !           in routine PSMILe_mg_final_gauss2_type,
00272 !           the data is generated for the entire grid !
00273 !
00274 !     Note: my_range(:,3) is set to gp%grid_shape(1,3)
00275 !           since this level is only used for lonlat part of
00276 !           GaussReduced grid
00277 !=======================================================================
00278 !
00279       if ( gp%grid_type == PRISM_Gaussreduced_regvrt ) then
00280          lev = 0
00281 !
00282          my_range      = gp%grid_shape
00283          my_range(2,3) = gp%grid_shape(1,3)
00284 
00285          gp%mg_infos(lev)%levdim = my_range(2,1:ndim_3d)-my_range(1,1:ndim_3d)
00286          simplified_grid = .false.
00287 
00288          call psmile_mg_first_level (grid_id, my_range,   &
00289                                      gp%mg_infos(lev), &
00290                                      tol, simplified_grid, ierror)
00291          if (ierror /= 0) return
00292       endif
00293 !
00294 !=======================================================================
00295 !
00296 !=======================================================================
00297 !
00298       call psmile_mg_get_cyclic (grid_id, my_range, tol, ierror)
00299 !
00300 !===> All done
00301 !
00302 #ifdef VERBOSE
00303       print 9980, trim(ch_id), ierror
00304       call psmile_flushstd
00305 #endif /* VERBOSE */
00306 !
00307 #ifdef VERBOSE
00308 
00309 9990 format (1x, a, ': psmile_mg_setup: comp_id', i3, ', range ', 6i6)
00310 9980 format (1x, a, ': psmile_mg_setup: eof ierror =', i3)
00311 
00312 #endif /* VERBOSE */
00313 
00314       end subroutine PSMILe_MG_setup

Generated on 18 Mar 2011 for Oasis4 by  doxygen 1.6.1