FV3 Bundle
Sort_Utility.f90
Go to the documentation of this file.
1 !
2 ! Sort_Utility
3 !
4 ! Module containing routines for sorting
5 !
6 !
7 ! CREATION HISTORY:
8 ! Written by: Paul van Delst, 30-May-2006
9 ! paul.vandelst@noaa.gov
10 !
11 
13 
14  ! ------------------
15  ! Environment set up
16  ! ------------------
17  ! Module usage
18  USE type_kinds
19  ! Diable implicit typing
20  IMPLICIT NONE
21 
22 
23  ! ------------
24  ! Visibilities
25  ! ------------
26  ! Everything private by default
27  PRIVATE
28  ! Public routines in this module
29  PUBLIC :: insertionsort
30  PUBLIC :: uniquecount
31  PUBLIC :: unique
32 
33 
34  ! ---------------------
35  ! Procedure overloading
36  ! ---------------------
37  INTERFACE insertionsort
38  MODULE PROCEDURE isort_long
39  MODULE PROCEDURE isortidx_long
40  MODULE PROCEDURE isort_char
41  MODULE PROCEDURE isortidx_char
42 ! MODULE PROCEDURE iSort_Single
43 ! MODULE PROCEDURE iSort_Double
44  END INTERFACE insertionsort
45 
46  INTERFACE uniquecount
47  MODULE PROCEDURE uniquecount_long
48  MODULE PROCEDURE uniquecount_char
49  END INTERFACE uniquecount
50 
51  INTERFACE unique
52  MODULE PROCEDURE unique_long
53  MODULE PROCEDURE unique_char
54  END INTERFACE unique
55 
56 
57 CONTAINS
58 
59 
60  PURE SUBROUTINE isort_long( x )
61  INTEGER(Long), DIMENSION(:), INTENT(IN OUT) :: x
62  INTEGER(Long) :: t
63  INTEGER :: n, i, j
64  n=SIZE(x)
65  DO i = 2, n
66  t = x(i)
67  j = i
68  DO
69  IF ( j < 2 ) EXIT
70  IF ( x(j-1) < t ) EXIT ! Separate exit since no short circuit
71  x(j) = x(j-1)
72  j = j-1
73  END DO
74  x(j) = t
75  END DO
76  END SUBROUTINE isort_long
77 
78  PURE SUBROUTINE isortidx_long( x, Idx )
79  INTEGER(Long), DIMENSION(:), INTENT(IN) :: x
80  INTEGER, DIMENSION(SIZE(x)), INTENT(OUT) :: idx
81  INTEGER(Long) :: t
82  INTEGER :: u
83  INTEGER :: n, i, j
84  n=SIZE(x)
85  idx=(/(i,i=1,n)/)
86  DO i = 2, n
87  u = idx(i)
88  t = x(u)
89  j = i
90  DO
91  IF ( j < 2 ) EXIT
92  IF ( x(idx(j-1)) < t ) EXIT ! Separate exit since no short circuit
93  idx(j) = idx(j-1)
94  j = j-1
95  END DO
96  idx(j) = u
97  END DO
98  END SUBROUTINE isortidx_long
99 
100 
101  PURE SUBROUTINE isort_char( x )
102  CHARACTER(*), DIMENSION(:), INTENT(IN OUT) :: x
103  CHARACTER(LEN(x(1))) :: t
104  INTEGER :: n, i, j
105  n=SIZE(x)
106  DO i = 2, n
107  t = x(i)
108  j = i
109  DO
110  IF ( j < 2 ) EXIT
111  IF ( llt(x(j-1),t) ) EXIT ! Separate exit since no short circuit
112  x(j) = x(j-1)
113  j = j-1
114  END DO
115  x(j) = t
116  END DO
117  END SUBROUTINE isort_char
118 
119 
120  PURE SUBROUTINE isortidx_char( x, Idx )
121  CHARACTER(*), DIMENSION(:), INTENT(IN) :: x
122  INTEGER, DIMENSION(SIZE(x)), INTENT(OUT) :: idx
123  CHARACTER(LEN(x(1))) :: t
124  INTEGER :: u
125  INTEGER :: n, i, j
126  n=SIZE(x)
127  idx=(/(i,i=1,n)/)
128  DO i = 2, n
129  u = idx(i)
130  t = x(u)
131  j = i
132  DO
133  IF ( j < 2 ) EXIT
134  IF ( llt(x(idx(j-1)),t) ) EXIT ! Separate exit since no short circuit
135  idx(j) = idx(j-1)
136  j = j-1
137  END DO
138  idx(j) = u
139  END DO
140  END SUBROUTINE isortidx_char
141 
142 
143  PURE FUNCTION uniquecount_long( x ) RESULT( n )
144  INTEGER(Long), INTENT(IN) :: x(:)
145  INTEGER(Long) :: n
146  INTEGER(Long) :: lx(size(x))
147  n = SIZE(x)
148  IF ( n < 2 ) RETURN
149  lx = x
150  CALL insertionsort(lx)
151  n = count(lx /= cshift(lx,-1))
152  END FUNCTION uniquecount_long
153 
154 
155  PURE FUNCTION uniquecount_char( x ) RESULT( n )
156  CHARACTER(*), INTENT(IN) :: x(:)
157  INTEGER(Long) :: n
158  CHARACTER(LEN(x)) :: lx(size(x))
159  n = SIZE(x)
160  IF ( n < 2 ) RETURN
161  lx = x
162  CALL insertionsort(lx)
163  n = count(lx /= cshift(lx,-1))
164  END FUNCTION uniquecount_char
165 
166 
167  PURE FUNCTION unique_long( x ) RESULT( ux )
168  INTEGER(Long), INTENT(IN) :: x(:)
169  INTEGER(Long) :: ux(uniquecount(x))
170  INTEGER(Long) :: lx(size(x))
171  IF ( SIZE(x) == 1 ) THEN
172  ux = x
173  RETURN
174  END IF
175  lx = x
176  CALL insertionsort(lx)
177  ux = pack(lx, lx /= cshift(lx,-1))
178  END FUNCTION unique_long
179 
180 
181  PURE FUNCTION unique_char( x ) RESULT( ux )
182  CHARACTER(*), INTENT(IN) :: x(:)
183  CHARACTER(LEN(x)) :: ux(uniquecount(x))
184  CHARACTER(LEN(x)) :: lx(size(x))
185  IF ( SIZE(x) == 1 ) THEN
186  ux = x
187  RETURN
188  END IF
189  lx = x
190  CALL insertionsort(lx)
191  ux = pack(lx, lx /= cshift(lx,-1))
192  END FUNCTION unique_char
193 
194 END MODULE sort_utility
pure integer(long) function uniquecount_long(x)
pure subroutine isort_long(x)
pure subroutine isort_char(x)
pure subroutine isortidx_long(x, Idx)
pure integer(long) function uniquecount_char(x)
pure subroutine isortidx_char(x, Idx)
pure character(len(x)) function, dimension(uniquecount(x)) unique_char(x)
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************subroutine READ_RECORD_CORE_(unit, field, nwords, data, start, axsiz) integer, intent(in) ::unit type(fieldtype), intent(in) ::field integer, intent(in) ::nwords MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in) ::start(:), axsiz(:) integer(SHORT_KIND) ::i2vals(nwords)!rab used in conjunction with transfer intrinsic to determine size of a variable integer(KIND=1) ::one_byte(8) integer ::word_sz!#ifdef __sgi integer(INT_KIND) ::ivals(nwords) real(FLOAT_KIND) ::rvals(nwords)!#else! integer ::ivals(nwords)! real ::rvals(nwords)!#endif real(DOUBLE_KIND) ::r8vals(nwords) pointer(ptr1, i2vals) pointer(ptr2, ivals) pointer(ptr3, rvals) pointer(ptr4, r8vals) if(mpp_io_stack_size< nwords) call mpp_io_set_stack_size(nwords) call mpp_error(FATAL, 'MPP_READ currently requires use_netCDF option') end subroutine READ_RECORD_CORE_ subroutine READ_RECORD_(unit, field, nwords, data, time_level, domain, position, tile_count, start_in, axsiz_in)!routine that is finally called by all mpp_read routines to perform the read!a non-netCDF record contains:! field ID! a set of 4 coordinates(is:ie, js:je) giving the data subdomain! a timelevel and a timestamp(=NULLTIME if field is static)! 3D real data(stored as 1D)!if you are using direct access I/O, the RECL argument to OPEN must be large enough for the above!in a global direct access file, record position on PE is given by %record.!Treatment of timestamp:! We assume that static fields have been passed without a timestamp.! Here that is converted into a timestamp of NULLTIME.! For non-netCDF fields, field is treated no differently, but is written! with a timestamp of NULLTIME. There is no check in the code to prevent! the user from repeatedly writing a static field. integer, intent(in) ::unit, nwords type(fieldtype), intent(in) ::field MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in), optional ::time_level type(domain2D), intent(in), optional ::domain integer, intent(in), optional ::position, tile_count integer, intent(in), optional ::start_in(:), axsiz_in(:) integer, dimension(size(field%axes(:))) ::start, axsiz integer ::tlevel !, subdomain(4) integer ::i, error, is, ie, js, je, isg, ieg, jsg, jeg type(domain2d), pointer ::io_domain=> tlevel if(PRESENT(start_in) .AND. PRESENT(axsiz_in)) then if(size(start(! the data domain and compute domain must refer to the subdomain being passed ! In this ! since that attempts to gather all data on PE size(field%axes(:)) axsiz(i)
pure integer(long) function, dimension(uniquecount(x)) unique_long(x)