psmile_mg_method_3d_dble.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_method_3d_dble
00008 !
00009 ! !INTERFACE:
00010 
00011       subroutine psmile_mg_method_3d_dble (                &
00012                            comp_info, nlev,                &
00013                            found, loc, range,              &
00014                            coords1, coords2, coords3,      &
00015                            shape, control,                 &
00016                            method_id,                      &
00017                            x_coords, y_coords, z_coords,   &
00018                            coords_shape,                   &
00019                            grid_valid_shape, cyclic,       &
00020                            chmin1, chmin2, chmin3,         &
00021                            chmax1, chmax2, chmax3,         &
00022                            midp1,  midp2,  midp3,          &
00023                            tol, ierror)
00024 !
00025 ! !USES:
00026 !
00027       use PRISM_constants
00028 !
00029       use PSMILe, dummy_interface => PSMILe_mg_method_3d_dble
00030 
00031       implicit none
00032 !
00033 ! !INPUT PARAMETERS:
00034 !
00035       Type (Enddef_comp), Intent (In) :: comp_info
00036 
00037 !     Info on the component in which the donor
00038 !     should be searched.
00039 
00040       Integer,          Intent (In)   :: nlev
00041 
00042 !     Total number of levels
00043 
00044       Integer,          Intent (In)   :: range (2, ndim_3d)
00045 
00046 !     Dimension of loc and found
00047 
00048       Integer,          Intent (In)   :: shape (2, ndim_3d)
00049 
00050 !     Dimension of coordinate arrays "coord1", "coord2", "coords3"
00051 !     which contain the coordinates to be searched.
00052 
00053       Integer,          Intent (InOut) :: found (range(1,1):range(2,1), 
00054                                                  range(1,2):range(2,2), 
00055                                                  range(1,3):range(2,3))
00056 
00057 !     Finest level number on which a grid cell was found for point i,j,k.
00058 !     Input :
00059 !     Level number < -1: Point was not found and
00060 !                        and last level number was (-found(i,j,k))
00061 !     Level number = -(nlev+1): Never found
00062 !     Output :
00063 !     found(i,j,k) = +1: Point (i,j,k) is located on a point
00064 !                        of the method grid.
00065 !     found(i,j,k) = -1: Point (i,j,k) is located in a cell
00066 !                        of the method grid.
00067 !     Otherwise, not contained in the method grid.
00068 
00069       Integer,          Intent (InOut) :: loc   (ndim_3d,               
00070                                                  range(1,1):range(2,1), 
00071                                                  range(1,2):range(2,2), 
00072                                                  range(1,3):range(2,3))
00073 
00074 !     Indices of the grid cell in which the point was found.
00075 !     The indices are relative to "shape".
00076 
00077       Double Precision, Intent (In)   :: coords1 (shape(1,1):shape(2,1), 
00078                                                   shape(1,2):shape(2,2), 
00079                                                   shape(1,3):shape(2,3))
00080       Double Precision, Intent (In)   :: coords2 (shape(1,1):shape(2,1), 
00081                                                   shape(1,2):shape(2,2), 
00082                                                   shape(1,3):shape(2,3))
00083       Double Precision, Intent (In)   :: coords3 (shape(1,1):shape(2,1), 
00084                                                   shape(1,2):shape(2,2), 
00085                                                   shape(1,3):shape(2,3))
00086 
00087 !     Coordinates to be searched
00088 
00089       Integer,          Intent (In)   :: control (2, ndim_3d)
00090 
00091 !     Input  value: index range in "coords" to be searched
00092 !     Output value: index range in "coords" for which a cell was found
00093 
00094       Integer,          Intent (In)   :: method_id
00095 
00096 !     Method id
00097 
00098       Integer,          Intent (In)   :: coords_shape (2, ndim_3d)
00099 
00100 !     Dimension of coordinates (method) x_coords, ...
00101 
00102       Double Precision, Intent (In)   :: x_coords(coords_shape(1,1): 
00103                                                   coords_shape(2,1), 
00104                                                   coords_shape(1,2): 
00105                                                   coords_shape(2,2), 
00106                                                   coords_shape(1,3): 
00107                                                   coords_shape(2,3))
00108       Double Precision, Intent (In)   :: y_coords(coords_shape(1,1): 
00109                                                   coords_shape(2,1), 
00110                                                   coords_shape(1,2): 
00111                                                   coords_shape(2,2), 
00112                                                   coords_shape(1,3): 
00113                                                   coords_shape(2,3))
00114       Double Precision, Intent (In)   :: z_coords(coords_shape(1,1): 
00115                                                   coords_shape(2,1), 
00116                                                   coords_shape(1,2): 
00117                                                   coords_shape(2,2), 
00118                                                   coords_shape(1,3): 
00119                                                   coords_shape(2,3))
00120 
00121 !     Coordinates of the method
00122 
00123       Integer,          Intent (In)   :: grid_valid_shape (2, ndim_3d)
00124 
00125 !     Specifies the valid block shape for the "ndim_3d"-dimensional block
00126 
00127 !     Dimension of chmin, chmax and midp
00128 
00129       Logical,          Intent (In)   :: cyclic (ndim_3d)
00130 
00131 !     Is this a (locally) cyclic coordinate in corresponding direction
00132 
00133       Double Precision, Intent (In)   :: chmin1 (grid_valid_shape(1,1)-1: 
00134                                                  grid_valid_shape(2,1),   
00135                                                  grid_valid_shape(1,2)-1: 
00136                                                  grid_valid_shape(2,2),   
00137                                                  grid_valid_shape(1,3)-1: 
00138                                                  grid_valid_shape(2,3))
00139       Double Precision, Intent (In)   :: chmin2 (grid_valid_shape(1,1)-1: 
00140                                                  grid_valid_shape(2,1),   
00141                                                  grid_valid_shape(1,2)-1: 
00142                                                  grid_valid_shape(2,2),   
00143                                                  grid_valid_shape(1,3)-1: 
00144                                                  grid_valid_shape(2,3))
00145       Double Precision, Intent (In)   :: chmin3 (grid_valid_shape(1,1)-1: 
00146                                                  grid_valid_shape(2,1),   
00147                                                  grid_valid_shape(1,2)-1: 
00148                                                  grid_valid_shape(2,2),   
00149                                                  grid_valid_shape(1,3)-1: 
00150                                                  grid_valid_shape(2,3))
00151 
00152 !     Minimum of grid coordinates per grid cell
00153 !
00154 ! chmin (i, j, k) contains the minimal value of bounding box of
00155 !              method cell ((i,j,k  ), (i+1,j,k  ), (i,j+1,k  ), (i+1,j+1,k  ),
00156 !                           (i,j,k+1), (i+1,j,k+1), (i,j+1,k+1), (i+1,j+1,k+1))
00157 !
00158 ! The first box
00159 ! chmin (range(1,1)-1,j,k) contains the minimal value of the bounding box
00160 !                        of virtual cell
00161 !       (array(range(1,1), j, k  ), array(range(1,1), j+1, k  ),
00162 !        array(range(1,1), j, k+1), array(range(1,1), j+1, k+1),
00163 !        bounding box of corner control volume of (range(1,1),j,k)
00164 !
00165 ! The last box
00166 ! chmin (range(2,1),  j,k) contains the minimal value of the bounding box
00167 !                        of virtual cell
00168 !       (array(range(2,1), j, k  ), array(range(2,1), j+1, k  ),
00169 !        array(range(2,1), j, k+1), array(range(2,1), j+1, k+1),
00170 !        bounding box of corner control volume of (range(2,1),j,k)
00171 !
00172 ! Corresponding values are contained for other virtual cells at block
00173 ! border.
00174 !
00175       Double Precision, Intent (In)   :: chmax1 (grid_valid_shape(1,1)-1: 
00176                                                  grid_valid_shape(2,1),   
00177                                                  grid_valid_shape(1,2)-1: 
00178                                                  grid_valid_shape(2,2),   
00179                                                  grid_valid_shape(1,3)-1: 
00180                                                  grid_valid_shape(2,3))
00181       Double Precision, Intent (In)   :: chmax2 (grid_valid_shape(1,1)-1: 
00182                                                  grid_valid_shape(2,1),   
00183                                                  grid_valid_shape(1,2)-1: 
00184                                                  grid_valid_shape(2,2),   
00185                                                  grid_valid_shape(1,3)-1: 
00186                                                  grid_valid_shape(2,3))
00187       Double Precision, Intent (In)   :: chmax3 (grid_valid_shape(1,1)-1: 
00188                                                  grid_valid_shape(2,1),   
00189                                                  grid_valid_shape(1,2)-1: 
00190                                                  grid_valid_shape(2,2),   
00191                                                  grid_valid_shape(1,3)-1: 
00192                                                  grid_valid_shape(2,3))
00193 
00194 
00195 !     Maximum of grid coordinates per grid cell
00196 
00197       Double Precision, Intent (In)   :: midp1  (grid_valid_shape(1,1)-1: 
00198                                                  grid_valid_shape(2,1),   
00199                                                  grid_valid_shape(1,2)-1: 
00200                                                  grid_valid_shape(2,2),   
00201                                                  grid_valid_shape(1,3)-1: 
00202                                                  grid_valid_shape(2,3))
00203       Double Precision, Intent (In)   :: midp2  (grid_valid_shape(1,1)-1: 
00204                                                  grid_valid_shape(2,1),   
00205                                                  grid_valid_shape(1,2)-1: 
00206                                                  grid_valid_shape(2,2),   
00207                                                  grid_valid_shape(1,3)-1: 
00208                                                  grid_valid_shape(2,3))
00209       Double Precision, Intent (In)   :: midp3  (grid_valid_shape(1,1)-1: 
00210                                                  grid_valid_shape(2,1),   
00211                                                  grid_valid_shape(1,2)-1: 
00212                                                  grid_valid_shape(2,2),   
00213                                                  grid_valid_shape(1,3)-1: 
00214                                                  grid_valid_shape(2,3))
00215 
00216 !     Mid point of the cell
00217 
00218       Double Precision, Intent (In)   :: tol
00219 !
00220 !     Absolute tolerance for search of "identical" points
00221 !     TOL >= 0.0
00222 !
00223 ! !OUTPUT PARAMETERS:
00224 !
00225       Integer,          Intent (Out)  :: ierror
00226 
00227 !     Returns the error code of PSMILE_mg_method_3d_dble;
00228 !             ierror = 0 : No error
00229 !             ierror > 0 : Severe error
00230 !
00231 ! !DEFINED PARAMETERS:
00232 !
00233 !  NREFD = Number of method coordinates to be controlled.
00234 !        = 3 ** ndim_3d
00235 !  NTET = Number of tetraeders used to determine whether
00236 !         point is within the grid cell
00237 !  EPS  = Tolerance for determinate of deformed grid cells
00238 !  val_direct  = Code for locations which should to be directly transferred
00239 !                to the destination process.
00240 !  val_coupler = Code for locations which should to be transferred
00241 !                to the coupler process.
00242 !
00243 #define USE6T
00244 #ifdef USE6T
00245       Integer, Parameter              :: ntet = 6
00246 #else
00247       Integer, Parameter              :: ntet = 4
00248 #endif
00249       Double Precision, Parameter     :: eps = 1.0d-9
00250       Double Precision, Parameter     :: rmxeps = 1.0d30
00251       Double Precision, Parameter     :: dzero = 0.0
00252 !
00253       Integer, Parameter              :: nrefd = 3 * 3 * 3
00254 !
00255       Integer, Parameter              :: val_direct  =  1
00256       Integer, Parameter              :: val_coupler = -1
00257 !
00258 !     ... for levels
00259 !
00260       Integer, Parameter              :: lev = 1
00261 !
00262 ! !LOCAL VARIABLES
00263 !
00264 !     ... for tolerances
00265 !
00266       Double Precision                :: tol1, tol2
00267 !
00268 !     ... for locations searched
00269 !
00270       Integer                         :: i, j, k
00271       Integer                         :: ibegl, iendl, jpart, n
00272       Integer                         :: ic (ndim_3d)
00273 !
00274 !     ... For locations controlled
00275 !
00276       Integer                         :: l, m
00277       Integer                         :: ijkctl (ndim_3d, nrefd)
00278       Integer                         :: ijkdst (ndim_3d, nrefd)
00279       Double Precision                :: dist (nrefd)
00280       Integer                         :: irange (2, ndim_3d)
00281 !
00282       Integer                         :: ii, jj, kk, nref
00283       Integer                         :: nmin (1)
00284 !   
00285 !     ... Local reference point and edges
00286 ! 
00287       Integer                         :: ijkref (ndim_3d, ntet)
00288       Integer                         :: ijkedg (ndim_3d, 3, ntet)
00289 !
00290       Double Precision                :: dble_huge
00291       Double Precision                :: xyzpnt (ndim_3d, ntet), 
00292                                          xyzref (ndim_3d, ntet)
00293       Double Precision                :: xyzedg (ndim_3d, 3, ntet)
00294       Double Precision                :: d1 (ntet), d2 (ntet), d3 (ntet)
00295       Double Precision                :: dnorm (ntet), det (ntet)
00296 !
00297 #ifdef DEBUG
00298 !     ... for locations searched
00299 !
00300       Integer                         :: nfnd (0:2)
00301 #endif /* DEBUG */
00302 !
00303 ! !DESCRIPTION:
00304 !
00305 ! Subroutine "PSMILe_mg_method_3d_dble" searches the corresponding points
00306 ! of the method (grid) for the subgrid coords by the sending process.
00307 !
00308 !
00309 ! !REVISION HISTORY:
00310 !
00311 !   Date      Programmer   Description
00312 ! ----------  ----------   -----------
00313 ! 03.07.21    H. Ritzdorf  created
00314 !
00315 !EOP
00316 !----------------------------------------------------------------------
00317 !
00318 !  $Id: psmile_mg_method_3d_dble.F90 2325 2010-04-21 15:00:07Z valcke $
00319 !  $Author: valcke $
00320 !
00321    Character(len=len_cvs_string), save :: mycvs = 
00322        '$Id: psmile_mg_method_3d_dble.F90 2325 2010-04-21 15:00:07Z valcke $'
00323 !
00324 !----------------------------------------------------------------------
00325 !
00326 !  Relative control indices
00327 ! ??? ist das richtig ??? muessen das nicht mehr sein
00328 !
00329       data ((ijkctl (i, n), i=1,ndim_3d), n = 1,nrefd) &
00330                             / -1,-1,-1,   0,-1,-1,   1,-1,-1, &
00331                               -1, 0,-1,   0, 0,-1,   1, 0,-1, &
00332                               -1, 1,-1,   0, 1,-1,   1, 1,-1, &
00333                               -1,-1, 0,   0,-1, 0,   1,-1, 0, &
00334                               -1, 0, 0,   0, 0, 0,   1, 0, 0, &
00335                               -1, 1, 0,   0, 1, 0,   1, 1, 0, &
00336                               -1,-1, 1,   0,-1, 1,   1,-1, 1, &
00337                               -1, 0, 1,   0, 0, 1,   1, 0, 1, &
00338                               -1, 1, 1,   0, 1, 1,   1, 1, 1/
00339 !
00340 !  Relative indices of tetraheders
00341 !
00342 #ifdef USE6T
00343 !         The cell is split into 6 tetraheders
00344 !
00345       data ((ijkref (i, n), i = 1, ndim_3d), n = 1, ntet) &
00346            / 0, 0, 1,   0, 0, 1,   1, 0, 1,   0, 1, 1,    &
00347              0, 1, 1,   1, 1, 1 /
00348 !
00349       data (((ijkedg (i,j, n), i = 1, ndim_3d), j = 1, 3), n = 1, ntet) &
00350            / 0, 0, 0,   1, 0, 0,   0, 1, 0,                             &
00351              1, 0, 0,   0, 1, 0,   1, 1, 0,                             &
00352              1, 0, 0,   1, 1, 0,   0, 0, 1,                             &
00353              0, 1, 0,   1, 1, 0,   0, 0, 1,                             &
00354              1, 1, 0,   0, 0, 1,   1, 0, 1,                             &
00355              1, 1, 0,   1, 0, 1,   0, 1, 1 /
00356 #else
00357 !         The cell is split into 4 tetraheders
00358 !
00359       data  ((ijkref (i,n), i = 1, ndim_3d), n = 1, ntet)               &
00360            / 0, 0, 0,   1, 1, 0,   0, 1, 1,   1, 0, 1/
00361 !
00362       data (((ijkedg (i,j,n), i = 1, ndim_3d), j = 1, 3), n = 1, ntet)  &
00363            / 1, 0, 0,   0, 1, 0,   0, 0, 1,                             &
00364              0, 1, 0,   1, 0, 0,   1, 1, 1,                             &
00365              1, 1, 1,   0, 0, 1,   0, 1, 0,                             &
00366              0, 0, 1,   1, 1, 1,   1, 0, 0 /
00367 #endif /* USE6T */
00368 
00369 !----------------------------------------------------------------------
00370 !
00371 !  Initialization
00372 !
00373       ierror = 0
00374 
00375 #ifdef VERBOSE
00376       print 9990, trim(ch_id), lev, control
00377 
00378       call psmile_flushstd
00379 #endif /* VERBOSE */
00380 !
00381 #ifdef PRISM_ASSERTION
00382       if (tol < 0.0) then
00383          call psmile_assert (__FILE__, __LINE__, &
00384                              "tol must be >= 0.0")
00385       endif
00386 #endif
00387 !
00388 ! temporaeren speicherbereich (control (2,1)-control(1,1)+1)*ndtry anlegen
00389 ! und do n =1,nref vor i-loop ziehen ?!?
00390 !
00391 ! ? statt immer alle nref zu kontrollieren, einmal location in der
00392 ! Zelle bestimmen ?
00393 !
00394 ! ? ein-dimensionaler Loop statt i,j,k loop
00395 !
00396       tol1 = tol + 1.0
00397       tol2 = tol * tol
00398 !
00399       dble_huge = huge (dist(1))
00400 !
00401 #ifdef DEBUG
00402       nfnd (:) = 0
00403 #endif /* DEBUG */
00404 !
00405 !===>
00406 !
00407          do k = control(1,3), control(2,3)
00408             do j = control(1,2), control (2,2)
00409 !
00410 !-----------------------------------------------------------------------
00411 !             Look in the fine parts of the coarse grid cell
00412 !             loc(i,j,k)
00413 !
00414 !  Besser ein gatter/Scatter hier einbauen
00415 !-----------------------------------------------------------------------
00416 !
00417             ibegl = control (1, 1)
00418 !
00419 !===> ... Look for the next cells to be controlled
00420 !
00421             do while (ibegl <= control(2,1))
00422 !
00423 !cdir vector
00424                do i = ibegl, control(2,1)
00425                if (found(i, j, k) == lev) exit
00426                end do
00427             if (i > control(2,1)) exit
00428             ibegl = i
00429 !
00430 !cdir vector
00431                do i = ibegl, control(2,1)
00432                if (found(i, j, k) /= lev) exit
00433                end do
00434 !
00435             iendl = i - 1
00436 !
00437 !===> ... Look in the real cell (ic(1),ic(2),ic(3))
00438 !
00439 #ifdef PRISM_ASSERTION
00440                do i = ibegl, iendl
00441                if (loc(1, i,j,k) < coords_shape(1,1) .or. &
00442                    loc(1, i,j,k) > coords_shape(2,1) .or. &
00443                    loc(2, i,j,k) < coords_shape(1,2) .or. &
00444                    loc(2, i,j,k) > coords_shape(2,2) .or. &
00445                    loc(3, i,j,k) < coords_shape(1,3) .or. &
00446                    loc(3, i,j,k) > coords_shape(2,3)) exit
00447                end do
00448 !
00449             if (i <= iendl) then
00450                print *, 'ic', loc (:, i,j,k)
00451                print *, 'coords_shape', coords_shape
00452                call psmile_assert (__FILE__, __LINE__, &
00453                                    'wrong index')
00454             endif
00455 #endif
00456 !
00457             do jpart = 0, (iendl-ibegl)/5000
00458 !cdir vector, loopcnt=5000
00459 loop_i:     do i = ibegl+jpart*5000, min (iendl, ibegl+(jpart+1)*5000-1)
00460 !
00461             ic(:) = loc (:, i, j, k)
00462 !
00463             irange (1, :) = max (ic(:)-1, grid_valid_shape (1, :))
00464             irange (2, :) = min (ic(:)+1, grid_valid_shape (2, :))
00465 !
00466             nref = (irange (2,1) - irange (1,1) + 1) * &
00467                    (irange (2,2) - irange (1,2) + 1) * &
00468                    (irange (2,3) - irange (1,3) + 1)
00469 !
00470 #ifdef PRISM_ASSERTION
00471             if (nref <= 0) then
00472                call psmile_assert (__FILE__, __LINE__, &
00473                                    'nref <= 0')
00474             endif
00475 #endif
00476 !
00477             if (nref == nrefd) then
00478                   do n = 1, nrefd
00479                   ijkdst (:, n) = ic (:) + ijkctl (:, n)
00480                   end do
00481             else
00482                 n = 0
00483                 do kk = irange (1, 3), irange (2, 3)
00484                    do jj = irange (1, 2), irange (2, 2)
00485                       do ii = irange (1, 1), irange (2, 1)
00486                       n = n + 1
00487                       ijkdst (1, n) = ii
00488                       ijkdst (2, n) = jj
00489                       ijkdst (3, n) = kk
00490                       end do ! ii
00491                    end do ! jj
00492                 end do ! kk
00493             endif
00494 !
00495 !===> ... Compute distance to points
00496 !
00497                do n = 1, nref
00498                dist (n) = (x_coords (ijkdst(1,n), ijkdst (2,n), ijkdst (3,n))-&
00499                              coords1(i,j,k)) ** 2 + &
00500                           (y_coords (ijkdst(1,n), ijkdst (2,n), ijkdst (3,n))-&
00501                              coords2(i,j,k)) ** 2 + &
00502                           (z_coords (ijkdst(1,n), ijkdst (2,n), ijkdst (3,n))-&
00503                              coords3(i,j,k)) ** 2
00504                end do
00505 !
00506 !===> ... Look for the minimum distance to corner points of adjoining method cells
00507 !
00508             nmin = MINLOC (dist(1:nref))
00509 #ifdef MINLOCFIX
00510             if (nmin(1).eq.0) nmin=1
00511 #endif /* MINLOCFIX */
00512 !
00513             if (dist(nmin(1)) < tol2) then
00514 !
00515 !===> ...... Point is located on the grid point of the method.
00516 !
00517 !              found (i,j,k)  = val_direct ! == lev == 1
00518                loc (:, i,j,k) = ijkdst (:, nmin(1))
00519 !
00520 #ifdef DEBUG
00521                nfnd (1) = nfnd (1) + 1
00522 #endif /* DEBUG */
00523 
00524                cycle loop_i
00525             endif 
00526 !
00527             found (i,j,k) = val_coupler
00528 !
00529 !===> ....... Get cell range "irange" for search
00530 !
00531             if (ic(1) == grid_valid_shape(1,1) .or. &
00532                 ic(2) == grid_valid_shape(1,2) .or. &
00533                 ic(3) == grid_valid_shape(1,3)) then
00534                irange (1, :) = max (ic(:)-1, grid_valid_shape(1,:)-1)
00535                irange (2, :) = min (ic(:)+1, grid_valid_shape(2,:))
00536 !
00537                nref = (irange (2,1) - irange (1,1) + 1) * &
00538                       (irange (2,2) - irange (1,2) + 1) * &
00539                       (irange (2,3) - irange (1,3) + 1)
00540 !
00541 #ifdef PRISM_ASSERTION
00542                if (nref <= 0) then
00543                   call psmile_assert (__FILE__, __LINE__, &
00544                                       'nref <= 0')
00545                endif
00546 #endif
00547 !
00548                if (nref == nrefd) then
00549                      do n = 1, nrefd
00550                      ijkdst (:, n) = ic (:) + ijkctl (:, n)
00551                      end do
00552                else
00553                    n = 0
00554                    do kk = irange (1, 3), irange (2, 3)
00555                       do jj = irange (1, 2), irange (2, 2)
00556                          do ii = irange (1, 1), irange (2, 1)
00557                          n = n + 1
00558                          ijkdst (1, n) = ii
00559                          ijkdst (2, n) = jj
00560                          ijkdst (3, n) = kk
00561                          end do ! ii
00562                       end do ! jj
00563                    end do ! kk
00564                endif
00565             endif
00566 !
00567 !===> ... Compute distance to the mid-points
00568 !
00569 !cdir vector
00570               do n = 1, nref
00571               if (coords1(i,j,k) >= chmin1(ijkdst(1,n),         &
00572                                            ijkdst(2,n),         &
00573                                            ijkdst(3,n)) .and.   &
00574                   coords2(i,j,k) >= chmin2(ijkdst(1,n),         &
00575                                            ijkdst(2,n),         &
00576                                            ijkdst(3,n)) .and.   &
00577                   coords3(i,j,k) >= chmin3(ijkdst(1,n),         &
00578                                            ijkdst(2,n),         &
00579                                            ijkdst(3,n)) .and.   &
00580                   coords1(i,j,k) <= chmax1(ijkdst(1,n),         &
00581                                            ijkdst(2,n),         &
00582                                            ijkdst(3,n)) .and.   &
00583                   coords2(i,j,k) <= chmax2(ijkdst(1,n),         &
00584                                            ijkdst(2,n),         &
00585                                            ijkdst(3,n)) .and.   &
00586                   coords3(i,j,k) <= chmax3(ijkdst(1,n),         &
00587                                            ijkdst(2,n),         &
00588                                            ijkdst(3,n))) then
00589 
00590                   dist (n) = (midp1 (ijkdst(1,n), ijkdst (2,n), ijkdst (3,n))-&
00591                                 coords1(i,j,k)) ** 2 + &
00592                              (midp2 (ijkdst(1,n), ijkdst (2,n), ijkdst (3,n))-&
00593                                 coords2(i,j,k)) ** 2 + &
00594                              (midp3 (ijkdst(1,n), ijkdst (2,n), ijkdst (3,n))-&
00595                                 coords3(i,j,k)) ** 2
00596                else
00597                   dist (n) = dble_huge
00598                endif
00599                end do
00600 !
00601 !-------------------------------------------------------------------------------
00602 !     ...... Control whether the point is located within the cell starting in
00603 !            "ic"
00604 !            ??? Kann man das vereinfachen, wenn man weiss, dass der Punkt
00605 !                in der bounding box ist ?
00606 !-------------------------------------------------------------------------------
00607 !
00608 !===> ... Look for the minimum distance
00609 !
00610             nmin = MINLOC (dist(1:nref))
00611 #ifdef MINLOCFIX
00612             if (nmin(1).eq.0) nmin=1
00613 #endif /* MINLOCFIX */
00614 !
00615                   do while (dist(nmin(1)) < dble_huge) 
00616                   ic = ijkdst (:, nmin(1))
00617 !
00618                   if (ic(1) >= grid_valid_shape(1,1) .and. &
00619                       ic(1) <  grid_valid_shape(2,1) .and. &
00620                       ic(2) >= grid_valid_shape(1,2) .and. &
00621                       ic(2) <  grid_valid_shape(2,2) .and. &
00622                       ic(3) >= grid_valid_shape(1,3) .and. &
00623                       ic(3) <  grid_valid_shape(2,3)) then
00624 !
00625 !===> ....... Point is not located in a virtual method cell.
00626 !             Get reference points of tetraeders for method cell (ic:ic+1)
00627 !
00628                      do n = 1, ntet
00629                      xyzref (1, n) = x_coords (ic(1)+ijkref(1, n), &
00630                                                ic(2)+ijkref(2, n), &
00631                                                ic(3)+ijkref(3, n))
00632                      xyzref (2, n) = y_coords (ic(1)+ijkref(1, n), &
00633                                                ic(2)+ijkref(2, n), &
00634                                                ic(3)+ijkref(3, n))
00635                      xyzref (3, n) = z_coords (ic(1)+ijkref(1, n), &
00636                                                ic(2)+ijkref(2, n), &
00637                                                ic(3)+ijkref(3, n))
00638                      end do
00639 !
00640                   xyzpnt (1, :) = coords1 (i, j, k) - xyzref (1, :)
00641                   xyzpnt (2, :) = coords2 (i, j, k) - xyzref (2, :)
00642                   xyzpnt (3, :) = coords3 (i, j, k) - xyzref (3, :)
00643 !
00644 !===> ....... Compute edges of tetraeders
00645 !
00646                      do n = 1, ntet
00647                         do m = 1, 3
00648                         xyzedg (1, m, n) = x_coords (ic(1)+ijkedg(1, m, n),   &
00649                                                      ic(2)+ijkedg(2, m, n),   &
00650                                                      ic(3)+ijkedg(3, m, n)) - &
00651                                            xyzref (1, n)
00652                         xyzedg (2, m, n) = y_coords (ic(1)+ijkedg(1, m, n),   &
00653                                                      ic(2)+ijkedg(2, m, n),   &
00654                                                      ic(3)+ijkedg(3, m, n)) - &
00655                                            xyzref (2, n)
00656                         xyzedg (3, m, n) = z_coords (ic(1)+ijkedg(1, m, n),   &
00657                                                      ic(2)+ijkedg(2, m, n),   &
00658                                                      ic(3)+ijkedg(3, m, n)) - &
00659                                            xyzref (3, n)
00660                         end do
00661                      end do
00662 !
00663 !===> ........ Solve trilinear system; compute spat product
00664 !
00665 !  ?!?! Normierung, damit det nicht zu klein wird ?!
00666 !
00667 !   (xyzedg(*,1), xyzedg(*,2), xyzedg(*,3)) (x) = xyzpnt
00668 !
00669 !   det = a1*(b2*c3-b3*c2) + b1*(c2*a3-c3*a2) + c1*(a2*b3-a3*b2)
00670 !
00671 ! :'a,'bs/c\([1-3]\)/xyzedg(\1,3,n)/g
00672 ! :'a,'bs/xyzedg(\([1-3]\),3,/xyzpnt(\1,  /g
00673 !
00674 !
00675                   det(:) = xyzedg(1,1,:)*(xyzedg(2,2,:)*xyzedg(3,3,:) - &
00676                                           xyzedg(3,2,:)*xyzedg(2,3,:))  &
00677                          + xyzedg(1,2,:)*(xyzedg(2,3,:)*xyzedg(3,1,:) - &
00678                                           xyzedg(3,3,:)*xyzedg(2,1,:))  &
00679                          + xyzedg(1,3,:)*(xyzedg(2,1,:)*xyzedg(3,2,:) - &
00680                                           xyzedg(3,1,:)*xyzedg(2,2,:))
00681 !
00682                      do n = 1, ntet
00683                      dnorm (n) = dzero
00684                         do m = 1, 3
00685 !cdir vector
00686                            do l = 1, ndim_3d
00687                            dnorm (n) = dnorm(n) + abs(xyzedg(l,m,n))
00688                            end do
00689                         end do
00690                      end do
00691 !
00692 #define ALLOW_DEGRADED_CELL
00693 #ifdef ALLOW_DEGRADED_CELL
00694 !
00695 ! ??? ist das koscher ?? wird d1(n), d2(n), d3(n) == 0
00696 !cdir vector
00697                      do n = 1, ntet
00698                      if (abs(det(n)) <= eps*dnorm(n)*dnorm(n)*dnorm(n) &
00699                          .or. dnorm(n) == dzero) then
00700                         det (n) = sign (rmxeps, det(n))
00701                      else
00702                         det (n) = 1.0d0 / det (n)
00703                      endif
00704                      end do
00705 #else 
00706 !cdir vector
00707                      do n = 1, ntet
00708                      if (abs(det(n)) <= eps*dnorm(n)*dnorm(n)*dnorm(n) &
00709                          .or. dnorm(n) == dzero) go to 170
00710                      end do
00711 !
00712                   det (:) = 1.0d0/det (:)
00713 
00714 #endif /* ALLOW_DEGRADED_CELL */
00715 !
00716                   d1(:) = (xyzpnt(1,  :)*(xyzedg(2,2,:)*xyzedg(3,3,:) -  &
00717                                           xyzedg(3,2,:)*xyzedg(2,3,:))   &
00718                          + xyzedg(1,2,:)*(xyzedg(2,3,:)*xyzpnt(3,  :) -  &
00719                                           xyzedg(3,3,:)*xyzpnt(2,  :))   &
00720                          + xyzedg(1,3,:)*(xyzpnt(2,  :)*xyzedg(3,2,:) -  &
00721                                           xyzpnt(3,  :)*xyzedg(2,2,:)))  &
00722                         * det (:)
00723 !
00724                   d2(:) = (xyzedg(1,1,:)*(xyzpnt(2  ,:)*xyzedg(3,3,:) -  &
00725                                           xyzpnt(3,  :)*xyzedg(2,3,:))   &
00726                          + xyzpnt(1,  :)*(xyzedg(2,3,:)*xyzedg(3,1,:) -  &
00727                                           xyzedg(3,3,:)*xyzedg(2,1,:))   &
00728                          + xyzedg(1,3,:)*(xyzedg(2,1,:)*xyzpnt(3,  :) -  &
00729                                           xyzedg(3,1,:)*xyzpnt(2,  :)))  &
00730                         * det (:)
00731 !
00732                   d3(:) = (xyzedg(1,1,:)*(xyzedg(2,2,:)*xyzpnt(3,  :) -  &
00733                                           xyzedg(3,2,:)*xyzpnt(2,  :))   &
00734                          + xyzedg(1,2,:)*(xyzpnt(2,  :)*xyzedg(3,1,:) -  &
00735                                           xyzpnt(3,  :)*xyzedg(2,1,:))   &
00736                          + xyzpnt(1,  :)*(xyzedg(2,1,:)*xyzedg(3,2,:) -  &
00737                                           xyzedg(3,1,:)*xyzedg(2,2,:)))  &
00738                         * det (:)
00739 !
00740 #ifdef USE6T
00741 !
00742                      do n = 1, ntet 
00743                      if (min(d1(n), d2(n), d3(n)) >= -tol .and. &
00744                          max(d1(n),dzero) +                     &
00745                          max(d2(n),dzero) +                     &
00746                          max(d3(n),dzero) <=  tol1) go to 160
00747                      end do
00748 !
00749                   go to 190
00750 #else
00751                      do n = 1, ntet
00752                      if (min(d1(n), d2(n), d3(n)) < -tol .or. &
00753                          max(d1(n), d2(n), d3(n)) >  tol1) go to 190
00754                      end do
00755                   go to 160
00756 #endif
00757                   endif
00758 !
00759 !===> ... point is contained in cell "ic"
00760 !
00761 160               continue
00762 #ifdef DEBUG
00763                   nfnd (2) = nfnd (2) + 1
00764 #endif /* DEBUG */
00765 !
00766                   loc (:, i, j, k) = ic
00767 !
00768                   cycle loop_i
00769 !
00770 !===> ... cell is degraded
00771 !
00772 #ifndef ALLOW_DEGRADED_CELL
00773 170               print 9960, trim(ch_id), method_id, ic, &
00774                      x_coords(ic(1),   ic(2),   ic(3)),  &
00775                      y_coords(ic(1),   ic(2),   ic(3)),  &
00776                      z_coords(ic(1),   ic(2),   ic(3)),  &
00777                      x_coords(ic(1)+1, ic(2),   ic(3)),  &
00778                      y_coords(ic(1)+1, ic(2),   ic(3)),  &
00779                      z_coords(ic(1)+1, ic(2),   ic(3)),  &
00780                      x_coords(ic(1),   ic(2)+1, ic(3)),  &
00781                      y_coords(ic(1),   ic(2)+1, ic(3)),  &
00782                      z_coords(ic(1),   ic(2)+1, ic(3)),  &
00783                      x_coords(ic(1)+1, ic(2)+1, ic(3)),  &
00784                      y_coords(ic(1)+1, ic(2)+1, ic(3)),  &
00785                      z_coords(ic(1)+1, ic(2)+1, ic(3)),  &
00786                      x_coords(ic(1),   ic(2),   ic(3)+1), &
00787                      y_coords(ic(1),   ic(2),   ic(3)+1), &
00788                      z_coords(ic(1),   ic(2),   ic(3)+1), &
00789                      x_coords(ic(1)+1, ic(2),   ic(3)+1), &
00790                      y_coords(ic(1)+1, ic(2),   ic(3)+1), &
00791                      z_coords(ic(1)+1, ic(2),   ic(3)+1), &
00792                      x_coords(ic(1),   ic(2)+1, ic(3)+1), &
00793                      y_coords(ic(1),   ic(2)+1, ic(3)+1), &
00794                      z_coords(ic(1),   ic(2)+1, ic(3)+1), &
00795                      x_coords(ic(1)+1, ic(2)+1, ic(3)+1), &
00796                      y_coords(ic(1)+1, ic(2)+1, ic(3)+1), &
00797                      z_coords(ic(1)+1, ic(2)+1, ic(3)+1)
00798 !
00799                      do n = 1, ntet
00800                      if (abs(det(n)) < eps) then
00801                         print 9950, n, det (n), dnorm(n), &
00802                           xyzedg (1, 1, n),                   &
00803                           xyzedg (1, 2, n), xyzedg (1, 3, n), &
00804                           xyzedg (2, 1, n), xyzedg (2, 2, n), &
00805                           xyzedg (2, 3, n), xyzedg (3, 1, n), &
00806                           xyzedg (3, 2, n), xyzedg (3, 3, n)
00807                      endif
00808 !
00809                      end do
00810 #endif /* ALLOW_DEGRADED_CELL */
00811 !
00812 !===> ... Point was not found in cell
00813 !         Look for the minimum distance of others cells
00814 !
00815 190               continue
00816 !
00817                   dist(nmin(1)) = dble_huge
00818                   nmin = MINLOC (dist(1:nref))
00819 #ifdef MINLOCFIX
00820                   if (nmin(1).eq.0) nmin=1
00821 #endif /* MINLOCFIX */
00822 !
00823                end do ! while (dist(nmin(1)) < dble_huge)
00824 !
00825 !===> ... Point was not found in any cell
00826 !         Point may be located in a neighbouring block
00827 !
00828 !         Get nearest cell mid point (weiss nicht, ob das so clever ist ??)
00829 !cdir vector
00830               do n = 1, nref
00831               dist (n) = (midp1 (ijkdst(1,n), ijkdst (2,n), ijkdst (3,n))-&
00832                           coords1(i,j,k)) ** 2 + &
00833                          (midp2 (ijkdst(1,n), ijkdst (2,n), ijkdst (3,n))-&
00834                           coords2(i,j,k)) ** 2 + &
00835                          (midp3 (ijkdst(1,n), ijkdst (2,n), ijkdst (3,n))-&
00836                           coords3(i,j,k)) ** 2
00837               end do
00838 
00839               nmin = MINLOC (dist(1:nref))
00840 #ifdef MINLOCFIX
00841               if (nmin(1).eq.0) nmin=1
00842 #endif /* MINLOCFIX */
00843               loc (:, i,j,k) = ijkdst (:, nmin(1))
00844 !
00845 #ifdef DEBUG
00846                nfnd (0) = nfnd (0) + 1
00847 
00848 #ifdef DEBUGX
00849                print *, trim(ch_id), ' Not found: -----'
00850                print *, 'i,j,k :', i, j, k
00851                print *, 'coords:', coords1(i,j,k), coords2(i,j,k), coords3(i,j,k)
00852                print *, 'irange:', irange
00853                print *, 'chmin low:', chmin1 (irange(1,1), irange(1,2), irange(1,3)), &
00854                                       chmin2 (irange(1,1), irange(1,2), irange(1,3)), &
00855                                       chmin3 (irange(1,1), irange(1,2), irange(1,3))
00856                print *, 'chmax low:', chmax1 (irange(1,1), irange(1,2), irange(1,3)), &
00857                                       chmax2 (irange(1,1), irange(1,2), irange(1,3)), &
00858                                       chmax3 (irange(1,1), irange(1,2), irange(1,3))
00859                print *, 'chmin hig:', chmin1 (irange(2,1), irange(2,2), irange(2,3)), &
00860                                       chmin2 (irange(2,1), irange(2,2), irange(2,3)), &
00861                                       chmin3 (irange(2,1), irange(2,2), irange(2,3))
00862                print *, 'chmax hig:', chmax1 (irange(2,1), irange(2,2), irange(2,3)), &
00863                                       chmax2 (irange(2,1), irange(2,2), irange(2,3)), &
00864                                       chmax3 (irange(2,1), irange(2,2), irange(2,3))
00865 #endif /* DEBUGX */
00866     
00867 #endif /* DEBUG */
00868 !
00869             end do loop_i ! i
00870             end do ! jpart
00871 !
00872 !===> ... Is there an cyclic index
00873 !
00874             do l = 1, ndim_3d
00875             if (cyclic(l)) then
00876 !
00877 !              This is an cyclic index;
00878 !              Move points, which are located in virtual cell 0
00879 !              into cell "grid_valid_shape(2,l)"
00880 !
00881 !cdir vector
00882                   do i = ibegl, iendl
00883                   if (loc (l, i,j,k) < grid_valid_shape (1,l)) then
00884                       loc (l, i,j,k) = grid_valid_shape (2,l)
00885                   endif
00886                   enddo
00887 #ifdef REMOVED
00888             else
00889 !
00890 !              Move points located in virtual cell 0 into
00891 !              cell 1; wird derzeit nur gemacht, um Probleme
00892 !              in anderen Routinen zu verhindern
00893 !              spaeter: diese indices in extra_search aufnehmen
00894 !              oder nearest neighbour
00895 !cdir vector
00896                   do i = ibegl, iendl
00897                   loc (l, i,j,k) = max (loc(l, i,j,k), grid_valid_shape (1,l))
00898                   enddo
00899 #endif
00900 !
00901             endif
00902             end do ! l
00903 !
00904 !===> ... Start index of the next search
00905 !
00906             ibegl = iendl + 2
00907             end do ! while
00908 !
00909             end do ! j
00910          end do ! k
00911 !
00912 !===> All done
00913 !
00914 #ifdef DEBUG
00915       print 9970, trim(ch_id), lev, nfnd
00916 9970  format (1x, a, ': PSMILe_mg_method_3d_dble: lev =', i3, &
00917               ': not :', i5, ', dir: ', i6, ', fnd :', i6, i5)
00918 #endif /* DEBUG */
00919 
00920 #ifdef VERBOSE
00921       print 9980, trim(ch_id), lev
00922 
00923       call psmile_flushstd
00924 #endif /* VERBOSE */
00925 !
00926 !  Formats:
00927 !
00928 
00929 9990 format (1x, a, ': psmile_mg_method_3d_dble: level', i3, &
00930                     ', control', 6i6)
00931 9980 format (1x, a, ': psmile_mg_method_3d_dble: eof, level', i3)
00932 9960 format (1x, a, ': psmile_mg_method_3d_dble: method id =', i5, &
00933             /1x,  ' Grid cell (', i4, ',', i4, ',', i4,           &
00934                  ') is degraded! Cell coordinates are:', 1p,      &
00935             8 (/1x, '(', 2 (e17.9, ','), e17.9, ')'))
00936 9950 format (1x, i1, '-th spawn; det =', 1p, e17.9, ' (', e17.9, &
00937              ') of', 3 (/1x, 3e17.9, ','))
00938 
00939 
00940       end subroutine psmile_mg_method_3d_dble

Generated on 18 Mar 2011 for Oasis4 by  doxygen 1.6.1