Changeset 1612 in lmdz_wrf for trunk


Ignore:
Timestamp:
Aug 30, 2017, 2:54:25 PM (8 years ago)
Author:
lfita
Message:

Adding all the required Fortran code for the path/polygon detection an definition

Location:
trunk/tools
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/tools/module_definitions.f90

    r1609 r1612  
    1313  REAL(r_k)                                              :: fillval64 = 1.e20
    1414  CHARACTER(len=50)                                      :: fname
     15  CHARACTER(len=256)                                     :: msg
    1516
    1617END MODULE module_definitions
  • trunk/tools/module_generic.f90

    r1608 r1612  
    55! ErrMsg: Subroutine to stop execution and provide an error message
    66! ErrWarnMsg: Function to print error/warning message
     7! index_list_coordsI: Function to provide the index of a given coordinate within a list of integer coordinates
    78! Index1DArrayR: Function to provide the first index of a given value inside a 1D real array
    89! Index1DArrayR_K: Function to provide the first index of a given value inside a 1D real(r_k) array
     
    1718
    1819  CONTAINS
     20
     21  INTEGER FUNCTION index_list_coordsI(Ncoords, coords, icoord)
     22  ! Function to provide the index of a given coordinate within a list of integer coordinates
     23
     24    IMPLICIT NONE
     25
     26    INTEGER, INTENT(in)                                  :: Ncoords
     27    INTEGER, DIMENSION(Ncoords,2), INTENT(in)            :: coords
     28    INTEGER, DIMENSION(2), INTENT(in)                    :: icoord
     29
     30! Local
     31    INTEGER, DIMENSION(Ncoords)                          :: dist
     32    INTEGER                                              :: i,mindist
     33    INTEGER, DIMENSION(1)                                :: iloc
     34
     35!!!!!!! Variables
     36! Ncoords: number of coordinates in the list
     37! coords: list of coordinates
     38! icoord: coordinate to find
     39
     40  fname = 'index_list_coordsI'
     41
     42  dist = (coords(:,1)-icoord(1))**2+(coords(:,2)-icoord(2))**2
     43
     44  IF (ANY(dist == 0)) THEN
     45    iloc = MINLOC(dist)
     46    index_list_coordsI = iloc(1)
     47  ELSE
     48    index_list_coordsI = -1
     49  END IF
     50
     51  END FUNCTION index_list_coordsI
    1952
    2053  CHARACTER(len=1000) FUNCTION vectorR_KS(d1, vector)
  • trunk/tools/module_scientific.f90

    r1609 r1612  
    33 
    44!!!!!!! Functions & subroutines
     5! borders_matrixL: Subroutine to provide the borders of a logical array (interested in .TRUE.)
    56! FindMinimumR_K*: Function returns the location of the minimum in the section between Start and End.
     7! gridpoints_InsidePolygon: Subroutine to determine if a series of grid points are inside a polygon
     8!   following ray casting algorithm
     9! look_clockwise_borders: Subroutine to look clock-wise for a next point within a collection of borders
     10!   (limits of a region)
     11! paths_border: Subroutine to search the paths of a border field.
     12! path_properties: Subroutine to determine the properties of a path
     13! polygons: Subroutine to search the polygons of a border field. FORTRAN based. 1st = 1!
     14! polygons_t: Subroutine to search the polygons of a temporal series of boolean fields. FORTRAN based. 1st = 1!
    615! PrintQuantilesR_K: Subroutine to print the quantiles of values REAL(r_k)
    716! quantilesR_K: Subroutine to provide the quantiles of a given set of values of type real 'r_k'
     
    1726
    1827  CONTAINS
     28
     29SUBROUTINE polygons_t(dbg, dx, dy, dt, boolmatt, polys, Npoly)
     30! Subroutine to search the polygons of a temporal series of boolean fields. FORTRAN based. 1st = 1!
     31
     32  IMPLICIT NONE
     33
     34  INTEGER, INTENT(in)                                    :: dx, dy, dt
     35  LOGICAL, DIMENSION(dx,dy,dt), INTENT(in)               :: boolmatt
     36  LOGICAL, INTENT(in)                                    :: dbg
     37  INTEGER, DIMENSION(dt), INTENT(out)                    :: Npoly
     38  INTEGER, DIMENSION(dx,dy,dt), INTENT(out)              :: polys
     39
     40! Local
     41  INTEGER                                                :: i,it
     42
     43!!!!!!! Variables
     44! dx,dy: spatial dimensions of the space
     45! boolmatt: boolean matrix tolook for the polygons (.TRUE. based)
     46! polys: found polygons
     47! Npoly: number of polygons found
     48
     49  fname = 'polygons'
     50
     51  IF (dbg) PRINT *,TRIM(fname)
     52
     53  polys = -1
     54
     55  DO it=1,dt
     56    IF (dbg) THEN
     57      PRINT *,'  it:', it, ' bool _______'
     58      DO i=1,dx
     59        PRINT *,boolmatt(:,:,it)
     60      END DO
     61    END IF
     62    CALL polygons(dbg, dx, dy, boolmatt(:,:,it), polys(:,:,it), Npoly(it))
     63  END DO
     64
     65END SUBROUTINE polygons_t
     66
     67SUBROUTINE polygons(dbg, dx, dy, boolmat, polys, Npoly)
     68! Subroutine to search the polygons of a boolean field. FORTRAN based. 1st = 1!
     69
     70  IMPLICIT NONE
     71
     72  INTEGER, INTENT(in)                                    :: dx, dy
     73  LOGICAL, DIMENSION(dx,dy), INTENT(in)                  :: boolmat
     74  LOGICAL, INTENT(in)                                    :: dbg
     75  INTEGER, INTENT(out)                                   :: Npoly
     76  INTEGER, DIMENSION(dx,dy), INTENT(out)                 :: polys
     77
     78! Local
     79  INTEGER                                                :: i, j, ip, ipp, Nppt
     80  INTEGER                                                :: ierr
     81  INTEGER, DIMENSION(:,:), ALLOCATABLE                   :: borders
     82  LOGICAL, DIMENSION(dx,dy)                              :: isborder
     83  INTEGER, DIMENSION(:,:,:), ALLOCATABLE                 :: paths
     84  INTEGER                                                :: Npath
     85  INTEGER, DIMENSION(:), ALLOCATABLE                     :: Nptpaths
     86  INTEGER, DIMENSION(2)                                  :: xtrx, xtry, meanpth
     87  INTEGER                                                :: Nvertx
     88  INTEGER, DIMENSION(:,:), ALLOCATABLE                   :: vertxs, points
     89  LOGICAL, DIMENSION(:), ALLOCATABLE                     :: isin
     90
     91!!!!!!! Variables
     92! dx,dy: spatial dimensions of the space
     93! boolmat: boolean matrix tolook for the polygons (.TRUE. based)
     94! polys: found polygons
     95! Npoly: number of polygons found
     96
     97  fname = 'polygons'
     98
     99  polys = -1
     100
     101  Nppt = dx*dy
     102  IF (ALLOCATED(borders)) DEALLOCATE(borders)
     103  ALLOCATE(borders(Nppt,2), STAT=ierr)
     104  msg = "Problems allocating matrix 'borders'"
     105  CALL ErrMsg(msg, fname, ierr)
     106
     107  IF (ALLOCATED(paths)) DEALLOCATE(paths)
     108  ALLOCATE(paths(Nppt,Nppt,2), STAT=ierr)
     109  msg = "Problems allocating matrix 'paths'"
     110  CALL ErrMsg(msg, fname, ierr)
     111
     112  IF (ALLOCATED(Nptpaths)) DEALLOCATE(Nptpaths)
     113  ALLOCATE(Nptpaths(Nppt), STAT=ierr)
     114  msg = "Problems allocating matrix 'Nptpaths'"
     115  CALL ErrMsg(msg, fname, ierr)
     116
     117  ! Filling with the points of all the space
     118  IF (ALLOCATED(points)) DEALLOCATE(points)
     119  ALLOCATE(points(Nppt,2), STAT=ierr)
     120  msg = "Problems allocating matrix 'points'"
     121  CALL ErrMsg(msg, fname, ierr)
     122
     123  ip = 1
     124  DO i=1, dx
     125    DO j=1, dy
     126      points(ip,1) = i
     127      points(ip,2) = j
     128      ip = ip + 1
     129    END DO
     130  END DO
     131
     132  CALL borders_matrixL(dx, dy, Nppt, boolmat, borders, isborder)
     133  CALL paths_border(dbg, dx, dy, isborder, Nppt, borders, paths, Npath, Nptpaths)
     134
     135  Npoly = Npath
     136
     137  DO ip=1, Npath
     138    IF (ALLOCATED(vertxs)) DEALLOCATE(vertxs)
     139    ALLOCATE(vertxs(Nptpaths(ip),2))
     140    msg = "Problems allocating matrix 'vertxs'"
     141    CALL ErrMsg(msg, fname, ierr)
     142
     143    IF (ALLOCATED(isin)) DEALLOCATE(isin)
     144    ALLOCATE(isin(Nppt), STAT=ierr)
     145    msg = "Problems allocating matrix 'isin'"
     146    CALL ErrMsg(msg, fname, ierr)
     147
     148    isin = .FALSE.
     149
     150    IF (dbg) PRINT *, '  path:', ip, ' N pts:', Nptpaths(ip)
     151
     152    CALL path_properties(dx, dy, boolmat, Nptpaths(ip), paths(ip,1:Nptpaths(ip),:), xtrx, xtry,       &
     153      meanpth, 'y', Nvertx, vertxs)
     154
     155    IF (dbg) THEN
     156      PRINT *, '    properties  _______'
     157      PRINT *, '    x-extremes:', xtrx
     158      PRINT *, '    y-extremes:', xtry
     159      PRINT *, '    center mean:', meanpth
     160      PRINT *, '    y-vertexs:', Nvertx,' ________'
     161      DO i=1, Nvertx
     162        PRINT *,'      ',i,':',vertxs(i,:)
     163      END DO
     164    END IF
     165 
     166    CALL gridpoints_InsidePolygon(dx, dy, boolmat, Nptpaths(ip), paths(ip,1:Nptpaths(ip),:), Nvertx,  &
     167      xtrx, xtry, vertxs, Nppt, points, isin)
     168
     169    ! Filling polygons
     170    ipp = 1
     171    DO i=1, dx
     172      DO j=1, dy
     173        IF (isin(ipp)) polys(i,j) = ip
     174        ipp = ipp + 1
     175      END DO
     176    END DO
     177
     178  END DO
     179
     180  DEALLOCATE (borders) 
     181  DEALLOCATE (Nptpaths)
     182  DEALLOCATE (paths)
     183  DEALLOCATE (vertxs)
     184  DEALLOCATE (points)
     185  DEALLOCATE (isin)
     186
     187  RETURN
     188
     189END SUBROUTINE polygons
     190
     191  SUBROUTINE path_properties(dx, dy, Lmat, Nptspth, pth, xxtrm, yxtrm, meanctr, axs, Nvrtx, vrtxs)
     192! Subroutine to determine the properties of a path:
     193!   extremes: minimum and maximum of the path along x,y axes
     194!   meancenter: center from the mean of the coordinates of the paths locations
     195!   vertexs: path point, without neighbours along a given axis
     196
     197  IMPLICIT NONE
     198
     199  INTEGER, INTENT(in)                                    :: dx, dy, Nptspth
     200  LOGICAL, DIMENSION(dx,dy), INTENT(in)                  :: Lmat
     201  INTEGER, DIMENSION(Nptspth,2), INTENT(in)              :: pth
     202  CHARACTER, INTENT(in)                                  :: axs
     203  INTEGER, DIMENSION(2), INTENT(out)                     :: meanctr, xxtrm, yxtrm
     204  INTEGER, INTENT(out)                                   :: Nvrtx
     205  INTEGER, DIMENSION(Nptspth,2), INTENT(out)             :: vrtxs
     206
     207! Local
     208  INTEGER                                                :: i, ip, jp
     209  INTEGER                                                :: neig1, neig2
     210
     211!!!!!!! Variables
     212! dx,dy: size of the space
     213! Lmat: original matrix of logical values for the path
     214! Nptspth: number of points of the path
     215! pth: path coordinates (clockwise)
     216! axs: axis of finding the vertex
     217! [x/y]xtrm: minimum and maximum coordinates of the path
     218! meanctr: center from the mean of the coordinates of the path
     219! Nvrtx: Number of vertexs of the path
     220! vrtxs: coordinates of the vertexs
     221
     222  fname = 'path_properties'
     223
     224  vrtxs = -1
     225  Nvrtx = 0
     226
     227  xxtrm = (/ MINVAL(pth(:,1)), MAXVAL(pth(:,1)) /)
     228  yxtrm = (/ MINVAL(pth(:,2)), MAXVAL(pth(:,2)) /)
     229  meanctr = (/ SUM(pth(:,1))/Nptspth, SUM(pth(:,2))/Nptspth /)
     230
     231  IF (axs == 'x' .OR. axs == 'X') THEN
     232    ! Looking vertexs along x-axis
     233    DO i=1, Nptspth
     234      ip = pth(i,1)
     235      jp = pth(i,2)
     236      neig1 = 0
     237      neig2 = 0
     238      ! W-point
     239      IF (ip == 1) THEN
     240        neig1 = -1
     241      ELSE
     242        IF (.NOT.Lmat(ip-1,jp)) neig1 = -1
     243      END IF
     244      ! E-point
     245      IF (ip == dx) THEN
     246        neig2 = -1
     247      ELSE
     248        IF (.NOT.Lmat(ip+1,jp)) neig2 = -1
     249      END IF
     250   
     251      IF (neig1 == -1 .AND. neig2 == -1) THEN
     252        Nvrtx = Nvrtx + 1
     253        vrtxs(Nvrtx,:) = (/ip,jp/)
     254      END IF
     255    END DO
     256  ELSE IF (axs == 'y' .OR. axs == 'Y') THEN
     257    ! Looking vertexs along x-axis
     258    DO i=1, Nptspth
     259      ip = pth(i,1)
     260      jp = pth(i,2)
     261
     262      neig1 = 0
     263      neig2 = 0
     264      ! S-point
     265      IF (jp == 1) THEN
     266        neig1 = -1
     267      ELSE
     268        IF (.NOT.Lmat(ip,jp-1)) neig1 = -1
     269      END IF
     270      ! N-point
     271      IF (jp == dy) THEN
     272        neig2 = -1
     273      ELSE
     274        IF (.NOT.Lmat(ip,jp+1)) neig2 = -1
     275      END IF
     276
     277      IF (neig1 == -1 .AND. neig2 == -1) THEN
     278        Nvrtx = Nvrtx + 1
     279        vrtxs(Nvrtx,:) = (/ ip, jp /)
     280      END IF
     281    END DO
     282  ELSE
     283    msg = "Axis '" // axs // "' not available" // CHAR(10) // "  Available ones: 'x', 'X', 'y, 'Y'"
     284    CALL ErrMsg(msg, fname, -1)
     285  END IF
     286
     287  RETURN
     288
     289  END SUBROUTINE path_properties
     290
     291  SUBROUTINE gridpoints_InsidePolygon(dx, dy, isbrdr, Npath, path, Nvrtx, xpathxtrm, ypathxtrm,       &
     292    vrtxs, Npts, pts, inside)
     293! Subroutine to determine if a series of grid points are inside a polygon following ray casting algorithm
     294! FROM: https://en.wikipedia.org/wiki/Point_in_polygon
     295
     296  IMPLICIT NONE
     297
     298  INTEGER, INTENT(in)                                    :: dx,dy,Npath,Nvrtx,Npts
     299  LOGICAL, DIMENSION(dx,dy), INTENT(in)                  :: isbrdr
     300  INTEGER, DIMENSION(Npath,2), INTENT(in)                :: path
     301  INTEGER, DIMENSION(2), INTENT(in)                      :: xpathxtrm, ypathxtrm
     302  INTEGER, DIMENSION(Npath,2)                            :: vrtxs
     303  INTEGER, DIMENSION(Npts,2), INTENT(in)                 :: pts
     304  LOGICAL, DIMENSION(Npts), INTENT(out)                  :: inside
     305
     306! Local
     307  INTEGER                                                :: i,j,ip,ix,iy
     308  INTEGER                                                :: Nintersecs, isvertex
     309  INTEGER                                                :: ierr
     310  LOGICAL, DIMENSION(:,:), ALLOCATABLE                   :: halo_brdr
     311
     312!!!!!!! Variables
     313! dx,dy: space size
     314! Npath: number of points of the path of the polygon
     315! path: path of the polygon
     316! isbrdr: boolean matrix of the space wqith .T. on polygon border
     317! Nvrtx: number of vertexs of the path
     318! vrtxs: vertexs of the path along y-axis
     319! Npts: number of points
     320! pts: points to look for
     321! inside: vector wether point is inside or not (coincident to a border is inside)
     322
     323  fname = 'gridpoints_InsidePolygon'
     324
     325  ! Creation of a 1-grid point larger matrix to deal with points reaching the limits
     326  IF (ALLOCATED(halo_brdr)) DEALLOCATE(halo_brdr)
     327  ALLOCATE(halo_brdr(dx+2,dy+2), STAT=ierr)
     328  msg = "Problems allocating matrix 'halo_brdr'"
     329  CALL ErrMsg(msg, fname, ierr)
     330  halo_brdr = .FALSE.
     331
     332  DO i=1,dx
     333    halo_brdr(i+1,2:dy+1) = isbrdr(i,:)
     334  END DO
     335
     336  inside = .FALSE.
     337
     338  DO ip=1,Npts
     339    Nintersecs = 0
     340    ix = pts(ip,1)
     341    iy = pts(ip,2)
     342    ! Point might be outside path range...
     343    IF (ix >= xpathxtrm(1) .AND. ix <= xpathxtrm(2) .AND. iy >= ypathxtrm(1) .AND.                    &
     344      iy <= ypathxtrm(2)) THEN
     345
     346      ! It is a border point?
     347      IF (isbrdr(ix,iy)) THEN
     348        inside(ip) = .TRUE.
     349        CYCLE
     350      END IF
     351
     352      ! Looking along y-axis
     353      DO j=1,iy
     354        ! Only counting that borders that are not vertexs
     355        isvertex = index_list_coordsI(Npath, vrtxs, (/ix,j/))
     356        IF (halo_brdr(ix+1,j+1) .AND. ( isvertex == -1)) Nintersecs = Nintersecs + 1
     357      END DO
     358      IF (MOD(Nintersecs,2) /= 0) inside(ip) = .TRUE.
     359    END IF
     360
     361  END DO
     362
     363  RETURN
     364
     365END SUBROUTINE gridpoints_InsidePolygon
     366
     367SUBROUTINE look_clockwise_borders(dx,dy,Nbrdrs,brdrs,gbrdr,isbrdr,ix,iy,dbg,xf,yf,iff)
     368! Subroutine to look clock-wise for a next point within a collection of borders (limits of a region)
     369
     370  IMPLICIT NONE
     371
     372  INTEGER, INTENT(in)                                    :: dx, dy, Nbrdrs, ix, iy
     373  INTEGER, DIMENSION(Nbrdrs,2), INTENT(in)               :: brdrs
     374  LOGICAL, DIMENSION(Nbrdrs), INTENT(in)                 :: gbrdr
     375  LOGICAL, DIMENSION(dx,dy), INTENT(in)                  :: isbrdr
     376  LOGICAL, INTENT(in)                                    :: dbg
     377  INTEGER, INTENT(out)                                   :: xf, yf, iff
     378
     379! Local
     380  INTEGER                                                :: isch
     381  CHARACTER(len=2), DIMENSION(8)                         :: Lclock
     382  INTEGER, DIMENSION(8,2)                                :: spt
     383  INTEGER                                                :: iif, jjf
     384
     385!!!!!!! Variables
     386! dx, dy: 2D shape ot the space
     387! Nbrdrs: number of brdrs found in this 2D space
     388! brdrs: list of coordinates of the borders
     389! gbrdr: accounts for the use if the given border point
     390! isbrdr: accounts for the matrix of the point is a border or not
     391! ix,iy: coordinates of the point to start to find for
     392! xf,yf: coordinates of the found point
     393! iff: position of the border found within the list of borders
     394
     395  fname = 'look_clockwise_borders'
     396
     397  ! Looking clock-wise assuming that one starts from the westernmost point
     398
     399  ! Label of the search
     400  lclock = (/ 'N ', 'NE', 'E ', 'SE', 'S ', 'SW', 'W ', 'NW' /)
     401  ! Transformation to apply
     402  !spt = (/ (/0,1/), (/1,1/), (/1,0/), (/1,-1/), (/0,-1/), (/-1,-1/), (/-1,0/), (/-1,1/) /)
     403  spt(:,1) = (/ 0, 1, 1, 1, 0, -1, -1, -1 /)
     404  spt(:,2) = (/ 1, 1, 0, -1, -1, -1, 0, 1 /)
     405
     406  xf = -1
     407  yf = -1
     408  DO isch=1, 8
     409    ! clock-wise search
     410    IF (spt(isch,1) >= 0) THEN
     411      iif = MIN(dx,ix+spt(isch,1))
     412    ELSE
     413      iif = MAX(1,ix+spt(isch,1))
     414    END IF
     415    IF (spt(isch,2) >= 0) THEN
     416      jjf = MIN(dy,iy+spt(isch,2))
     417    ELSE
     418      jjf = MAX(1,iy+spt(isch,2))
     419    END IF
     420    iff = index_list_coordsI(Nbrdrs, brdrs,(/iif,jjf/))
     421    IF (iff > 0) THEN
     422      IF (dbg) PRINT *,'    ' // lclock(isch) // '-point:', iif,jjf, ':', iff, 'is',isbrdr(iif,jjf),  &
     423        'got',gbrdr(iff)
     424      IF (isbrdr(iif,jjf) .AND. .NOT.gbrdr(iff)) THEN
     425        xf = iif
     426        yf = jjf
     427        EXIT
     428      END IF
     429    END IF
     430  END DO
     431
     432  RETURN
     433
     434END SUBROUTINE look_clockwise_borders
     435
     436SUBROUTINE borders_matrixL(dx,dy,dxy,Lmat,brdrs,isbrdr)
     437! Subroutine to provide the borders of a logical array (interested in .TRUE.)
     438
     439  IMPLICIT NONE
     440
     441  INTEGER, INTENT(in)                                    :: dx,dy,dxy
     442  LOGICAL, DIMENSION(dx,dy), INTENT(in)                  :: Lmat
     443  INTEGER, DIMENSION(dxy,2), INTENT(out)                 :: brdrs
     444  LOGICAL, DIMENSION(dx,dy), INTENT(out)                 :: isbrdr
     445
     446! Local
     447  INTEGER                                                :: i,j,ib
     448
     449!!!!!!! Variables
     450! dx,dy: size of the space
     451! dxy: maximum number of border points
     452! Lmat: Matrix to look for the borders
     453! brdrs: list of coordinates of the borders
     454! isbrdr: matrix with .T./.F. wether the given matrix point is a border or not
     455
     456  fname = 'borders_matrixL'
     457
     458  isbrdr = .FALSE.
     459  brdrs = -1
     460  ib = 1
     461
     462  ! Starting with the borders. If a given point is TRUE it is a path-vertex
     463  ! Along y-axis
     464  DO i=1, dx
     465    IF (Lmat(i,1) .AND. .NOT.isbrdr(i,1)) THEN
     466      brdrs(ib,1) = i
     467      brdrs(ib,2) = 1
     468      isbrdr(i,1) = .TRUE.
     469      ib=ib+1
     470    END IF
     471    IF (Lmat(i,dy) .AND. .NOT.isbrdr(i,dy)) THEN
     472      brdrs(ib,1) = i
     473      brdrs(ib,2) = dy
     474      isbrdr(i,dy) = .TRUE.
     475      ib=ib+1
     476    END IF
     477  END DO
     478  ! Along x-axis
     479  DO j=1, dy
     480    IF (Lmat(1,j) .AND. .NOT.isbrdr(1,j)) THEN
     481      brdrs(ib,1) = 1
     482      brdrs(ib,2) = j
     483      isbrdr(1,j) = .TRUE.
     484      ib=ib+1
     485     END IF
     486    IF (Lmat(dx,j) .AND. .NOT.isbrdr(dx,j)) THEN
     487      brdrs(ib,1) = dx
     488      brdrs(ib,2) = j
     489      isbrdr(dx,j) = .TRUE.
     490      ib=ib+1
     491    END IF
     492  END DO
     493
     494  ! Border as that when looking on x-axis points with Lmat(i) /= Lmat(i+1)
     495  DO i=1, dx-1
     496    DO j=1, dy-1
     497      IF ( Lmat(i,j) .NEQV. Lmat(i+1,j) ) THEN
     498        IF (Lmat(i,j) .AND. .NOT.isbrdr(i,j)) THEN
     499          brdrs(ib,1) = i
     500          brdrs(ib,2) = j
     501          isbrdr(i,j) = .TRUE.
     502          ib=ib+1
     503        ELSE IF (Lmat(i+1,j) .AND. .NOT.isbrdr(i+1,j)) THEN
     504          brdrs(ib,1) = i+1
     505          brdrs(ib,2) = j
     506          isbrdr(i+1,j) = .TRUE.
     507          ib=ib+1
     508        END IF
     509      END IF
     510      ! y-axis
     511      IF ( Lmat(i,j) .NEQV. Lmat(i,j+1) ) THEN
     512        IF (Lmat(i,j) .AND. .NOT.isbrdr(i,j)) THEN
     513          brdrs(ib,1) = i
     514          brdrs(ib,2) = j
     515          isbrdr(i,j) = .TRUE.
     516          ib=ib+1
     517        ELSE IF (Lmat(i,j+1) .AND. .NOT.isbrdr(i,j+1)) THEN
     518          brdrs(ib,1) = i
     519          brdrs(ib,2) = j+1
     520          isbrdr(i,j+1) = .TRUE.
     521          ib=ib+1
     522        END IF
     523      END IF
     524    END DO       
     525  END DO
     526
     527  RETURN
     528
     529END SUBROUTINE borders_matrixL
     530
     531SUBROUTINE paths_border(dbg, dx, dy, isborder, Nppt, borders, paths, Npath, Nptpaths)
     532! Subroutine to search the paths of a border field.
     533
     534  IMPLICIT NONE
     535
     536  INTEGER, INTENT(in)                                    :: dx, dy, Nppt
     537  LOGICAL, INTENT(in)                                    :: dbg
     538  LOGICAL, DIMENSION(dx,dy), INTENT(in)                  :: isborder
     539  INTEGER, DIMENSION(Nppt,2), INTENT(in)                 :: borders
     540  INTEGER, DIMENSION(Nppt,Nppt,2), INTENT(out)           :: paths
     541  INTEGER, INTENT(out)                                   :: Npath
     542  INTEGER, DIMENSION(Nppt), INTENT(out)                  :: Nptpaths
     543
     544! Local
     545  INTEGER                                                :: i,j,k,ib
     546  INTEGER                                                :: ierr
     547  INTEGER                                                :: Nbrdr
     548  LOGICAL, DIMENSION(:), ALLOCATABLE                     :: gotbrdr, emptygotbrdr
     549  INTEGER                                                :: iipth, ipath, ip, Nptspath
     550  INTEGER                                                :: iib, jjb, iip, ijp, iif, jjf, iff
     551  LOGICAL                                                :: found, finishedstep
     552
     553!!!!!!! Variables
     554! dx,dy: spatial dimensions of the space
     555! Nppt: possible number of paths and points that the paths can have
     556! isborder: boolean matrix which provide the borders of the polygon
     557! borders: coordinates of the borders of the polygon
     558! paths: coordinates of each found path
     559! Npath: number of paths found
     560! Nptpaths: number of points per path
     561
     562  fname = 'paths_border'
     563
     564  ! Sarting matrix
     565  paths = -1
     566  Npath = 0
     567  Nptspath = 0
     568  Nptpaths = -1
     569
     570  ib=1
     571  finishedstep = .FALSE.
     572
     573  ! Number of border points
     574  DO ib=1, Nppt
     575    IF (borders(ib,1) == -1 ) EXIT
     576  END DO
     577  Nbrdr = ib-1
     578   
     579  IF (dbg) THEN
     580    PRINT *,'  isborder ______'
     581    DO i=1,dx
     582      PRINT *,isborder(i,:)
     583    END DO
     584
     585    PRINT *,'    borders _______'
     586    DO i=1,Nbrdr
     587      PRINT *,'    ',i,':',borders(i,:)
     588    END DO
     589  END IF
     590
     591  ! Matrix which keeps track if a border point has been located
     592  IF (ALLOCATED(gotbrdr)) DEALLOCATE(gotbrdr)
     593  ALLOCATE(gotbrdr(Nbrdr), STAT=ierr)
     594  msg = "Problems allocating matrix 'gotbrdr'"
     595  CALL ErrMsg(msg, fname, ierr)
     596  IF (ALLOCATED(emptygotbrdr)) DEALLOCATE(emptygotbrdr)
     597  ALLOCATE(emptygotbrdr(Nbrdr), STAT=ierr)
     598  msg = "Problems allocating matrix 'emptygotbrdr'"
     599  CALL ErrMsg(msg, fname, ierr)
     600
     601  gotbrdr = .FALSE.
     602  emptygotbrdr = .FALSE.
     603
     604  ! Starting the fun...
     605   
     606  ! Looking along the lines and when a border is found, starting from there in a clock-wise way
     607  iipth = 1
     608  ipath = 1   
     609  DO ib=1,Nbrdr
     610    iib = borders(iipth,1)
     611    jjb = borders(iipth,2)
     612    ! Starting new path
     613    newpath: IF (.NOT.gotbrdr(iipth)) THEN
     614      ip = 1
     615      Nptspath = 1
     616      paths(ipath,ip,:) = borders(iipth,:)
     617      gotbrdr(iipth) = .TRUE.
     618      ! Looking for following clock-wise search
     619      ! Not looking for W, because search starts from the W
     620      iip = iib
     621      ijp = jjb
     622      DO k=1,Nbrdr
     623        IF (dbg) PRINT *,ipath,'iip jip:', iip, ijp
     624        found = .FALSE.
     625        CALL look_clockwise_borders(dx,dy,Nppt,borders,gotbrdr,isborder,iip,ijp,.FALSE.,iif,jjf,iff)
     626        IF (iif /= -1) THEN
     627          ip=ip+1
     628          paths(ipath,ip,:) = (/ iif,jjf /)
     629          found = .TRUE.
     630          gotbrdr(iff) = .TRUE.
     631          iip = iif
     632          ijp = jjf
     633          Nptspath = Nptspath + 1         
     634        END IF
     635
     636        IF (dbg) THEN
     637          PRINT *,iib,jjb,'    end of this round path:', ipath, '_____', gotbrdr
     638          DO i=1, Nptspath
     639            PRINT *,'      ',i,':',paths(ipath,i,:)
     640          END DO
     641        END IF
     642        ! If it is not found a next point, might be because it is a non-polygon related value
     643        IF (.NOT.found) THEN
     644          IF (dbg) PRINT *,'NOT FOUND !!!', gotbrdr
     645          ! Are still there available borders? 
     646          IF (ALL(gotbrdr) .EQV. .TRUE.) THEN
     647            finishedstep = .TRUE.
     648            Npath = ipath
     649            Nptpaths(ipath) = Nptspath
     650            EXIT
     651          ELSE
     652            Nptpaths(ipath) = Nptspath
     653            ! Let's have a look if the next point would be someone already in the path
     654            CALL look_clockwise_borders(dx,dy,Nppt,borders,gotbrdr,isborder,iip,ijp,.FALSE.,iif,jjf,  &
     655              iff)
     656            iff = index_list_coordsI(Nptspath, paths(ipath,:,:),(/iif,jjf/))
     657            IF (iff /= -1) THEN
     658              IF (dbg) THEN
     659                PRINT *,'    point already in Path!'
     660                PRINT *,'  path:', ipath, '_____'
     661                DO i=1, Nptspath
     662                  PRINT *,'    ',i,':',paths(ipath,i,:)
     663                END DO
     664              END IF
     665              ! Continung unfinished path
     666              iip = paths(ipath,Nptspath,1)
     667              ijp = paths(ipath,Nptspath,2)
     668              iipth = index_list_coordsI(Nppt, borders, (/iip,ijp/))
     669            ELSE
     670              ! Looking for the next available border point for the new path
     671              DO i=1,Nbrdr
     672                IF (.NOT.gotbrdr(i)) THEN
     673                  iipth = i
     674                  EXIT
     675                END IF
     676              END DO
     677              IF (dbg) PRINT *,'  Looking for next path starting at:', iipth, ' point:',              &
     678                borders(iipth,:)
     679              ipath=ipath+1
     680              EXIT
     681            END IF
     682          END IF
     683        ELSE
     684          IF (dbg) PRINT *,'  looking for next point...'
     685        END IF
     686        IF (finishedstep) EXIT
     687      END DO
     688    END IF newpath
     689  END DO
     690  Npath = ipath
     691  Nptpaths(ipath) = Nptspath
     692   
     693  DEALLOCATE (gotbrdr)
     694  DEALLOCATE (emptygotbrdr)
     695
     696  RETURN
     697
     698END SUBROUTINE paths_border
    19699
    20700SUBROUTINE rand_sample(Nvals, Nsample, sample)
Note: See TracChangeset for help on using the changeset viewer.