SABER
tools_fit.F90
Go to the documentation of this file.
1 # 1 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/bump/tools_fit.fypp"
2 # 1 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/bump/../instrumentation.fypp" 1
3 # 1 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/bump/../subr_list.fypp" 1
4 !----------------------------------------------------------------------
5 ! Header: subr_list
6 !> Subroutines/functions list
7 ! Author: Benjamin Menetrier
8 ! Licensing: this code is distributed under the CeCILL-C license
9 ! Copyright 2015-... UCAR, CERFACS, METEO-FRANCE and IRIT
10 !----------------------------------------------------------------------
11 
12 # 926 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/bump/../subr_list.fypp"
13 # 2 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/bump/../instrumentation.fypp" 2
14 !----------------------------------------------------------------------
15 ! Header: instrumentation
16 !> Instrumentation functions
17 ! Author: Benjamin Menetrier
18 ! Licensing: this code is distributed under the CeCILL-C license
19 ! Copyright 2015-... UCAR, CERFACS, METEO-FRANCE and IRIT
20 !----------------------------------------------------------------------
21 
22 # 112 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/bump/../instrumentation.fypp"
23 # 2 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/bump/tools_fit.fypp" 2
24 !----------------------------------------------------------------------
25 ! Module: tools_fit
26 !> Fit-related tools
27 ! Author: Benjamin Menetrier
28 ! Licensing: this code is distributed under the CeCILL-C license
29 ! Copyright 2015-... UCAR, CERFACS, METEO-FRANCE and IRIT
30 !----------------------------------------------------------------------
31 module tools_fit
32 
33 use tools_const, only: zero,quarter,half,one
34 use tools_func, only: fit_func
36 use tools_repro, only: inf,sup
37 use type_mpl, only: mpl_type
38 
39 
40 implicit none
41 
42 integer,parameter :: itermax = 10 !< Maximum number of iteration for the threshold definition
43 
44 interface fast_fit
45  module procedure fit_fast_fit
46 end interface
47 interface ver_smooth
48  module procedure fit_ver_smooth
49 end interface
50 interface ver_fill
51  module procedure fit_ver_fill
52 end interface
53 
54 private
56 
57 contains
58 
59 !----------------------------------------------------------------------
60 ! Subroutine: fit_fast_fit
61 !> Fast fit length-scale estimation based on the value at mid-height
62 !----------------------------------------------------------------------
63 subroutine fit_fast_fit(mpl,n,iz,dist,raw,fit_r)
64 
65 implicit none
66 
67 ! Passed variables
68 type(mpl_type),intent(inout) :: mpl !< MPI data
69 integer,intent(in) :: n !< Vector size
70 integer,intent(in) :: iz !< Zero separation index
71 real(kind_real),intent(in) :: dist(n) !< Distance
72 real(kind_real),intent(in) :: raw(n) !< Raw data
73 real(kind_real),intent(out) :: fit_r !< Fast fit result
74 
75 ! Local variables
76 integer :: di,i,im,ip,iter
77 real(kind_real) :: th,thinv,dthinv,thtest
78 real(kind_real) :: fit_rm,fit_rp,distmin
79 real(kind_real) :: raw_tmp(n)
80 
81 ! Set name
82 
83 
84 ! Probe in
85 
86 
87 if (any(dist<zero)) call mpl%abort('fit_fast_fit','negative distance')
88 
89 if (raw(iz)>zero) then
90  if (n>1) then
91  ! Copy points that are lower than the zero-separation
92  raw_tmp = mpl%msv%valr
93  raw_tmp(iz) = one
94  do i=1,n
95  if (i/=iz) then
96  if (inf(raw(i),raw(iz))) raw_tmp(i) = raw(i)/raw(iz)
97  end if
98  end do
99 
100  if (count(mpl%msv%isnot(raw_tmp))>1) then
101  if (count(raw_tmp>zero)>1) then
102  ! Curve-dependent threshold
103  th = half*(one+minval(raw_tmp,mask=(raw_tmp>zero)))
104 
105  ! Find inverse threshold with a dichotomy
106  thinv = half
107  dthinv = quarter
108  do iter=1,itermax
109  thtest = fit_func(mpl,thinv)
110  if (sup(th,thtest)) then
111  thinv = thinv-dthinv
112  else
113  thinv = thinv+dthinv
114  end if
115  dthinv = half*dthinv
116  end do
117 
118  ! Find support radius, lower value
119  fit_rm = mpl%msv%valr
120  ip = iz
121  do di=1,n
122  ! Check whether fit value has been found
123  if (mpl%msv%is(fit_rm)) then
124  ! Index
125  im = iz-di
126 
127  ! Check index validity
128  if (im>=1) then
129  ! Check raw value validity
130  if (raw_tmp(im)>zero) then
131  ! Check whether threshold has been crossed
132  if (inf(raw_tmp(im),th)) then
133  ! Set fit value
134  fit_rm = dist(im)+(dist(ip)-dist(im))*(th-raw_tmp(im))/(raw_tmp(ip)-raw_tmp(im))
135  else
136  ! Update index
137  ip = im
138  end if
139  end if
140  end if
141  end if
142  end do
143 
144  ! Find support radius, upper value
145  fit_rp = mpl%msv%valr
146  im = iz
147  do di=1,n
148  ! Check whether fit value has been found
149  if (mpl%msv%is(fit_rp)) then
150  ! Index
151  ip = iz+di
152 
153  ! Check index validity
154  if (ip<=n) then
155  ! Check raw value validity
156  if (raw_tmp(ip)>zero) then
157  ! Check whether threshold has been crossed
158  if (inf(raw_tmp(ip),th)) then
159  ! Set fit value
160  fit_rp = dist(im)+(dist(ip)-dist(im))*(th-raw_tmp(im))/(raw_tmp(ip)-raw_tmp(im))
161  else
162  ! Update index
163  im = ip
164  end if
165  end if
166  end if
167  end if
168  end do
169 
170  ! Gather values
171  if (mpl%msv%isnot(fit_rm).and.mpl%msv%isnot(fit_rp)) then
172  fit_r = half*(fit_rm+fit_rp)
173  elseif (mpl%msv%isnot(fit_rm)) then
174  fit_r = fit_rm
175  elseif (mpl%msv%isnot(fit_rp)) then
176  fit_r = fit_rp
177  end if
178 
179  ! Normalize
180  if (mpl%msv%isnot(fit_r)) fit_r = fit_r/thinv
181 
182  ! Check positivity
183  if (inf(fit_r,zero)) fit_r = mpl%msv%valr
184  else
185  ! All positive-separation points are negative
186  fit_r = zero
187  end if
188  else
189  ! All positive-separation points are missing
190  fit_r = mpl%msv%valr
191  end if
192 
193  ! Set minimum distance
194  if (mpl%msv%isnot(fit_r)) then
195  distmin = huge_real
196  if (iz>1) distmin = min(distmin,1.0e-6_kind_real*abs(dist(iz-1)-dist(iz)))
197  if (iz<n) distmin = min(distmin,1.0e-6_kind_real*abs(dist(iz+1)-dist(iz)))
198  fit_r = max(fit_r,distmin)
199  end if
200  else
201  ! Only one point, zero radius
202  fit_r = zero
203  end if
204 else
205  ! Zero-separation point is negative
206  fit_r = mpl%msv%valr
207 end if
208 
209 ! Probe out
210 
211 
212 end subroutine fit_fast_fit
213 
214 !----------------------------------------------------------------------
215 ! Subroutine: fit_ver_smooth
216 !> Homogeneous smoothing of a vertical profile
217 !----------------------------------------------------------------------
218 subroutine fit_ver_smooth(mpl,n,x,rv,profile)
219 
220 implicit none
221 
222 ! Passed variables
223 type(mpl_type),intent(inout) :: mpl !< MPI data
224 integer,intent(in) :: n !< Vector size
225 real(kind_real),intent(in) :: x(n) !< Coordinate
226 real(kind_real),intent(in) :: rv !< Filtering support radius
227 real(kind_real),intent(inout) :: profile(n) !< Vertical profile
228 
229 ! Local variables
230 integer :: i,j
231 real(kind_real) :: kernel(n,n),distnorm,profile_init(n),norm
232 
233 ! Set name
234 
235 
236 ! Probe in
237 
238 
239 if (n>1) then
240  if (rv<zero) call mpl%abort('fit_ver_smooth','negative filtering support radius')
241 
242  if ((rv>zero).and.mpl%msv%isanynot(profile)) then
243  ! Vertical smoothing kernel
244  kernel = zero
245  do i=1,n
246  do j=1,n
247  if (mpl%msv%isnot(profile(i)).and.mpl%msv%isnot(profile(j))) then
248  ! Gaspari-Cohn (1999) function
249  distnorm = abs(x(j)-x(i))/rv
250  kernel(i,j) = fit_func(mpl,distnorm)
251  end if
252  end do
253  end do
254 
255  ! Apply kernel
256  profile_init = profile
257  profile = zero
258  do i=1,n
259  norm = zero
260  do j=1,n
261  profile(i) = profile(i)+kernel(i,j)*profile_init(j)
262  norm = norm+kernel(i,j)
263  end do
264  if (norm>zero) then
265  profile(i) = profile(i)/norm
266  else
267  profile(i) = mpl%msv%valr
268  end if
269  end do
270  end if
271 end if
272 
273 ! Probe out
274 
275 
276 end subroutine fit_ver_smooth
277 
278 !----------------------------------------------------------------------
279 ! Subroutine: fit_ver_fill
280 !> Missing values filling of a vertical profile
281 !----------------------------------------------------------------------
282 subroutine fit_ver_fill(mpl,n,x,profile)
283 
284 implicit none
285 
286 ! Passed variables
287 type(mpl_type),intent(inout) :: mpl !< MPI data
288 integer,intent(in) :: n !< Vector size
289 real(kind_real),intent(in) :: x(n) !< Coordinate
290 real(kind_real),intent(inout) :: profile(n) !< Vertical profile
291 
292 ! Local variables
293 integer :: i,j,iinf,isup
294 real(kind_real) :: profile_init(n)
295 
296 ! Set name
297 
298 
299 ! Probe in
300 
301 
302 if (mpl%msv%isanynot(profile)) then
303  ! Initialization
304  profile_init = profile
305  iinf = mpl%msv%vali
306 
307  do i=1,n
308  if (mpl%msv%isnot(profile_init(i))) then
309  ! Valid inferior point
310  iinf = i
311  else
312  ! Look for a superior point
313  isup = mpl%msv%vali
314  j = i+1
315  do while ((j<=n).and.(mpl%msv%is(isup)))
316  if (mpl%msv%isnot(profile_init(j))) isup = j
317  j = j+1
318  end do
319 
320  if (mpl%msv%isnot(iinf).and.mpl%msv%isnot(isup)) then
321  ! Interpolation
322  profile(i) = profile_init(iinf)+(x(i)-x(iinf))*(profile_init(isup)-profile_init(iinf))/(x(isup)-x(iinf))
323  elseif (mpl%msv%isnot(isup)) then
324  ! Extrapolation with nearest superior point
325  profile(i) = profile(isup)
326  elseif (mpl%msv%isnot(iinf)) then
327  ! Extrapolation with nearest inferior point
328  profile(i) = profile(iinf)
329  else
330  call mpl%abort('fit_ver_fill','too many missing values')
331  end if
332  end if
333  end do
334 end if
335 
336 ! Probe out
337 
338 
339 end subroutine fit_ver_fill
340 
341 end module tools_fit
Subroutines/functions list.
Definition: tools_const.F90:31
real(kind_real), parameter, public one
One.
Definition: tools_const.F90:42
real(kind_real), parameter, public half
Half.
Definition: tools_const.F90:41
real(kind_real), parameter, public zero
Zero.
Definition: tools_const.F90:37
real(kind_real), parameter, public quarter
Quarter.
Definition: tools_const.F90:40
Subroutines/functions list.
Definition: tools_fit.F90:31
integer, parameter itermax
Maximum number of iteration for the threshold definition.
Definition: tools_fit.F90:42
subroutine fit_ver_fill(mpl, n, x, profile)
Missing values filling of a vertical profile.
Definition: tools_fit.F90:283
subroutine fit_ver_smooth(mpl, n, x, rv, profile)
Homogeneous smoothing of a vertical profile.
Definition: tools_fit.F90:219
subroutine fit_fast_fit(mpl, n, iz, dist, raw, fit_r)
Fast fit length-scale estimation based on the value at mid-height.
Definition: tools_fit.F90:64
Subroutines/functions list.
Definition: tools_func.F90:42
Kinds definition.
Definition: tools_kinds.F90:9
integer, parameter, public kind_real
Real kind alias for the whole code.
Definition: tools_kinds.F90:31
real(kind_real), parameter, public huge_real
Real huge.
Definition: tools_kinds.F90:36
Generic ranks, dimensions and types.
Definition: tools_repro.F90:42
Generic ranks, dimensions and types.
Definition: type_mpl.F90:42