Changeset 2340 in lmdz_wrf for trunk/tools


Ignore:
Timestamp:
Feb 15, 2019, 5:50:02 PM (6 years ago)
Author:
lfita
Message:

Adding:

  • `continguos_homogene_zones': Subroutine to look for contiguous zones by looking by continuous grid points
  • `get_xyconlimits': Subroutine for getting the limits of contiguous values from a given point in a 2D matrix
  • `Index1DArrayL': Function to provide the first index of a given value inside a 1D boolean array
  • `multi_Index1DArrayL': Subroutine to provide the indices of a given value inside a 1D boolean array
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tools/module_generic.f90

    r2331 r2340  
    33
    44!!!!!!! Subroutines/Functions
     5! continguos_homogene_zones: Subroutine to look for contiguous zones by looking by continuous grid points
    56! freeunit: provides the number of a free unit in which open a file
    67! GetInNamelist: Subroutine to get a paramter from a namelistfile
     8! get_xyconlimits: Subroutine for getting the limits of contiguous values from a given point in a 2D matrix
    79! index_list_coordsI: Function to provide the index of a given coordinate within a list of integer coordinates
    810! Index1DArrayI: Function to provide the first index of a given value inside a 1D integer array
    911! Index1DArrayR: Function to provide the first index of a given value inside a 1D real array
    1012! Index1DArrayR_K: Function to provide the first index of a given value inside a 1D real(r_k) array
     13! Index1DArrayL: Function to provide the first index of a given value inside a 1D boolean array
    1114! Index2DArrayR: Function to provide the first index of a given value inside a 2D real array
    1215! Index2DArrayR_K: Function to provide the first index of a given value inside a 2D real(r_k) array
    1316! Nvalues_2DArrayI: Number of different values of a 2D integer array
    1417! mat2DPosition: Function to provide the i, j indices of a given value inside a 2D matrix
     18! multi_Index1DArrayL: Subroutine to provide the indices of a given value inside a 1D boolean array
    1519! numberTimes: Function to provide the number of times that a given set of characters happen within a string
    1620! RangeI: Function to provide a range of d1 values from 'iniv' to 'endv', of integer values in a vector
     
    174178
    175179  END FUNCTION Index1DArrayR_K
     180
     181  INTEGER FUNCTION Index1DArrayL(array1D, d1, val)
     182! Function to provide the first index of a given value inside a 1D boolean array
     183
     184    IMPLICIT NONE
     185
     186    INTEGER, INTENT(in)                                  :: d1
     187    LOGICAL, INTENT(in)                                  :: val
     188    LOGICAL, DIMENSION(d1), INTENT(in)                   :: array1D
     189
     190! Local
     191    INTEGER                                              :: i
     192    CHARACTER(LEN=50)                                    :: fname
     193
     194    fname = 'Index1DArrayL'
     195
     196    Index1DArrayL = -1
     197
     198    DO i=1,d1
     199      IF (array1d(i) .EQV. val) THEN
     200        Index1DArrayL = i
     201        EXIT
     202      END IF
     203    END DO
     204
     205  END FUNCTION Index1DArrayL
     206
     207  SUBROUTINE multi_Index1DArrayL(array1D, d1, val, Ntimes, pos)
     208! Subroutine to provide the indices of a given value inside a 1D boolean array
     209
     210    IMPLICIT NONE
     211
     212    INTEGER, INTENT(in)                                  :: d1
     213    LOGICAL, INTENT(in)                                  :: val
     214    LOGICAL, DIMENSION(d1), INTENT(in)                   :: array1D
     215    INTEGER, INTENT(out)                                 :: Ntimes
     216    INTEGER, DIMENSION(d1), INTENT(out)                  :: pos
     217
     218! Local
     219    INTEGER                                              :: i
     220    CHARACTER(LEN=50)                                    :: fname
     221
     222!!!!!!! Variables
     223! array1D: 1D Array of values
     224! d1: length of array
     225! val: Value to look for
     226! Ntimes: Number of times val is found within array1D
     227! pos: positions of the values of val
     228
     229    fname = 'multi_Index1DArrayL'
     230
     231    Ntimes = 0
     232    pos = -1
     233
     234    DO i=1,d1
     235      IF (array1d(i) .EQV. val) THEN
     236        Ntimes = Ntimes + 1
     237        pos(Ntimes) = i
     238      END IF
     239    END DO
     240
     241  END SUBROUTINE multi_Index1DArrayL
    176242
    177243  FUNCTION Index2DArrayR(array2D, d1, d2, val)
     
    704770  END FUNCTION vectorR_S
    705771
     772  SUBROUTINE continguos_homogene_zones(dx, dy, matvals, Nzones, contzones)
     773  ! Subroutine to look for contiguous zones by looking by continuous grid points
     774
     775    IMPLICIT NONE
     776
     777    INTEGER, INTENT(in)                                  :: dx, dy
     778    INTEGER, DIMENSION(dx,dy), INTENT(in)                :: matvals
     779    INTEGER, INTENT(out)                                 :: Nzones
     780    INTEGER, DIMENSION(dx,dy), INTENT(out)               :: contzones
     781! Local
     782    INTEGER                                              :: i,j, k
     783    INTEGER                                              :: ii, ei, ij, ej
     784    INTEGER                                              :: Ncont, Nassigned, Ncontmin
     785    LOGICAL, DIMENSION(dx,dy)                            :: assigned, notdone
     786    INTEGER, DIMENSION(:), ALLOCATABLE                   :: pzones, allzones
     787    LOGICAL, DIMENSION(:), ALLOCATABLE                   :: passigns
     788
     789!!!!!!! Variables
     790! dx, dy: shape of the matrix
     791! matvals: matrix with the values
     792! contzones: homogeneous zones found
     793
     794    fname = 'continguos_homogene_zones'
     795
     796    ! Vector to keep track of all zone values
     797    IF (ALLOCATED(allzones)) DEALLOCATE(allzones)
     798    ALLOCATE(allzones(dx*dy/4))
     799    allzones = 0
     800
     801    assigned = .FALSE.
     802    notdone = .TRUE.
     803    contzones = -1
     804    Nzones = 0
     805    DO i=1, dx
     806      DO j=1, dy
     807        ! First
     808        IF (matvals(i,j) /= 0 .AND. notdone(i,j)) THEN
     809          CALL get_xyconlimits(dx, dy, matvals, 0, i, j, ii, ei, ij, ej)
     810
     811          ! Has any point of the rays already been assigned?
     812          ! Along x
     813          IF (ALLOCATED(pzones)) DEALLOCATE(pzones)
     814          ALLOCATE(pzones(ei-ii+1))
     815          IF (ALLOCATED(passigns)) DEALLOCATE(passigns)
     816          ALLOCATE(passigns(ei-ii+1))
     817          passigns = assigned(ii:ei,j)
     818          CALL multi_Index1DArrayL(passigns, ei-ii+1, .TRUE., Nassigned, pzones)
     819          IF (Nassigned /= 0) THEN
     820            Ncontmin = 10000000
     821            DO k=1, Nassigned
     822              IF (contzones(ii+pzones(k)-1,j) < Ncontmin) Ncontmin = contzones(ii+pzones(k)-1,j)
     823            END DO
     824            ! If there is more than one assigned value change all values to the minimum one
     825            DO k=1, Nassigned
     826              IF (contzones(ii+pzones(k)-1,j) /= Ncontmin) THEN
     827                WHERE (contzones == contzones(ii+pzones(k)-1,j) .AND. contzones /= Ncontmin)
     828                  contzones = Ncontmin
     829                END WHERE
     830                allzones(contzones(ii+pzones(k)-1,j)) = 0
     831              END IF
     832            END DO
     833            Ncont = Ncontmin
     834          END IF
     835          ! Along y
     836          IF (ALLOCATED(pzones)) DEALLOCATE(pzones)
     837          ALLOCATE(pzones(ej-ij+1))
     838          IF (ALLOCATED(passigns)) DEALLOCATE(passigns)
     839          ALLOCATE(passigns(ej-ij+1))
     840          passigns = assigned(i,ij:ej)
     841          CALL multi_Index1DArrayL(passigns, ej-ij+1, .TRUE., Nassigned, pzones)
     842          IF (Nassigned /= 0) THEN
     843            Ncontmin = 10000000
     844            DO k=1, Nassigned
     845              IF (contzones(i,ij+pzones(k)-1) < Ncontmin) Ncontmin = contzones(i,ij+pzones(k)-1)
     846            END DO
     847            ! If there is more than one assigned value change all values to the minimum one
     848            DO k=1, Nassigned
     849              IF (contzones(i,ij+pzones(k)-1) /= Ncontmin) THEN
     850                WHERE (contzones == contzones(i,ij+pzones(k)-1) .AND. contzones /= Ncontmin)
     851                  contzones = Ncontmin
     852                END WHERE
     853                allzones(contzones(i,ij+pzones(k)-1)) = 0
     854              END IF
     855            END DO
     856            Ncont = Ncontmin
     857          END IF
     858
     859          IF (.NOT.assigned(i,j)) THEN
     860            Nzones = Nzones + 1
     861            Ncont = Nzones
     862            allzones(Nzones) = 1
     863          ELSE
     864            Ncont = contzones(i,j)
     865          END IF
     866          contzones(i,j) = Ncont
     867          contzones(ii:ei,j) = Ncont
     868          contzones(i,ij:ej) = Ncont
     869          notdone(i,j) = .FALSE.
     870          assigned(i,j) = .TRUE.
     871          assigned(ii:ei,j) = .TRUE.
     872          assigned(i,ij:ej) = .TRUE.
     873        END IF
     874      END DO
     875    END DO
     876
     877    ! Using allzones to provide continuous assigned values
     878    Nzones = 0
     879    DO k=1, dx*dy/4
     880      IF (allzones(k) /= 0) THEN
     881        Nzones = Nzones + 1
     882        IF (allzones(k) /= Nzones) THEN
     883          WHERE(contzones == allzones(k))
     884            contzones = Nzones
     885          END WHERE
     886        END IF
     887      END IF
     888    END DO
     889
     890    RETURN
     891
     892  END SUBROUTINE continguos_homogene_zones
     893
     894  SUBROUTINE get_xyconlimits(d1, d2, matv, NOval, i, j, ix, ex, iy, ey)
     895  ! Subroutine for getting the limits of contiguous values from a given point in a 2D matrix
     896
     897    IMPLICIT NONE
     898
     899    INTEGER, INTENT(in)                                  :: d1, d2, i, j, NOval
     900    INTEGER, DIMENSION(d1,d2), INTENT(in)                :: matv
     901    INTEGER, INTENT(out)                                 :: ix, ex, iy, ey
     902
     903    ! Local
     904    INTEGER                                              :: i1, j1
     905    LOGICAL                                              :: found
     906
     907!!!!!!! Variables
     908! d1, d2: Shape of input 2D values
     909! i, j: grid point from which get the contiguous values
     910! NOval: value for grid points without data
     911! matv: 2D matrx values
     912! ix, ex, iy, ey: limits from a grid point
     913
     914    fname = 'get_xyconlimits'
     915
     916    ix = -1
     917    ex = -1
     918    iy = -1
     919    ey = -1
     920
     921    ! Before i
     922    IF (i > 1) THEN
     923      ix = i
     924      found = .FALSE.
     925      DO i1=i-1,1,-1
     926        IF (matv(i1,j) == NOval) THEN
     927          ix = i1 + 1
     928          found = .TRUE.
     929          EXIT
     930        END IF
     931      END DO
     932      IF (.NOT.found) ix=1
     933    ELSE
     934      ix = 1
     935    END IF
     936    ! After i
     937    IF (i < d1) THEN
     938      ex = i
     939      found = .FALSE.
     940      DO i1=i+1,d1
     941        IF (matv(i1,j) == NOval) THEN
     942          ex = i1 - 1
     943          found = .TRUE.
     944          EXIT
     945        END IF
     946      END DO
     947      IF (.NOT.found) ex=d1
     948    ELSE
     949      ex = d1
     950    END IF
     951
     952    ! Before j
     953    IF (j > 1) THEN
     954      iy = j
     955      found = .FALSE.
     956      DO j1=j-1,1,-1
     957        IF (matv(i,j1) == NOval) THEN
     958          iy = j1 + 1
     959          found = .TRUE.
     960          EXIT
     961        END IF
     962      END DO
     963      IF (.NOT.found) iy=1
     964    ELSE
     965      iy = 1
     966    END IF
     967    ! After j
     968    IF (j < d2) THEN
     969      ey = j
     970      found = .FALSE.
     971      DO j1=j+1,d2
     972        IF (matv(i,j1) == NOval) THEN
     973          ey = j1 - 1
     974          found = .TRUE.
     975          EXIT
     976        END IF
     977      END DO
     978      IF (.NOT.found) ey=d2
     979    ELSE
     980      ey = d2
     981    END IF
     982
     983    RETURN
     984
     985  END SUBROUTINE get_xyconlimits
     986
    706987END MODULE module_generic
Note: See TracChangeset for help on using the changeset viewer.