SABER
tools_sp.F90
Go to the documentation of this file.
1 # 1 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/tools_sp.fypp"
2 # 1 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/../instrumentation.fypp" 1
3 # 1 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/../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/external/../subr_list.fypp"
13 # 2 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/../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/external/../instrumentation.fypp"
23 # 2 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/tools_sp.fypp" 2
24 !----------------------------------------------------------------------
25 ! (C) Copyright 2018-2019 UCAR
26 !
27 ! This software is licensed under the terms of the Apache Licence Version 2.0
28 ! which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
29 !----------------------------------------------------------------------
30 ! Module: tools_sp
31 !> Spectral transforms
32 !----------------------------------------------------------------------
33 module tools_sp
34 
36 use tools_kinds, only: kind_real
37 
38 
39 implicit none
40 
41 interface splat
42  module procedure sp_splat
43 end interface
44 interface lubksb
45  module procedure sp_lubksb
46 end interface
47 interface ludcmp
48  module procedure sp_ludcmp
49 end interface
50 
51 private
52 public :: splat
53 
54 contains
55 
56 !-----------------------------------------------------------------
57 ! Subroutine: sp_splat
58 !> Compute latitude functions
59 !-----------------------------------------------------------------
60 subroutine sp_splat(IDRT,JMAX,SLAT,WLAT)
61 
62 implicit none
63 
64 ! Passed variables
65 integer,intent(in) :: IDRT !< Grid identifier
66 integer,intent(in) :: JMAX !< Number of latitudes
67 real(kind_real),intent(out) :: SLAT(JMAX) !< Sines of latitude
68 real(kind_real),intent(out) :: WLAT(JMAX) !< Gaussian weights
69 
70 ! Local variables
71 real(kind_real):: PK(JMAX/2),PKM1(JMAX/2),PKM2(JMAX/2)
72 real(kind_real):: SLATD(JMAX/2),SP,SPMAX,EPS
73 integer,parameter:: JZ=50
74 real(kind_real):: BZ(JZ)
75 real(kind_real):: DLT,D1,d,R
76 real(kind_real):: AWORK((JMAX+1)/2,((JMAX+1)/2))
77 real(kind_real):: BWORK(((JMAX+1)/2))
78 integer:: JH,JHE,JHO,J0
79 integer:: IPVT((JMAX+1)/2)
80 real(kind_real),parameter:: C=(one-(two/pi)**2)*quarter
81 integer:: J,JS,N
82 
83 ! Set name
84 
85 
86 ! Probe in
87 
88 
89 data bz / 2.4048255577_kind_real, 5.5200781103_kind_real, &
90  & 8.6537279129_kind_real, 11.7915344391_kind_real, &
91  & 14.9309177086_kind_real, 18.0710639679_kind_real, &
92  & 21.2116366299_kind_real, 24.3524715308_kind_real, &
93  & 27.4934791320_kind_real, 30.6346064684_kind_real, &
94  & 33.7758202136_kind_real, 36.9170983537_kind_real, &
95  & 40.0584257646_kind_real, 43.1997917132_kind_real, &
96  & 46.3411883717_kind_real, 49.4826098974_kind_real, &
97  & 52.6240518411_kind_real, 55.7655107550_kind_real, &
98  & 58.9069839261_kind_real, 62.0484691902_kind_real, &
99  & 65.1899648002_kind_real, 68.3314693299_kind_real, &
100  & 71.4729816036_kind_real, 74.6145006437_kind_real, &
101  & 77.7560256304_kind_real, 80.8975558711_kind_real, &
102  & 84.0390907769_kind_real, 87.1806298436_kind_real, &
103  & 90.3221726372_kind_real, 93.4637187819_kind_real, &
104  & 96.6052679510_kind_real, 99.7468198587_kind_real, &
105  & 102.888374254_kind_real, 106.029930916_kind_real, &
106  & 109.171489649_kind_real, 112.313050280_kind_real, &
107  & 115.454612653_kind_real, 118.596176630_kind_real, &
108  & 121.737742088_kind_real, 124.879308913_kind_real, &
109  & 128.020877005_kind_real, 131.162446275_kind_real, &
110  & 134.304016638_kind_real, 137.445588020_kind_real, &
111  & 140.587160352_kind_real, 143.728733573_kind_real, &
112  & 146.870307625_kind_real, 150.011882457_kind_real, &
113  & 153.153458019_kind_real, 156.295034268_kind_real /
114 
115 ! Initialization
116 eps=ten*epsilon(sp)
117 d1=one
118 j0=0
119 
120 if(idrt==4) then
121  ! Gaussian latitudes
122  jh=jmax/2
123  jhe=(jmax+1)/2
124  r=one/sqrt((real(jmax,kind_real)+half)**2+c)
125  do j=1,min(jh,jz)
126  slatd(j)=cos(bz(j)*r)
127  end do
128  do j=jz+1,jh
129  slatd(j)=cos((bz(jz)+(j-jz)*pi)*r)
130  end do
131  spmax=one
132  do while(spmax>eps)
133  spmax=zero
134  do j=1,jh
135  pkm1(j)=one
136  pk(j)=slatd(j)
137  end do
138  do n=2,jmax
139  do j=1,jh
140  pkm2(j)=pkm1(j)
141  pkm1(j)=pk(j)
142  pk(j)=real((2*n-1)*slatd(j)*pkm1(j)-(n-1)*pkm2(j),kind_real)/real(n,kind_real)
143  end do
144  end do
145  do j=1,jh
146  sp=pk(j)*(one-slatd(j)**2)/(jmax*(pkm1(j)-slatd(j)*pk(j)))
147  slatd(j)=slatd(j)-sp
148  spmax=max(spmax,abs(sp))
149  end do
150  end do
151  do j=1,jh
152  slat(j)=slatd(j)
153  wlat(j)=(two*(one-slatd(j)**2))/(jmax*pkm1(j))**2
154  slat(jmax+1-j)=-slat(j)
155  wlat(jmax+1-j)=wlat(j)
156  end do
157  if(jhe>jh) then
158  slat(jhe)=zero
159  wlat(jhe)=two/jmax**2
160  do n=2,jmax,2
161  wlat(jhe)=wlat(jhe)*n**2/(n-1)**2
162  end do
163  end if
164 else if(idrt==0) then
165  ! Equally-spaced latitudes including poles
166  jh=jmax/2
167  jhe=(jmax+1)/2
168  jho=jhe-1
169  dlt=pi/(jmax-1)
170  slat(1)=one
171  do j=2,jh
172  slat(j)=cos(real((j-1),kind_real)*dlt)
173  end do
174  do js=1,jho
175  do j=1,jho
176  awork(js,j)=cos(real(2*(js-1)*j,kind_real)*dlt)
177  end do
178  end do
179  do js=1,jho
180  bwork(js)=-d1/real((4*(js-1)**2-1),kind_real)
181  end do
182  call ludcmp(awork,jho,jhe,ipvt)
183  call lubksb(awork,jho,jhe,ipvt,bwork)
184  wlat(1)=zero
185  do j=1,jho
186  wlat(j+1)=bwork(j)
187  end do
188  do j=1,jh
189  slat(jmax+1-j)=-slat(j)
190  wlat(jmax+1-j)=wlat(j)
191  end do
192  if(jhe>jh) then
193  slat(jhe)=zero
194  wlat(jhe)=two*wlat(jhe)
195  end if
196 else if(idrt==256) then
197  ! Equally-spaced latitudes excluding poles
198  jh=jmax/2
199  jhe=(jmax+1)/2
200  jho=jhe
201  dlt=pi/jmax
202  slat(1)=one
203  do j=1,jh
204  slat(j)=cos((real(j,kind_real)-half)*dlt)
205  end do
206  do js=1,jho
207  do j=1,jho
208  awork(js,j)=cos(real(2*(js-1),kind_real)*(real(j,kind_real)-half)*dlt)
209  end do
210  end do
211  do js=1,jho
212  bwork(js)=-d1/real(4*(js-1)**2-1,kind_real)
213  end do
214  call ludcmp(awork,jho,jhe,ipvt,d)
215  call lubksb(awork,jho,jhe,ipvt,bwork)
216  wlat(1)=zero
217  do j=1,jho
218  wlat(j)=bwork(j)
219  end do
220  do j=1,jh
221  slat(jmax+1-j)=-slat(j)
222  wlat(jmax+1-j)=wlat(j)
223  end do
224  if(jhe>jh) then
225  slat(jhe)=zero
226  wlat(jhe)=two*wlat(jhe)
227  end if
228 end if
229 
230 ! Probe out
231 
232 
233 end subroutine sp_splat
234 
235 !-----------------------------------------------------------------
236 ! Subroutine: sp_lubksb
237 !> Solves a system of linear equations, follows call to LUDCMP
238 !-----------------------------------------------------------------
239 subroutine sp_lubksb(A,N,NP,INDX,B)
240 
241 implicit none
242 
243 ! Passed varaibles
244 integer,intent(in):: NP !< ?
245 integer,intent(in):: N !< ?
246 real(kind_real),intent(in):: A(NP,NP) !< ?
247 real(kind_real),intent(inout):: B(N) !< ?
248 integer,intent(in):: INDX(N) !< ?
249 
250 ! Local variables
251 real(kind_real):: SUM
252 integer:: I,II,J,LL
253 
254 ! Set name
255 
256 
257 ! Probe in
258 
259 
260 ii=0
261 do i=1,n
262  ll=indx(i)
263  sum=b(ll)
264  b(ll)=b(i)
265  if(ii/=0) then
266  do j=ii,i-1
267  sum=sum-a(i,j)*b(j)
268  end do
269  else if(abs(sum)>zero) then
270  ii=i
271  end if
272  b(i)=sum
273 end do
274 do i=n,1,-1
275  sum=b(i)
276  if(i<n) then
277  do j=i+1,n
278  sum=sum-a(i,j)*b(j)
279  end do
280  end if
281  b(i)=sum/a(i,i)
282 end do
283 
284 ! Probe out
285 
286 
287 end subroutine sp_lubksb
288 
289 !-----------------------------------------------------------------
290 ! Subroutine: sp_ludcmp
291 !> Replaces an NxN matrix A with the LU decomposition
292 !-----------------------------------------------------------------
293 subroutine sp_ludcmp(A,N,NP,INDX,D)
294 
295 implicit none
296 
297 ! Passed variables
298 integer,intent(in):: N !< ?
299 integer,intent(in):: NP !< ?
300 real(kind_real),intent(inout):: A(NP,NP) !< ?
301 integer,intent(out):: INDX(N) !< ?
302 real(kind_real),intent(out),optional:: D !< ?
303 
304 ! Local variables
305 real(kind_real),parameter:: TINY=1.0e-20_kind_real
306 real(kind_real):: AAMAX,SUM,DUM
307 real(kind_real):: VV(N)
308 integer:: IMAX
309 integer:: I,J,K
310 
311 ! Set name
312 
313 
314 ! Probe in
315 
316 
317 d=one
318 do i=1,n
319  aamax=zero
320  do j=1,n
321  if(abs(a(i,j))>aamax) aamax=abs(a(i,j))
322  end do
323  if(.NOT.(abs(aamax)>zero)) print *, 'SINGULAR MATRIX.'
324  vv(i)=one/aamax
325 end do
326 do j=1,n
327  if(j>1) then
328  do i=1,j-1
329  sum=a(i,j)
330  if(i>1) then
331  do k=1,i-1
332  sum=sum-a(i,k)*a(k,j)
333  end do
334  a(i,j)=sum
335  end if
336  end do
337  end if
338  aamax=zero
339  do i=j,n
340  sum=a(i,j)
341  if(j>1) then
342  do k=1,j-1
343  sum=sum-a(i,k)*a(k,j)
344  end do
345  a(i,j)=sum
346  end if
347  dum=vv(i)*abs(sum)
348  if(dum>=aamax) then
349  imax=i
350  aamax=dum
351  end if
352  end do
353  if(j/=imax) then
354  do k=1,n
355  dum=a(imax,k)
356  a(imax,k)=a(j,k)
357  a(j,k)=dum
358  end do
359  d=-d
360  vv(imax)=vv(j)
361  end if
362  indx(j)=imax
363  if(j/=n) then
364  if(.NOT.(abs(a(j,j))>zero)) a(j,j)=tiny
365  dum=one/a(j,j)
366  do i=j+1,n
367  a(i,j)=a(i,j)*dum
368  end do
369  end if
370 end do
371 if(.NOT.(abs(a(n,n))>zero)) a(n,n)=tiny
372 
373 ! Probe out
374 
375 
376 end subroutine sp_ludcmp
377 
378 end module tools_sp
Subroutines/functions list.
Definition: tools_const.F90:31
real(kind_real), parameter, public ten
Ten.
Definition: tools_const.F90:49
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 pi
Pi.
Definition: tools_const.F90:53
real(kind_real), parameter, public zero
Zero.
Definition: tools_const.F90:37
real(kind_real), parameter, public two
Two.
Definition: tools_const.F90:43
real(kind_real), parameter, public quarter
Quarter.
Definition: tools_const.F90:40
Kinds definition.
Definition: tools_kinds.F90:9
integer, parameter, public kind_real
Real kind alias for the whole code.
Definition: tools_kinds.F90:31
Subroutines/functions list.
Definition: tools_sp.F90:33
subroutine sp_splat(IDRT, JMAX, SLAT, WLAT)
Compute latitude functions.
Definition: tools_sp.F90:61
subroutine sp_ludcmp(A, N, NP, INDX, D)
Replaces an NxN matrix A with the LU decomposition.
Definition: tools_sp.F90:294
subroutine sp_lubksb(A, N, NP, INDX, B)
Solves a system of linear equations, follows call to LUDCMP.
Definition: tools_sp.F90:240