UFO
ufo_gnssroonedvarcheck_utils_mod.f90
Go to the documentation of this file.
1 !-------------------------------------------------------------------------------
2 ! (C) British Crown Copyright 2020 Met Office
3 !
4 ! This software is licensed under the terms of the Apache Licence Version 2.0
5 ! which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6 !-------------------------------------------------------------------------------
7 
9 
10 use, intrinsic :: iso_c_binding
11 use missing_values_mod
12 use kinds
13 
14 implicit none
15 private
17 public :: find_unique
18 public :: ops_realsortquick
21 
22 ! Add the ability to hold various data and meta-data for a variable
24  real(kind_real) :: value ! Observed value
25  real(kind_real) :: oberr ! Observation error
26  real(kind_real) :: pgefinal ! Probability of gross error
27 end type element_type
28 
29 ! Structure for the observation information
31  integer :: niter
32  integer :: id
33  real(kind_real) :: jcost
34  real(kind_real) :: latitude
35  real(kind_real) :: longitude
36  type (element_type), allocatable :: p(:)
37  type (element_type), allocatable :: q(:)
38  real(kind_real), allocatable :: solutbendingangle(:)
39  type (element_type), allocatable :: bendingangle(:)
40  type (element_type), allocatable :: impactparam(:)
41  type (element_type) :: ro_rad_curv
42  type (element_type) :: ro_geoid_und
43  integer, allocatable :: qc_flags(:)
44 end type
45 
46 ! Structure for the background (model) information
48  real(kind_real), allocatable :: za(:)
49  real(kind_real), allocatable :: zb(:)
50  real(kind_real), allocatable :: p(:)
51  real(kind_real), allocatable :: q(:)
52 end type
53 
54 contains
55 
56 !------------------------------------------------------------------------------
57 !> Find the unique entries in the input list
58 !!
59 !! \author Met Office
60 !!
61 !! \date 15/10/2020: Created
62 !!
63 subroutine find_unique(input, output)
64 
65 integer(c_size_t), intent(in) :: input(:)
66 integer, allocatable, intent(out) :: output(:)
67 
68 integer, allocatable :: unique_vals(:) ! The list of unique elements
69 integer :: nfound ! The number of unique elements found
70 integer :: cur_val ! The current value being considered
71 integer :: max_val ! The maximum value in the input list
72 
73 nfound = 0
74 allocate(unique_vals(1:size(input)))
75 
76 cur_val = minval(input) - 1
77 max_val = maxval(input)
78 do while (cur_val < max_val)
79  nfound = nfound + 1
80  cur_val = minval(input, mask=input>cur_val)
81  unique_vals(nfound) = cur_val
82 end do
83 allocate(output(nfound))
84 output = unique_vals(1:nfound)
85 
86 end subroutine find_unique
87 
88 !------------------------------------------------------------------------------
89 !> Generates a index array pointing to the elements of the array 'key'
90 ! in increasing order
91 !!
92 !! \author Met Office
93 !!
94 !! \date 15/10/2020: Created
95 !!
96 !
97 ! Method:
98 ! The heap sort invented by J.W.J.Williams is used.
99 ! A description of the method can be found in 'Numerical Recipes'
100 ! The group information array is used to allow easy sorting on several
101 ! parameters of different types. For details see the Parent Module
102 ! OpsMod_Sort
103 !
104 ! Inputs:
105 ! key : An array of character strings, to be sorted
106 !
107 ! Input/Output:
108 ! index : An integer array pointing to the sorted items.
109 !-------------------------------------------------------------------------------
110 SUBROUTINE ops_realsortquick(key, &
111  index)
112 
113 IMPLICIT NONE
114 
115 ! Subroutine arguments:
116 REAL(kind_real), INTENT(IN) :: key(:)
117 INTEGER, ALLOCATABLE, INTENT(OUT) :: index(:)
118 
119 ! Local declarations:
120 INTEGER :: n ! The number of items
121 INTEGER :: head ! heaps are tree structures: head and child refer
122 INTEGER :: child ! to related items within the tree
123 INTEGER :: j
124 INTEGER :: dum ! used to swap index items
125 CHARACTER(len=*), PARAMETER :: routinename = 'Ops_RealSortQuick'
126 
127 ! Could put in an optional mask
128 
129 n = SIZE (key)
130 ALLOCATE (index(n))
131 DO j = 1, n
132  index(j) = j
133 END DO
134 
135 ! Do heapsort: Create the heap...
136 
137 makeheap : DO j = n / 2, 1, -1
138  head = j
139  sift1 : DO
140 
141  ! find the largest out of the head and its two children...
142 
143  child = head * 2
144  IF (child > n) EXIT sift1
145  IF (child < n) THEN
146  IF (key(index(child + 1)) > key(index(child))) child = child + 1
147  END IF
148 
149  ! if the head is the largest, then sift is done...
150 
151  IF (key(index(head)) >= key(index(child))) EXIT sift1
152 
153  ! otherwise swap to put the largest child at the head,
154  ! and prepare to repeat the procedure for the head in its new
155  ! subordinate position.
156 
157  dum = index(child)
158  index(child) = index(head)
159  index(head) = dum
160  head = child
161  END DO sift1
162 END DO makeheap
163 
164 ! Retire heads of the heap, which are the largest, and
165 ! stack them at the end of the array.
166 
167 retire : DO j = n, 2, -1
168  dum = index(1)
169  index(1) = index(j)
170  index(j) = dum
171  head = 1
172 
173  ! second sift is similar to first...
174 
175  sift2: DO
176  child = head * 2
177  IF (child > (j - 1)) EXIT sift2
178  IF (child < (j - 1)) THEN
179  IF (key(index(child + 1)) > key(index(child))) child = child + 1
180  END IF
181  IF (key(index(head)) >= key(index(child))) EXIT sift2
182  dum = index(child)
183  index(child) = index(head)
184  index(head) = dum
185  head = child
186  END DO sift2
187 END DO retire
188 
189 END SUBROUTINE ops_realsortquick
190 
191 
192 !------------------------------------------------------------------------------
193 !> Allocate the singleob_type structure, given a certain number of observations,
194 ! and model levels for pressure and specific humidity.
195 !!
196 !! \author Met Office
197 !!
198 !! \date 15/10/2020: Created
199 !!
200 subroutine allocate_singleob(singleob, nobs, nlevp, nlevq)
201 
202 implicit none
203 
204 type(singleob_type), intent(out) :: singleob
205 integer, intent(in) :: nobs
206 integer, intent(in) :: nlevp
207 integer, intent(in) :: nlevq
208 
209 allocate(singleob % p(1:nlevp))
210 allocate(singleob % q(1:nlevq))
211 allocate(singleob % solutbendingangle(1:nobs))
212 allocate(singleob % bendingangle(1:nobs))
213 allocate(singleob % impactparam(1:nobs))
214 allocate(singleob % qc_flags(1:nobs))
215 
216 singleob % solutbendingangle(:) = missing_value(singleob % solutbendingangle(1))
217 singleob % qc_flags(:) = 0 ! Set to unflagged
218 
219 singleob % p(:) % value = missing_value(singleob % p(1) % value)
220 singleob % p(:) % oberr = missing_value(singleob % p(1) % oberr)
221 singleob % p(:) % pgefinal = missing_value(singleob % p(1) % pgefinal)
222 
223 singleob % q(:) % value = missing_value(singleob % q(1) % value)
224 singleob % q(:) % oberr = missing_value(singleob % q(1) % oberr)
225 singleob % q(:) % pgefinal = missing_value(singleob % q(1) % pgefinal)
226 
227 singleob % bendingangle(:) % value = missing_value(singleob % bendingangle(1) % value)
228 singleob % bendingangle(:) % oberr = missing_value(singleob % bendingangle(1) % oberr)
229 singleob % bendingangle(:) % pgefinal = missing_value(singleob % bendingangle(1) % pgefinal)
230 
231 singleob % impactparam(:) % value = missing_value(singleob % impactparam(1) % value)
232 singleob % impactparam(:) % oberr = missing_value(singleob % impactparam(1) % oberr)
233 singleob % impactparam(:) % pgefinal = missing_value(singleob % impactparam(1) % pgefinal)
234 
235 end subroutine allocate_singleob
236 
237 
238 !------------------------------------------------------------------------------
239 !> Deallocate the singleob_type structure
240 !!
241 !! \author Met Office
242 !!
243 !! \date 15/10/2020: Created
244 !!
245 subroutine deallocate_singleob(singleob)
246 
247 implicit none
248 
249 type(singleob_type), intent(inout) :: singleob
250 
251 deallocate(singleob % p)
252 deallocate(singleob % q)
253 deallocate(singleob % solutbendingangle)
254 deallocate(singleob % bendingangle)
255 deallocate(singleob % impactparam)
256 deallocate(singleob % qc_flags)
257 
258 end subroutine deallocate_singleob
259 
260 
261 !------------------------------------------------------------------------------
262 !> Allocate the structure to hold background information from a single profile.
263 !!
264 !! \author Met Office
265 !!
266 !! \date 15/10/2020: Created
267 !!
268 subroutine allocate_singlebg(singlebg, nlevp, nlevq)
269 
270 implicit none
271 
272 type(singlebg_type), intent(out) :: singlebg
273 integer, intent(in) :: nlevp
274 integer, intent(in) :: nlevq
275 
276 allocate(singlebg % za(1:nlevp))
277 allocate(singlebg % zb(1:nlevq))
278 allocate(singlebg % p(1:nlevp))
279 allocate(singlebg % q(1:nlevq))
280 
281 singlebg % za(:) = missing_value(singlebg % za(1))
282 singlebg % zb(:) = missing_value(singlebg % zb(1))
283 singlebg % p(:) = missing_value(singlebg % p(1))
284 singlebg % q(:) = missing_value(singlebg % q(1))
285 
286 end subroutine allocate_singlebg
287 
288 
289 !------------------------------------------------------------------------------
290 !> Dealloate the singlebg_type structure
291 !!
292 !! \author Met Office
293 !!
294 !! \date 15/10/2020: Created
295 !!
296 subroutine deallocate_singlebg(singlebg)
297 
298 implicit none
299 
300 type(singlebg_type), intent(inout) :: singlebg
301 
302 deallocate(singlebg % za)
303 deallocate(singlebg % zb)
304 deallocate(singlebg % p)
305 deallocate(singlebg % q)
306 
307 end subroutine deallocate_singlebg
308 
309 ! ------------------------------------------------------------------------------
subroutine, public allocate_singleob(singleob, nobs, nlevp, nlevq)
Allocate the singleob_type structure, given a certain number of observations,.
subroutine, public deallocate_singleob(singleob)
Deallocate the singleob_type structure.
subroutine, public ops_realsortquick(key, index)
Generates a index array pointing to the elements of the array 'key'.
subroutine, public deallocate_singlebg(singlebg)
Dealloate the singlebg_type structure.
subroutine, public find_unique(input, output)
Find the unique entries in the input list.
subroutine, public allocate_singlebg(singlebg, nlevp, nlevq)
Allocate the structure to hold background information from a single profile.