SABER
tools_asa007.F90
Go to the documentation of this file.
1 # 1 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/tools_asa007.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_asa007.fypp" 2
24 !----------------------------------------------------------------------
25 ! Module: tools_asa007
26 !> Inverse of symmetric positive definite matrix routines
27 ! Source: https://people.sc.fsu.edu/~jburkardt/f_src/asa007/asa007.html
28 ! Author: Michael Healy
29 ! Original licensing: none
30 ! Modified by Alan Miller
31 ! Fortran 90 version by John Burkardt
32 ! Modified by Benjamin Menetrier for BUMP
33 ! Licensing: this code is distributed under the CeCILL-C license
34 ! Copyright 2015-... UCAR, CERFACS, METEO-FRANCE and IRIT
35 !----------------------------------------------------------------------
37 
38 use tools_const, only: zero,one
39 use tools_kinds, only: kind_real
40 use tools_repro, only: inf,infeq
41 use type_mpl, only: mpl_type
42 
43 
44 implicit none
45 
46 real(kind_real),parameter :: eta = 1.0e-9_kind_real !< Small parameter for the Cholesky decomposition
47 
48 interface cholesky
49  module procedure asa007_cholesky
50 end interface
51 interface syminv
52  module procedure asa007_syminv
53 end interface
54 
55 private
56 public :: cholesky,syminv
57 
58 contains
59 
60 !----------------------------------------------------------------------
61 ! Subroutine: asa007_cholesky
62 !> Compute cholesky decomposition
63 !----------------------------------------------------------------------
64 subroutine asa007_cholesky(mpl,n,nn,a,u)
65 
66 implicit none
67 
68 ! Passed variables
69 type(mpl_type),intent(inout) :: mpl !< MPI data
70 integer,intent(in) :: n !< Matrix rank
71 integer,intent(in) :: nn !< Half-matrix size (n*(n-1)/2)
72 real(kind_real),intent(in) :: a(nn) !< Matrix
73 real(kind_real),intent(out) :: u(nn) !< Matrix square-root
74 
75 ! Local variables
76 integer :: i,icol,ii,irow,j,k,kk,l,m
77 real(kind_real) :: w,x
78 
79 ! Set name
80 
81 
82 ! Probe in
83 
84 
85 ! Initialization
86 ii = 0
87 j = 1
88 k = 0
89 if (nn/=(n*(n+1))/2) call mpl%abort('asa007_cholesky','wrong size in Cholesky decomposition')
90 w = zero
91 
92 ! Factorize column by column, ICOL = column number
93 do icol=1,n
94  ii = ii+icol
95  x = eta**2*a(ii)
96  l = 0
97  kk = 0
98 
99  ! IROW = row number within column ICOL
100  do irow=1,icol
101  kk = kk+irow
102  k = k+1
103  w = a(k)
104  m = j
105  do i=1,irow-1
106  l = l+1
107  w = w-u(l)*u(m)
108  m = m+1
109  end do
110  l = l+1
111  if (irow==icol) exit
112  if (abs(u(l))>zero) then
113  u(k) = w/u(l)
114  else
115  u(k) = zero
116  if (inf(abs(x*a(k)),w**2)) call mpl%abort('asa007_cholesky','matrix is not positive semi-definite')
117  end if
118  end do
119 
120  ! End of row, estimate relative accuracy of diagonal element
121  if (infeq(abs(w),abs(eta*a(k)))) then
122  u(k) = zero
123  else
124  if (w<zero) call mpl%abort('asa007_cholesky','matrix is not positive semi-definite')
125  u(k) = sqrt(w)
126  end if
127  j = j+icol
128 end do
129 
130 ! Probe out
131 
132 
133 end subroutine asa007_cholesky
134 
135 !----------------------------------------------------------------------
136 ! Subroutine: asa007_syminv
137 !> Compute inverse of a symmetric matrix
138 !----------------------------------------------------------------------
139 subroutine asa007_syminv(mpl,n,nn,a,c)
140 
141 implicit none
142 
143 ! Passed variables
144 type(mpl_type),intent(inout) :: mpl !< MPI data
145 integer,intent(in) :: n !< Matrix rank
146 integer,intent(in) :: nn !< Half-matrix size (n*(n-1)/2)
147 real(kind_real),intent(in) :: a(nn) !< Matrix
148 real(kind_real),intent(out) :: c(nn) !< Matrix inverse
149 
150 ! Local variables
151 integer :: i,icol,irow,j,jcol,k,l,mdiag,ndiag,nrow
152 real(kind_real) :: w(n),x
153 
154 ! Set name
155 
156 
157 ! Probe in
158 
159 
160 ! Initialization
161 nrow = n
162 if (nn/=(n*(n+1))/2) then
163  call mpl%abort('asa007_syminv','wrong size in matrix inversion')
164 end if
165 w = zero
166 
167 ! Compute the Cholesky factorization of A
168 call cholesky(mpl,n,nn,a,c)
169 
170 ! Invert C and form the product (Cinv)' * Cinv, where Cinv is the inverse of C, row by row starting with the last row
171 irow = nrow
172 ndiag = nn
173 
174 do
175  if (abs(c(ndiag))>zero) then
176  ! General case
177  l = ndiag
178  do i=irow,nrow
179  w(i) = c(l)
180  l = l+i
181  end do
182  icol = nrow
183  jcol = nn
184  mdiag = nn
185  do
186  l = jcol
187  if (icol==irow) then
188  x = one/w(irow)
189  else
190  x = zero
191  end if
192  k = nrow
193  do while (irow<k)
194  x = x-w(k)*c(l)
195  k = k-1
196  l = l-1
197  if (mdiag<l) l = l-k+1
198  end do
199  c(l) = x/w(irow)
200  if (icol<=irow) exit
201  mdiag = mdiag-icol
202  icol = icol-1
203  jcol = jcol-1
204  end do
205  else
206  ! Special case, zero diagonal element
207  l = ndiag
208  do j=irow,nrow
209  c(l) = zero
210  l = l+j
211  end do
212  end if
213  ndiag = ndiag-irow
214  irow = irow-1
215  if (irow<=0) exit
216 end do
217 
218 ! Probe out
219 
220 
221 end subroutine asa007_syminv
222 
223 end module tools_asa007
Subroutines/functions list.
real(kind_real), parameter eta
Small parameter for the Cholesky decomposition.
subroutine asa007_syminv(mpl, n, nn, a, c)
Compute inverse of a symmetric matrix.
subroutine asa007_cholesky(mpl, n, nn, a, u)
Compute cholesky decomposition.
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 zero
Zero.
Definition: tools_const.F90:37
Kinds definition.
Definition: tools_kinds.F90:9
integer, parameter, public kind_real
Real kind alias for the whole code.
Definition: tools_kinds.F90:31
Generic ranks, dimensions and types.
Definition: tools_repro.F90:42
Generic ranks, dimensions and types.
Definition: type_mpl.F90:42