FV3 Bundle
tools_fit.F90
Go to the documentation of this file.
1 !----------------------------------------------------------------------
2 ! Module: tools_fit
3 ! Purpose: fit-related tools
4 ! Author: Benjamin Menetrier
5 ! Licensing: this code is distributed under the CeCILL-C license
6 ! Copyright © 2015-... UCAR, CERFACS, METEO-FRANCE and IRIT
7 !----------------------------------------------------------------------
8 module tools_fit
9 
10 use tools_func, only: gc99
11 use tools_kinds, only: kind_real
13 use tools_repro, only: inf,sup
14 use type_mpl, only: mpl_type
15 
16 implicit none
17 
18 integer,parameter :: itermax = 10 ! Maximum number of iteration for the threshold definition
19 
20 private
22 
23 contains
24 
25 !----------------------------------------------------------------------
26 ! Subroutine: fast_fit
27 ! Purpose: fast fit length-scale estimation based on the value at mid-height
28 !----------------------------------------------------------------------
29 subroutine fast_fit(mpl,n,iz,dist,raw,fit_r)
30 
31 implicit none
32 
33 ! Passed variables
34 type(mpl_type),intent(in) :: mpl ! MPI data
35 integer,intent(in) :: n ! Vector size
36 integer,intent(in) :: iz ! Zero separation index
37 real(kind_real),intent(in) :: dist(n) ! Distance
38 real(kind_real),intent(in) :: raw(n) ! Raw data
39 real(kind_real),intent(out) :: fit_r ! Fast fit result
40 
41 ! Local variables
42 integer :: di,i,im,ip,iter
43 real(kind_real) :: th,thinv,dthinv,thtest
44 real(kind_real) :: fit_rm,fit_rp
45 real(kind_real) :: raw_tmp(n)
46 logical :: valid
47 
48 if (any(dist<0.0)) call mpl%abort('negative distance in fast_fit')
49 
50 if (raw(iz)>0.0) then
51  if (n>1) then
52  ! Copy points that are lower than the zero-separation
53  call msr(raw_tmp)
54  raw_tmp(iz) = raw(iz)
55  do i=1,n
56  if (i/=iz) then
57  if (inf(raw(i),raw(iz))) raw_tmp(i) = raw(i)
58  end if
59  end do
60 
61  ! At least one positive point is needed
62  valid = .false.
63  do i=1,n
64  if (i/=iz) then
65  if (raw_tmp(i)>0.0) valid = .true.
66  end if
67  end do
68 
69  if (valid) then
70  ! Define threshold and its inverse
71  if (inf(minval(raw_tmp/raw_tmp(iz),mask=(raw_tmp>0.0)),0.5_kind_real)) then
72  ! Default threshold
73  th = 0.5
74  thinv = 0.33827292796125663
75  else
76  ! Curve-dependent threshold
77  th = minval(raw_tmp/raw_tmp(iz),mask=(raw_tmp>0.0))+1.0e-6
78 
79  ! Find inverse threshold by dichotomy
80  thinv = 0.5
81  dthinv = 0.25
82  do iter=1,itermax
83  thtest = gc99(mpl,thinv)
84  if (sup(th,thtest)) then
85  thinv = thinv-dthinv
86  else
87  thinv = thinv+dthinv
88  end if
89  dthinv = 0.5*dthinv
90  end do
91  end if
92 
93  ! Find support radius, lower value
94  call msr(fit_rm)
95  ip = iz
96  do di=1,n
97  ! Check whether fit value has been found
98  if (ismsr(fit_rm)) then
99  ! Index
100  im = iz-di
101 
102  ! Check index validity
103  if (im>=1) then
104  ! Check raw value validity
105  if (raw_tmp(im)>0.0) then
106  ! Check whether threshold has been crossed
107  if (inf(raw_tmp(im),th*raw_tmp(iz))) then
108  ! Set fit value
109  fit_rm = dist(im)+(dist(ip)-dist(im))*(th*raw_tmp(iz)-raw_tmp(im))/(raw_tmp(ip)-raw_tmp(im))
110  else
111  ! Update index
112  ip = im
113  end if
114  end if
115  end if
116  end if
117  end do
118 
119  ! Find support radius, upper value
120  call msr(fit_rp)
121  im = iz
122  do di=1,n
123  ! Check whether fit value has been found
124  if (ismsr(fit_rp)) then
125  ! Index
126  ip = iz+di
127 
128  ! Check index validity
129  if (ip<=n) then
130  ! Check raw value validity
131  if (raw_tmp(ip)>0.0) then
132  ! Check whether threshold has been crossed
133  if (inf(raw_tmp(ip),th*raw_tmp(iz))) then
134  ! Set fit value
135  fit_rp = dist(im)+(dist(ip)-dist(im))*(th*raw_tmp(iz)-raw_tmp(im))/(raw_tmp(ip)-raw_tmp(im))
136  else
137  ! Update index
138  im = ip
139  end if
140  end if
141  end if
142  end if
143  end do
144 
145  ! Gather values
146  if (isnotmsr(fit_rm).and.isnotmsr(fit_rp)) then
147  fit_r = 0.5*(fit_rm+fit_rp)
148  elseif (isnotmsr(fit_rm)) then
149  fit_r = fit_rm
150  elseif (isnotmsr(fit_rp)) then
151  fit_r = fit_rp
152  end if
153 
154  ! Normalize
155  if (isnotmsr(fit_r)) fit_r = fit_r/thinv
156 
157  ! Check positivity
158  if (inf(fit_r,0.0_kind_real)) then
159  call mpl%warning('negative fit_r in fast_fit')
160  fit_r = 0.0
161  end if
162  else
163  ! Only the zero-separation point is valid, zero radius
164  fit_r = 0.0
165  end if
166  else
167  ! Only one point, zero radius
168  fit_r = 0.0
169  end if
170 else
171  ! Zero-separation point is negative
172  call msr(fit_r)
173 end if
174 
175 end subroutine fast_fit
176 
177 !----------------------------------------------------------------------
178 ! Subroutine: ver_smooth
179 ! Purpose: homogeneous smoothing of a vertical profile
180 !----------------------------------------------------------------------
181 subroutine ver_smooth(mpl,n,x,rv,profile)
183 implicit none
184 
185 ! Passed variables
186 type(mpl_type),intent(in) :: mpl ! MPI data
187 integer,intent(in) :: n ! Vector size
188 real(kind_real),intent(in) :: x(n) ! Coordinate
189 real(kind_real),intent(in) :: rv ! Filtering support radius
190 real(kind_real),intent(inout) :: profile(n) ! Vertical profile
191 
192 ! Local variables
193 integer :: i,j
194 real(kind_real) :: kernel(n,n),distnorm,profile_init(n),norm
195 
196 if (rv<0.0) call mpl%abort('negative filtering support radius in ver_smooth')
197 
198 if ((rv>0.0).and.isanynotmsr(profile)) then
199  ! Vertical smoothing kernel
200  kernel = 0.0
201  do i=1,n
202  do j=1,n
203  if (isnotmsr(profile(j))) then
204  ! Gaspari-Cohn (1999) function
205  distnorm = abs(x(j)-x(i))/rv
206  kernel(i,j) = gc99(mpl,distnorm)
207  end if
208  end do
209  end do
210 
211  ! Apply kernel
212  profile_init = profile
213  profile = 0.0
214  do i=1,n
215  norm = 0.0
216  do j=1,n
217  profile(i) = profile(i)+kernel(i,j)*profile_init(j)
218  norm = norm+kernel(i,j)
219  end do
220  if (norm>0.0) then
221  profile(i) = profile(i)/norm
222  else
223  call msr(profile(i))
224  end if
225  end do
226 end if
227 
228 end subroutine ver_smooth
229 
230 !----------------------------------------------------------------------
231 ! Subroutine: ver_fill
232 ! Purpose: missing values filling of a vertical profile
233 !----------------------------------------------------------------------
234 subroutine ver_fill(mpl,n,x,profile)
236 implicit none
237 
238 ! Passed variables
239 type(mpl_type),intent(in) :: mpl ! MPI data
240 integer,intent(in) :: n ! Vector size
241 real(kind_real),intent(in) :: x(n) ! Coordinate
242 real(kind_real),intent(inout) :: profile(n) ! Vertical profile
243 
244 ! Local variables
245 integer :: i,j,iinf,isup
246 real(kind_real) :: profile_init(n)
247 
248 if (isanynotmsr(profile)) then
249  ! Initialization
250  profile_init = profile
251  call msi(iinf)
252 
253  do i=1,n
254  if (isnotmsr(profile_init(i))) then
255  ! Valid inferior point
256  iinf = i
257  else
258  ! Look for a superior point
259  call msi(isup)
260  j = i+1
261  do while ((j<=n).and.(ismsi(isup)))
262  if (isnotmsr(profile_init(j))) isup = j
263  j = j+1
264  end do
265 
266  if (isnotmsi(iinf).and.isnotmsi(isup)) then
267  ! Interpolation
268  profile(i) = profile_init(iinf)+(x(i)-x(iinf))*(profile_init(isup)-profile_init(iinf))/(x(isup)-x(iinf))
269  elseif (isnotmsi(isup)) then
270  ! Extrapolation with nearest superior point
271  profile(i) = profile(isup)
272  elseif (isnotmsi(iinf)) then
273  ! Extrapolation with nearest inferior point
274  profile(i) = profile(iinf)
275  else
276  call mpl%abort('ver_fill failed')
277  end if
278  end if
279  end do
280 end if
281 
282 end subroutine ver_fill
283 
284 end module tools_fit
logical function, public sup(x, y)
Definition: tools_repro.F90:85
subroutine, public fast_fit(mpl, n, iz, dist, raw, fit_r)
Definition: tools_fit.F90:30
integer, parameter, public ip
Definition: Type_Kinds.f90:97
real(kind_real) function, public gc99(mpl, distnorm)
Definition: tools_func.F90:518
integer, parameter itermax
Definition: tools_fit.F90:18
subroutine, public ver_smooth(mpl, n, x, rv, profile)
Definition: tools_fit.F90:182
subroutine, public ver_fill(mpl, n, x, profile)
Definition: tools_fit.F90:235
integer, parameter, public kind_real
logical function, public inf(x, y)
Definition: tools_repro.F90:47