psmile_mg_next_level_1d_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_next_level_1d_real
00008 !
00009 ! !INTERFACE:
00010 
00011       subroutine psmile_mg_next_level_1d_real ( &
00012                            grid_id, idim, lev, nlev, &
00013                            chmin, chmax, midp, levdim,    &
00014                            found, loc, coords, ibeg, iend, &
00015                            ijkinc, ijkcoa, ierror)
00016 !
00017 ! !USES:
00018 !
00019       use PRISM_constants
00020 !
00021       use PSMILe, dummy_interface => psmile_mg_next_level_1d_real
00022 
00023       implicit none
00024 !
00025 ! !INPUT PARAMETERS:
00026 !
00027       Integer, Intent (In)            :: grid_id
00028 
00029 !     Info on the component in which the donor
00030 !     should be searched.
00031 
00032       Integer, Intent (In)            :: idim
00033 
00034 !     Dimension in which should be searched
00035 
00036       Integer, Intent (In)            :: lev
00037 
00038 !     Level number of the next grid
00039 
00040       Integer, Intent (In)            :: nlev
00041 
00042 !     Total number of levels
00043 
00044       Integer, Intent (In)            :: levdim
00045 
00046 !     Dimension of chmin, chmax and midp
00047 
00048       Integer, Intent (InOut)         :: ibeg
00049 
00050 !     Input  value: First index in "coords" to be searched
00051 !     Output value: First index in "coords" for which a cell was found
00052 !
00053       Integer, Intent (InOut)         :: iend
00054 
00055 !     Input  value: Last  index in "coords" to be searched
00056 !                   Dimension of "found" and "location".
00057 !     Output value: Last  index in "coords" for which a cell was found
00058 
00059       Real, Intent (In)               :: chmin (0:levdim)
00060 
00061 !     Minimum of grid coordinates per grid cell
00062 
00063       Real, Intent (In)               :: chmax (0:levdim)
00064 
00065 !     Maximum of grid coordinates per grid cell
00066 
00067       Real, Intent (In)               :: midp (0:levdim)
00068 
00069 !     Mid point of the cell
00070 
00071       Integer, Intent (InOut)         :: found (iend)
00072 
00073 !     Finest level number on which a grid cell was found for point I.
00074 !     Level number < -1: Point was not found and
00075 !                        and last level number was (-found(i,j,k))
00076 !     Level number = (-nlev+1): Never found (input value)
00077 
00078       Integer, Intent (InOut)         :: loc (iend)
00079 
00080 !     Indices of the grid cell in which the point was found.
00081 
00082       Real, Intent (In)               :: coords (iend)
00083 
00084 !     Coordinates to be searched
00085 
00086       Integer, Intent (In)            :: ijkinc
00087 
00088 !     Increment
00089 
00090       Integer, Intent (In)            :: ijkcoa
00091 !
00092 !     Coarsening
00093 !
00094 ! !OUTPUT PARAMETERS:
00095 !
00096       integer, Intent (Out)           :: ierror
00097 
00098 !     Returns the error code of PSMILe_MG_coars_level;
00099 !             ierror = 0 : No error
00100 !             ierror > 0 : Severe error
00101 !
00102 ! !DEFINED PARAMETERS:
00103 !
00104       Integer, parameter              :: ntry1 = 3
00105       Integer, parameter              :: ntry3 = 3
00106       Integer, parameter              :: ndtry = 5
00107       Real,    parameter              :: remax = 1.0e20
00108 !
00109 ! !LOCAL VARIABLES
00110 
00111 !     ... for levels
00112 
00113       Integer                         :: levc
00114 
00115 !     ... for locations searched
00116 
00117       Integer                         :: i, ibegl, n, nprev
00118       Integer                         :: ifound, nmin(1)
00119       Integer                         :: ijkf, ijkold, newijk
00120       Integer                         :: ijkdst (ndtry)
00121       Real                            :: dist (ndtry)
00122 !
00123 #ifdef DEBUG
00124 !     ... for locations searched
00125 !
00126       Integer                      :: nfnd (0:4)
00127 #endif /* DEBUG */
00128 !
00129 ! !DESCRIPTION:
00130 !
00131 ! Subroutine "psmile_mg_next_level_1d_real" searches the donor cells
00132 ! on the next MG grid for the subgrid coords by the sending process.
00133 !
00134 !
00135 ! !REVISION HISTORY:
00136 !
00137 !   Date      Programmer   Description
00138 ! ----------  ----------   -----------
00139 ! 03.07.21    H. Ritzdorf  created
00140 !
00141 !EOP
00142 !----------------------------------------------------------------------
00143 !
00144 !  $Id: psmile_mg_next_level_1d_real.F90 2912 2011-01-25 09:21:26Z coquart $
00145 !  $Author: coquart $
00146 !
00147    Character(len=len_cvs_string), save :: mycvs = 
00148        '$Id: psmile_mg_next_level_1d_real.F90 2912 2011-01-25 09:21:26Z coquart $'
00149 !
00150 !----------------------------------------------------------------------
00151 !
00152 !  Initialization
00153 !
00154 #ifdef VERBOSE
00155       print 9990, trim(ch_id), lev, ibeg, iend
00156 
00157       call psmile_flushstd
00158 #endif /* VERBOSE */
00159 !
00160 #ifdef PRISM_ASSERTION
00161 #endif
00162 !
00163       ierror = 0
00164       levc = lev + 1
00165 !
00166 #ifdef DEBUG
00167       nfnd (0) = 0
00168       nfnd (1) = 0
00169       nfnd (2) = 0
00170       nfnd (3) = 0
00171       nfnd (4) = 0
00172 
00173 !     print *, 'chmin', chmin(0), chmin (levdim)
00174 !     print *, 'chmax', chmax(0), chmax (levdim)
00175 !     print *, 'midp ', midp (0), midp  (levdim)
00176 #endif /* DEBUG */
00177 
00178 #ifdef DEBUGX
00179       print *, 'begin ---'
00180       do i = ibeg, iend
00181          print *, 'i, coord, found', i, coords (i), loc(i), found (i)
00182       end do
00183 #endif
00184 !
00185 !-----------------------------------------------------------------------
00186 !     Look in the fine parts of the coarse grid cell loc(i)
00187 !-----------------------------------------------------------------------
00188 !
00189       nprev = 0
00190       ibegl = ibeg
00191 !
00192 !===> ... Look for the next cell to be controlled
00193 !
00194       do while (ibegl <= iend)
00195 !cdir vector
00196          do i = ibegl, iend, ijkinc
00197             if (found (i) == levc) go to 11
00198          end do
00199 !
00200          if (i .lt. iend+ijkinc) then
00201             i = iend
00202             if (found (i) == levc) go to 11
00203          endif
00204 !
00205          exit
00206 !
00207 !===> ... Look in the fine parts of cell loc(i)
00208 !
00209 11       continue
00210 !
00211          ijkf = min (loc(i) * ijkcoa, levdim)
00212 !
00213          ijkdst (1) = max(ijkf - 1, 0)
00214          ijkdst (2) = ijkf
00215          ijkdst (3) = min(ijkf + 1, levdim)
00216 !
00217          do n = 1, ntry1
00218             if (coords(i) >= chmin(ijkdst(n)) .and. &
00219                 coords(i) <= chmax(ijkdst(n))) then
00220                dist (n) = abs (coords(i) - midp (ijkdst(n)))
00221             else
00222                dist (n) = remax
00223             endif
00224          end do
00225 !
00226 !===> ... Look for the minimum distance
00227 !
00228          nmin = MINLOC (dist(1:ntry1))
00229 #ifdef MINLOCFIX
00230          if (nmin(1).eq.0) nmin=1
00231 #endif /* MINLOCFIX */
00232 !
00233          if (dist(nmin(1)) .ne. remax) then
00234             found (i)  = lev
00235             loc (i) = ijkdst (nmin(1))
00236 !
00237 #ifdef DEBUG
00238             nfnd (1) = nfnd (1) + 1
00239 #endif /* DEBUG */
00240             go to 95
00241 !
00242          else
00243 !
00244             if (levc == nlev) then
00245                found (i) = - found(i)
00246 #ifdef DEBUG
00247                nfnd (0) = nfnd (0) + 1
00248 #endif /* DEBUG */
00249                go to 95
00250             endif
00251          endif
00252 !
00253 !-----------------------------------------------------------------------
00254 !          Look in the neigbourhood of the coarse grid cell
00255 !          loc(i)
00256 !-----------------------------------------------------------------------
00257 !
00258          ijkdst (ntry1+1) = max(ijkf-2, 0)
00259          ijkdst (ntry1+2) = min(ijkf+2, levdim)
00260 !
00261          do n = ntry1+1, ndtry
00262             if (coords(i) >= chmin(ijkdst(n)) .and. &
00263                 coords(i) <= chmax(ijkdst(n))) then
00264                dist (n) = abs (coords(i) - midp (ijkdst(n)))
00265             else
00266                dist (n) = remax
00267             endif
00268          end do
00269 !
00270 !===> ... Look for the minimum distance
00271 !
00272          nmin = MINLOC (dist(ntry1+1:ndtry)) + ntry1
00273 #ifdef MINLOCFIX
00274          if (nmin(1).eq.ntry1) nmin=ntry1 + 1
00275 #endif /* MINLOCFIX */
00276 !
00277          if (dist(nmin(1)) .ne. remax) then
00278             found (i)  = lev
00279             loc (i) = ijkdst (nmin(1))
00280 !
00281 #ifdef DEBUG
00282             nfnd (2) = nfnd (2) + 1
00283 #endif /* DEBUG */
00284 !
00285          else
00286 !
00287             nprev = nprev + 1
00288          endif
00289 !
00290 !===> ... Start index of the next search
00291 !
00292 95       if (i == iend) exit
00293          ibegl = min (iend, i+ijkinc)
00294 
00295       end do ! while (ibegl <= iend)
00296 !
00297 !===> ... Have points to be controlled o a coarser level ?
00298 !
00299       if (nprev == 0) go to 20
00300 !
00301 !-----------------------------------------------------------------------
00302 !          Some points were not found.
00303 !          Try to interpolate the fine point a from neighbouring points
00304 !-----------------------------------------------------------------------
00305 !
00306       ibegl = ibeg+ijkinc
00307 !
00308       do while (ibegl <= iend)
00309 !cdir vector
00310          do i = ibegl, iend-ijkinc, ijkinc
00311             if (found (i)        == levc .and. &
00312                 found (i-ijkinc) == lev  .and. &
00313                found (i+ijkinc) == lev) go to 211
00314          end do
00315 !
00316          if (i .lt. iend) then
00317             i = iend - ijkinc
00318             if (found (i)        == levc .and. &
00319                 found (i-ijkinc) == lev  .and. &
00320                found (i+ijkinc) == lev) go to 211
00321          endif
00322 !
00323          exit
00324 !
00325 !===> ... Interpolate cell IJKF and
00326 !         look in the neighbourhood of cell IJKF
00327 !
00328 211      continue
00329          ijkf   = min ((loc (i-ijkinc) + loc (i+ijkinc)) / 2, levdim)
00330 !
00331          ijkold = min (loc(i) * ijkcoa, levdim)
00332 !
00333          if (ijkold == ijkf) go to 260
00334 !
00335          ijkdst (1) = max(ijkf - 1, 0)
00336          ijkdst (2) = ijkf
00337          ijkdst (3) = min(ijkf + 1, levdim)
00338 !
00339 !===> ... Compute distances to the cell midpoints
00340 !
00341 !cdir vector
00342          do n = 1, ntry3
00343             if (coords(i) >= chmin(ijkdst(n)) .and. &
00344                 coords(i) <= chmax(ijkdst(n))) then
00345                dist (n) = abs (coords(i) - midp (ijkdst(n)))
00346             else
00347                dist (n) = remax
00348             endif
00349          end do
00350 !
00351 !===> ... Look for the minimum distance
00352 !
00353          nmin = MINLOC (dist(1:ntry3))
00354 #ifdef MINLOCFIX
00355          if (nmin(1).eq.0) nmin=1
00356 #endif /* MINLOCFIX */
00357 !
00358          if (dist(nmin(1)) .ne. remax) then
00359             found (i)  = lev
00360             loc (i) = ijkdst (nmin(1))
00361 !
00362             nprev = nprev - 1
00363 !
00364 #ifdef DEBUG
00365             nfnd (3) = nfnd (3) + 1
00366 #endif /* DEBUG */
00367          endif
00368 !
00369 !===> ... Start index of the next search
00370 !
00371 260      if (i >= iend-ijkinc) exit
00372          ibegl = min (iend-ijkinc, i+ijkinc)
00373 !
00374       end do ! while (ibegl <= iend)
00375 !
00376       if (nprev == 0) go to 20
00377 
00378 !-----------------------------------------------------------------------
00379 !     Some points were still not found.
00380 !     Look again on the next coarser level whether the points
00381 !     are located in other cells.
00382 !-----------------------------------------------------------------------
00383 !
00384       ibegl = ibeg
00385 
00386       do while (ibegl <= iend)
00387 !
00388 !===> ... Look for the next cell to be controlled
00389 !
00390 !cdir vector
00391          do i = ibegl, iend, ijkinc
00392             if (found (i) == levc) go to 311
00393          end do
00394 !
00395          if (i < iend+ijkinc) then
00396             i = iend
00397             if (found (i) == levc) go to 311
00398          endif
00399 !
00400          exit
00401 !
00402 !===> ... Look in the coarser parts of cell loc(i)
00403 !
00404 311      continue
00405 #ifdef PRISM_ASSERTION
00406          if (loc(i) < 0) then
00407             print *, i, loc(i)
00408             call psmile_assert (__FILE__, __LINE__, 'incorrect loc(i)')
00409          endif
00410 #endif /* PRISM_ASSERTION */
00411 !
00412          if (lev+1 < nlev) then
00413             call psmile_mg_prev_levels_1d_real (grid_id, idim, lev, nlev, &
00414                               loc(i), coords(i), ifound, newijk)
00415 !
00416             if (ifound .gt. 0) then
00417                loc (i) = newijk
00418 !
00419                found (i) = lev
00420 #ifdef DEBUG
00421                nfnd (4) = nfnd (4) + 1
00422 #endif /* DEBUG */
00423             else
00424                found (i) = - found (i)
00425 #ifdef DEBUG
00426                nfnd (0) = nfnd (0) + 1
00427 #endif /* DEBUG */
00428             endif
00429          else
00430             found (i) = - found (i)
00431 #ifdef DEBUG
00432             nfnd (0) = nfnd (0) + 1
00433 #endif /* DEBUG */
00434          endif
00435 !
00436 !===> ...
00437 !
00438          nprev = nprev - 1
00439          if (nprev == 0) go to 20
00440 !
00441 !===> ... Start index of the next search
00442 !
00443          if (i == iend) exit
00444 
00445          ibegl = min (iend, i+ijkinc)
00446       end do ! while (ibegl <= iend)
00447 !
00448 !===> All done
00449 !
00450 20    continue
00451 
00452 #ifdef DEBUGX
00453       print *, 'end ---'
00454       do i = ibeg, iend
00455          print *, 'i, coord, found', i, coords (i), loc(i), found (i), chmin(loc(i)), chmax(loc(i))
00456       end do
00457 #endif
00458 !
00459 #ifdef DEBUG
00460       print 9970, trim(ch_id), lev, nfnd, ijkinc
00461 9970  format (1x, a, ': psmile_mg_next_level_1d_real: lev =', i3, &
00462               ': fnd =', 5i8, ', ijkinc ', 3i4)
00463 #endif /* DEBUG */
00464 
00465 #ifdef VERBOSE
00466       print 9980, trim(ch_id), lev
00467 
00468       call psmile_flushstd
00469 #endif /* VERBOSE */
00470 !
00471 !  Formats:
00472 !
00473 9990 format (1x, a, ': psmile_mg_next_level_1d_real: level', i3, &
00474                     ', ibeg, iend', 2i6)
00475 9980 format (1x, a, ': psmile_mg_next_level_1d_real: eof, level', i3)
00476 
00477       end subroutine psmile_mg_next_level_1d_real

Generated on 18 Mar 2011 for Oasis4 by  doxygen 1.6.1