psmile_mg_final_prev_2d_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_final_prev_2d_real
00008 !
00009 ! !INTERFACE:
00010 
00011       subroutine psmile_mg_final_prev_2d_real (grid_id, nlev,        &
00012                       lstijk, xyz, found, newijk, nc,                &
00013                       corners1, corners2, corner_shape, nbr_corners, &
00014                       tol, ierror)
00015 !
00016 ! !USES:
00017 !
00018       use PRISM_constants
00019 !
00020       use PSMILe, dummy_interface => PSMILe_MG_final_prev_2d_real
00021 
00022       Implicit none
00023 !
00024 ! !INPUT PARAMETERS:
00025 !
00026       Integer, Intent (In)            :: grid_id
00027 !
00028 !     Grid Id for which the donor cells should be searched.
00029 !
00030       Integer, Intent (In)            :: nlev
00031 !
00032 !     Total number of levels
00033 !
00034       Integer, Intent (In)            :: nc
00035 !
00036 !     Number of points to be searched.
00037 !
00038       Integer, Intent (In)            :: lstijk (ndim_2d, nc)
00039 !
00040 !     Last indices of cell on finest level "lev == 1".
00041 !     !!! This routine assumes that all parts on the corrsponding
00042 !     coarse grid cells on level "LEV+1" were already controlled and
00043 !     point "xyz" was not found.
00044 !     Note: "lstijk" is relative to "ijk0"
00045 !
00046       Real, Intent (In)               :: xyz (ndim_2d, nc)
00047 !
00048 !     Coordinates of the points to be searched
00049 !
00050       Integer, Intent (In)            :: corner_shape (2, ndim_2d)
00051 
00052 !     Dimension of corner coordinate arrays
00053 
00054       Integer, Intent (In)            :: nbr_corners
00055 
00056 !     Number of corners
00057 !     Note: This routine assumes nbr_corners == 4.
00058 
00059       Real,   Intent (In)             ::                 
00060          corners1 ( corner_shape(1,1):corner_shape(2,1), 
00061                     corner_shape(1,2):corner_shape(2,2), nbr_corners)
00062 
00063       Real,   Intent (In)             ::                 
00064          corners2 ( corner_shape(1,1):corner_shape(2,1), 
00065                     corner_shape(1,2):corner_shape(2,2), nbr_corners)
00066 
00067 !     Corner coordinates
00068 !
00069       Real, Intent (In)               :: tol
00070 !
00071 !     Absolute tolerance for search of "identical" points
00072 !     TOL >= 0.0
00073 !
00074 ! !OUTPUT PARAMETERS:
00075 !
00076       Integer, Intent (Out)           :: found (nc)
00077 !
00078 !     Was the point xyz found ?
00079 !     found = 0: Not found
00080 !     found > 0: Part of the cell where point XYZ was found.
00081 !
00082       Integer, Intent (Out)           :: newijk (ndim_2d, nc)
00083 !
00084 !     Indices on level LEV if found > 0 is returned.
00085 !
00086       Integer, Intent (Out)           :: ierror
00087 
00088 !     Returns the error code of PSMILE_mg_final_prev_2d_real;
00089 !             ierror = 0 : No error
00090 !             ierror > 0 : Severe error
00091 !
00092 ! !DEFINED PARAMETERS:
00093 !
00094 !  NTET = Number of triangles used to determine whether
00095 !         point is within the grid cell
00096 !  EPS  = Tolerance for determinate of deformed grid cells
00097 !
00098       Integer, Parameter              :: ntet = 3
00099 !
00100       Real, Parameter                 :: eps = 1.0d-9
00101       Real, Parameter                 :: rmxeps = 1.0d30
00102       Real, Parameter                 :: dzero = 0.0
00103 !
00104       Integer, Parameter              :: lev  = 1
00105       Integer, Parameter              :: levc = 2
00106       Logical, Parameter              :: wide = .true.
00107       Logical, Parameter              :: small = .false.
00108 !
00109 ! !LOCAL VARIABLES
00110 !
00111       Integer                         :: i, n
00112 
00113 !     ... for Grid
00114 
00115       Type (Enddef_mg), Pointer       :: mg_infos (:)
00116       Integer, Pointer                :: ijk0 (:)
00117 
00118 !     ... for levels
00119 
00120       Integer                         :: levd, levdbg, levu, levubg
00121       Integer                         :: nlev1
00122       Integer                         :: nold (nc, nlev-1)
00123       Integer                         :: ijk (ndim_2d, nc, nlev-1)
00124       Integer                         :: ignore (ndim_2d, nlev-1)
00125 !
00126 !     ... for tolerances
00127 !
00128       Real                            :: tol1
00129 !
00130 !     ... for locations controlled
00131 !
00132       Integer                         :: j, m, nt
00133 !
00134 !     ... Logical reference point and edges (constant)
00135 ! 
00136       Integer, Save                   :: ijkedg (2, ntet)
00137 !
00138 !     ... Reference point and edges and distances
00139 ! 
00140       Integer                         :: ind (ndim_2d)
00141       Real                            :: xyzpnt (ntet, ndim_2d), 
00142                                          xyzref (ntet, ndim_2d)
00143       Real                            :: xyzedg (ntet, ndim_2d, 2)
00144       Real                            :: d1, d2
00145       Real                            :: det (ntet)
00146       Real                            :: dnorm
00147 !
00148 ! !DESCRIPTION:
00149 !
00150 ! Subroutine "PSMILe_MG_final_prev_2d_real" searches for the donor cell
00151 ! of points "xyz (*, 1:nc)". The points was last found on final level
00152 ! in donor cell "lstijk (*, 1:nc)". 
00153 ! If the i-th point is found in another cell of the real grid,
00154 ! "found(i)" > 0 is returned and
00155 ! "newijk (*, i)" returns the donor cell index on final level.
00156 !
00157 ! !REVISION HISTORY:
00158 !
00159 !   Date      Programmer   Description
00160 ! ----------  ----------   -----------
00161 ! 12.03.07    H. Ritzdorf  created
00162 !
00163 !EOP
00164 !----------------------------------------------------------------------
00165 !
00166 !  $Id: psmile_mg_final_prev_2d_real.F90,v 1.1.2.2 2008/12/08 18:36:56 ritzdorf Exp $
00167 !  $Author: ritzdorf $
00168 !
00169    Character(len=len_cvs_string), save :: mycvs = 
00170        '$Id: psmile_mg_final_prev_2d_real.F90,v 1.1.2.2 2008/12/08 18:36:56 ritzdorf Exp $'
00171 !
00172 !----------------------------------------------------------------------
00173 !
00174 !  Relative indices of triangles
00175 !
00176 !     The cell is split into 3 triangles
00177 !
00178       data ((ijkedg (j, n), j = 1, 2), n = 1, ntet) &
00179            / 2, 4,  3, 1,  4, 2/
00180 !             1      2      3
00181 
00182 !----------------------------------------------------------------------
00183 !
00184 !  Initialization
00185 !
00186 #ifdef VERBOSE
00187       print 9990, trim(ch_id), nc
00188 
00189       call psmile_flushstd
00190 #endif /* VERBOSE */
00191 !
00192       ierror = 0
00193 !
00194       mg_infos => Grids(grid_id)%mg_infos
00195       ijk0     => Grids(grid_id)%ijk0
00196 
00197       nlev1 = nlev - 1
00198       tol1 = tol + 1.0
00199 !
00200 #ifdef PRISM_ASSERTION
00201       if (levc >= nlev) then
00202          call psmile_assert (__FILE__, __LINE__, 'incorrect level')
00203       endif
00204 !
00205       if (tol < 0.0) then
00206          call psmile_assert (__FILE__, __LINE__, &
00207                              "tol must be >= 0.0")
00208       endif
00209 !
00210 !cdir vector
00211          do i = 1, nc
00212          if (lstijk(1,i)+ijk0(1) < corner_shape(1,1) .or. &
00213              lstijk(1,i)+ijk0(1) > corner_shape(2,1) .or. &
00214              lstijk(2,i)+ijk0(2) < corner_shape(1,2) .or. &
00215              lstijk(2,i)+ijk0(2) > corner_shape(2,2) ) then
00216             exit
00217          endif
00218          end do
00219 !
00220       if (i <= nc) then
00221          print *, 'i, lstijk', i, lstijk (:, i), ijk0
00222          print *, 'corner_shape', corner_shape
00223          call psmile_assert (__FILE__, __LINE__, &
00224                              'wrong index')
00225       endif
00226 #endif
00227 !
00228          do levd = levc, nlev1
00229          nold (:, levd) = 0 ! not clear to which part "lstijk" belongs
00230          end do
00231 !
00232 !===> ... Compute indices on the coarser levels
00233 !         for coarsening factor 2 !
00234 !
00235          do i = 1, ndim_2d
00236          if (mg_infos(lev )%levdim(i) /= &
00237              mg_infos(levc)%levdim(i) ) then
00238 !           Note: Calling routines have controlled cells
00239 !                (lstijk()-1:lstijk()+1)
00240 !           Thus index on level levc cannot lie on a coarse grid line
00241             ijk (:, :, levc) = lstijk (:, :) / 2
00242          else
00243             ijk (:, :, levc) = lstijk (:, :)
00244          endif
00245          end do
00246 !
00247          do levd = levc+1, nlev1
00248             do i = 1, ndim_2d
00249             if (mg_infos(levd  )%levdim(i) /= &
00250                 mg_infos(levd-1)%levdim(i) ) then
00251 !
00252 !              make sure that ijk lies on coarse grid line
00253 !
00254                ijk (i, :, levd) = (ijk (i, :, levd-1) / 4) * 2
00255             else
00256                ijk (i, :, levd) = ijk (i, :, levd-1)
00257             endif
00258             end do
00259          end do
00260 !
00261 !---------------------------------------------------------------------
00262 !     Go down in the level hierarchie
00263 !
00264 !     TODO: transfer nc loop into PSMILe_mg_control_cell_2d_real
00265 !           Use mask for points to be controlled and/or
00266 !           gather/scatter of points to be controlled.
00267 !
00268 !     Note: The "wide" control may cause some additional work
00269 !           (repeated control of fine grid cells) 
00270 !           at 2**i boundaries.
00271 !           Otherwise, the "wide" control may find the correct
00272 !           cell faster instead of looping till to the coarsest level.
00273 !           It's not totally clear, whether "small" control would
00274 !           be better should.
00275 !           Should performance control done with example
00276 !           "simple-orca-atmland" since it generates many controls.
00277 !           Possibly, adaptive setting of "wide" or "small" control.
00278 !---------------------------------------------------------------------
00279 !
00280 loop_n: do n = 1, nc
00281 
00282       levdbg = levc
00283 
00284 !     Define cells to be ignored
00285       ignore (:, lev)  = lstijk (:, n)
00286 !
00287          do i = 1, ndim_2d
00288             do levd = levc, nlev1
00289             if (mg_infos(levd-1)%levdim(i) > &
00290                 mg_infos(levd  )%levdim(i)) then
00291                ignore (i, levd) = ignore (i, levd-1) / 2
00292             else
00293                ignore (i, levd) = ignore (i, levd-1)
00294             endif
00295             end do
00296          end do
00297 !
00298 100   continue
00299 !
00300          do levd = levdbg, nlev1
00301 !
00302          call psmile_mg_control_cell_2d_real (                   &
00303                    mg_infos(levd)%real_arrays%chmin(1)%vector, &
00304                    mg_infos(levd)%real_arrays%chmin(2)%vector, &
00305                    mg_infos(levd)%real_arrays%chmax(1)%vector, &
00306                    mg_infos(levd)%real_arrays%chmax(2)%vector, &
00307                    mg_infos(levd)%real_arrays%midp (1)%vector, &
00308                    mg_infos(levd)%real_arrays%midp (2)%vector, &
00309                    mg_infos(levd)%levdim,                        &
00310                    ijk(1, n, levd), xyz(:,n), nold(n, levd),     &
00311                    ignore (1, levd), wide, found (n), newijk (:, n))
00312 !
00313          if (found (n) > 0) then
00314             go to 1990
00315          endif
00316 !
00317          end do
00318 !
00319 !===> Not found
00320 !
00321       cycle loop_n
00322 !
00323 !---------------------------------------------------------------------
00324 !     Up again; startpoint is newijk on level "levd"
00325 !---------------------------------------------------------------------
00326 !
00327 1990  nold (n, levd) = found (n)
00328 !
00329       levdbg = levd
00330       levubg = levd - 1
00331 !
00332       nold (n, levubg) = 0
00333 !
00334          do i = 1, ndim_2d
00335          if (mg_infos(levubg  )%levdim(i) > &
00336              mg_infos(levubg+1)%levdim(i)) then
00337             ijk (i, n, levubg) = min (newijk(i,n)*2, &
00338                                       mg_infos(levubg)%levdim(i))
00339          else
00340             ijk (i, n, levubg) = newijk (i,n)
00341          endif
00342          enddo
00343 !
00344 1995  continue
00345 !
00346          do levu = levubg, lev, -1
00347 !
00348 2000     continue
00349 !
00350          call psmile_mg_control_cell_2d_real (                   &
00351                    mg_infos(levu)%real_arrays%chmin(1)%vector, &
00352                    mg_infos(levu)%real_arrays%chmin(2)%vector, &
00353                    mg_infos(levu)%real_arrays%chmax(1)%vector, &
00354                    mg_infos(levu)%real_arrays%chmax(2)%vector, &
00355                    mg_infos(levu)%real_arrays%midp (1)%vector, &
00356                    mg_infos(levu)%real_arrays%midp (2)%vector, &
00357                    mg_infos(levu)%levdim,                        &
00358                    ijk(1, n, levu), xyz(:,n), nold(n, levu),     &
00359                    ignore (1, levu), small, found(n), newijk (:,n))
00360 !
00361          if (found(n) == 0) then
00362             if (levu < levd-1) then
00363 !
00364 !===> ... go back to the previous level; and try again
00365 !
00366                levubg = levu + 1
00367                go to 1995
00368             else
00369 !
00370 !===> ... go down
00371 !
00372                go to 100
00373             endif
00374 !
00375          else if (levu > lev) then
00376 !           Not the finest level
00377             nold (n, levu) = found (n)
00378 !
00379 !           Initialize search on next finer level "levu-1"
00380 !
00381             nold (n, levu-1) = 0
00382 !
00383                do i = 1, ndim_2d
00384                if (mg_infos(levu-1)%levdim(i) > &
00385                    mg_infos(levu  )%levdim(i)) then
00386                   ijk (i, n, levu-1) = min (newijk(i,n)*2, &
00387                                             mg_infos(levu-1)%levdim(i))
00388                else
00389                   ijk (i, n, levu-1) = newijk (i,n)
00390                endif
00391                enddo
00392 !
00393          else ! levu == lev
00394 !           Finest level
00395 !-----------------------------------------------------------------------
00396 !           Point "n" was found in box newijk (*, n)
00397 !           Is the point contained in the real corner cell ?
00398 !-----------------------------------------------------------------------
00399 !
00400 !===>       Compute reference points, corners and edges of transformed
00401 !           triangles.
00402 !
00403                ind (:) = newijk (:, n) + ijk0 (1:ndim_2d)
00404 !
00405                do nt = 1, ntet
00406                xyzref (nt, 1) = corners1 (ind(1), ind(2), nt)
00407                xyzref (nt, 2) = corners2 (ind(1), ind(2), nt)
00408 !
00409                xyzpnt (nt, 1) = xyz (1, n) - xyzref (nt, 1)
00410                xyzpnt (nt, 2) = xyz (2, n) - xyzref (nt, 2)
00411 !
00412                   do m = 1, 2
00413                   xyzedg (nt, 1, m) = corners1 (ind(1), ind(2), &
00414                                                 ijkedg(m, nt)) &
00415                                     - xyzref (nt, 1)
00416 
00417                   xyzedg (nt, 2, m) = corners2 (ind(1), ind(2), &
00418                                                 ijkedg(m, nt)) &
00419                                     - xyzref (nt, 2)
00420                   end do
00421                end do ! nt
00422 !
00423 !===> Solve bilinear system; compute spat product
00424 !
00425 !   (xyzedg(*,1), xyzedg(*,2)) (x) = xyzpnt
00426 !
00427             det(:) = xyzedg(:, 1,1)*xyzedg(:, 2,2) &
00428                    - xyzedg(:, 1,2)*xyzedg(:, 2,1)
00429 !
00430 #define ALLOW_DEGRADED_CELL
00431 #ifdef ALLOW_DEGRADED_CELL
00432 !
00433 ! ??? ist das koscher ?? wird d1(nt), d2(nt), d3(nt) == 0
00434 !
00435                do nt = 1, ntet
00436                dnorm = abs(xyzedg(nt,1,1)) + abs(xyzedg(nt,2,1)) + &
00437                        abs(xyzedg(nt,1,2)) + abs(xyzedg(nt,2,2))
00438 
00439                if (abs(det(nt)) < eps*dnorm*dnorm .or. dnorm == dzero) then
00440                   det (nt) = sign (rmxeps, det(nt))
00441                else
00442                   det (nt) = 1.0 / det (nt)
00443                endif
00444                end do ! nt
00445 
00446 #else 
00447 
00448 loop_n:        do nt = 1, ntet
00449                dnorm = abs(xyzedg(nt,1,1)) + abs(xyzedg(nt,2,1)) + &
00450                        abs(xyzedg(nt,1,2)) + abs(xyzedg(nt,2,2))
00451 
00452                if (abs(det(i, nt)) < eps*dnorm*dnorm .or. &
00453                    dnorm(i,nt) == dzero) then
00454                   det (i, nt) = dnorm * 1e-25
00455 ! eigentlich exit loop_n und print_degraded cell
00456 ! ist bei vektorisierung verschwunden
00457 ! sollte man in part_list suchen
00458                endif
00459                end do ! nt
00460 !
00461 #ifdef PRINT_DEGRADED_CELL
00462             if (nt < ntet) then
00463 !
00464 !===> cell is degraded
00465 !
00466                print 9960, trim(ch_id), grid_id, newijk(:, n), &
00467                         (corners1(ind(1), ind(2), nt),         &
00468                          corners2(ind(1), ind(2), nt), nt = 1, nbr_corners)
00469 !
00470                   do nt = 1, ntet
00471                   if (abs(det(nt)) < eps) then
00472                      print 9950, nt, det (nt), dnorm, &
00473                        xyzedg (nt,1, 1), xyzedg (nt,1, 2), &
00474                        xyzedg (nt,2, 1), xyzedg (nt,2, 2)
00475                   endif
00476                   end do
00477 !
00478                nicht gefunden fnd (i) = .false. versucht, durch
00479                ganz kleine Determinante zu loesen
00480             endif
00481 #endif /* PRINT_DEGRADED_CELL */
00482 !
00483             det (:) = 1.0 / det (:)
00484 !
00485 #endif /* ALLOW_DEGRADED_CELL */
00486 !
00487 !===>          Is the point contained in a triangle ?
00488 !
00489                 do nt = 1, ntet
00490                 d1 = (xyzpnt(nt,1)*xyzedg(nt,2,2)- &
00491                       xyzpnt(nt,2)*xyzedg(nt,1,2)) * det (nt)
00492                 d2 = (xyzpnt(nt,2)*xyzedg(nt,1,1)- &
00493                       xyzpnt(nt,1)*xyzedg(nt,2,1)) * det (nt)
00494 !
00495                 if (min(d1, d2) >= -tol .and. &
00496                     max(d1,dzero) + max(d2,dzero) <= tol1) exit
00497                 end do ! ntet
00498 !
00499             if (nt > ntet) then
00500 !                 Point was not found in the real cell.
00501 !                 Search again on same level.
00502 !
00503                nold (n, levu) = found (n)
00504 !
00505                go to 2000
00506             endif
00507          endif
00508          end do ! levu
00509 !
00510          end do loop_n
00511 !
00512 !===> All done
00513 !
00514 #ifdef VERBOSE
00515       print 9980, trim(ch_id)
00516 
00517       call psmile_flushstd
00518 #endif /* VERBOSE */
00519 !
00520       return
00521 !
00522 !  Formats:
00523 !
00524 
00525 9990 format (1x, a, ': psmile_mg_final_prev_2d_real: nc', i5)
00526 9980 format (1x, a, ': psmile_mg_final_prev_2d_real: eof')
00527 
00528 #ifdef PRINT_DEGRADED_CELL
00529 9960 format (1x, a, ': psmile_MG_final_prev_2d_real: grid id =', i5, &
00530             /1x,  ' Grid cell (', i4, ',', i4,                    &
00531                  ') is degraded! Cell coordinates are:', 1p,      &
00532             4 (/1x, '(', 1 (e17.9, ','), e17.9, ')'))
00533 9950 format (1x, i1, '-th spawn; det =', 1p, e17.9, ' (', e17.9, &
00534              ') of', 2 (/1x, 2e17.9, ','))
00535 #endif
00536 
00537       end subroutine psmile_mg_final_prev_2d_real

Generated on 18 Mar 2011 for Oasis4 by  doxygen 1.6.1