Commit 2b83390c62d2805fd4b83574ddd5e47178368fb3

Authored by wdaniau
1 parent 8ba5c9c788

1) added fvn_sparse_det routine to compute determinant of a sparse matrix

2) added optional parameter det to fvn_sparse_solve to compute determinant
during solving
3) split the test_sparse.f90 into 4 files to test each specific interface

git-svn-id: https://lxsd.femto-st.fr/svn/fvn@64 b657c933-2333-4658-acf2-d3c7c2708721

Showing 8 changed files with 612 additions and 42 deletions Inline Diff

fvn_sparse/fvn_sparse.f90
module fvn_sparse 1 1 module fvn_sparse
use fvn_common 2 2 use fvn_common
implicit none 3 3 implicit none
4 4
! Sparse solving 5 5 ! Sparse solving
interface fvn_sparse_solve 6 6 interface fvn_sparse_solve
module procedure fvn_zl_sparse_solve,fvn_zi_sparse_solve,fvn_dl_sparse_solve,fvn_di_sparse_solve 7 7 module procedure fvn_zl_sparse_solve,fvn_zi_sparse_solve,fvn_dl_sparse_solve,fvn_di_sparse_solve
end interface fvn_sparse_solve 8 8 end interface fvn_sparse_solve
9 9
10 interface fvn_sparse_det
11 module procedure fvn_zl_sparse_det,fvn_zi_sparse_det,fvn_dl_sparse_det,fvn_di_sparse_det
12 end interface fvn_sparse_det
contains 10 13 contains
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 11 14 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! 12 15 !
! SPARSE RESOLUTION 13 16 ! SPARSE RESOLUTION
! 14 17 !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 15 18 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! 16 19 !
! Sparse resolution is done by interfaçing Tim Davi's UMFPACK 17 20 ! Sparse resolution is done by interfaçing Tim Davi's UMFPACK
! http://www.cise.ufl.edu/research/sparse/SuiteSparse/ 18 21 ! http://www.cise.ufl.edu/research/sparse/SuiteSparse/
! Used packages from SuiteSparse : AMD,UMFPACK,UFconfig 19 22 ! Used packages from SuiteSparse : AMD,UMFPACK,UFconfig
! 20 23 !
! Solve Ax=B using UMFPACK 21 24 ! Solve Ax=B using UMFPACK
! 22 25 !
! Where A is a sparse matrix given in its triplet form 23 26 ! Where A is a sparse matrix given in its triplet form
! T -> non zero elements 24 27 ! T -> non zero elements
! Ti,Tj -> row and column index (1-based) of the given elt 25 28 ! Ti,Tj -> row and column index (1-based) of the given elt
! n : rank of matrix A 26 29 ! n : rank of matrix A
! nz : number of non zero elts 27 30 ! nz : number of non zero elts
! 28 31 !
! fvn_*_sparse_solve 29 32 ! fvn_*_sparse_solve
! * = zl : double complex + integer(kind=dp_kind) 30 33 ! * = zl : double complex + integer(kind=dp_kind)
! * = zi : double complex + integer(kind=sp_kind) 31 34 ! * = zi : double complex + integer(kind=sp_kind)
! 32 35 !
subroutine fvn_zl_sparse_solve(n,nz,T,Ti,Tj,B,x,status) 33 36 subroutine fvn_zl_sparse_solve(n,nz,T,Ti,Tj,B,x,status,det)
implicit none 34 37 implicit none
integer(kind=dp_kind), intent(in) :: n,nz 35 38 integer(kind=dp_kind), intent(in) :: n,nz
complex(kind=dp_kind),dimension(nz),intent(in) :: T 36 39 complex(kind=dp_kind),dimension(nz),intent(in) :: T
integer(kind=dp_kind),dimension(nz),intent(in) :: Ti,Tj 37 40 integer(kind=dp_kind),dimension(nz),intent(in) :: Ti,Tj
complex(kind=dp_kind),dimension(n),intent(in) :: B 38 41 complex(kind=dp_kind),dimension(n),intent(in) :: B
complex(kind=dp_kind),dimension(n),intent(out) :: x 39 42 complex(kind=dp_kind),dimension(n),intent(out) :: x
integer(kind=dp_kind), intent(out) :: status 40 43 integer(kind=dp_kind), intent(out) :: status
44 complex(kind=dp_kind), optional, intent(out) :: det
41 45
integer(kind=dp_kind),dimension(:),allocatable :: wTi,wTj 42 46 integer(kind=dp_kind),dimension(:),allocatable :: wTi,wTj
real(kind=dp_kind),dimension(:),allocatable :: Tx,Tz 43 47 real(kind=dp_kind),dimension(:),allocatable :: Tx,Tz
real(kind=dp_kind),dimension(:),allocatable :: Ax,Az 44 48 real(kind=dp_kind),dimension(:),allocatable :: Ax,Az
integer(kind=dp_kind),dimension(:),allocatable :: Ap,Ai 45 49 integer(kind=dp_kind),dimension(:),allocatable :: Ap,Ai
integer(kind=dp_kind) :: symbolic,numeric 46 50 integer(kind=dp_kind) :: symbolic,numeric
real(kind=dp_kind),dimension(:),allocatable :: xx,xz,bx,bz 47 51 real(kind=dp_kind),dimension(:),allocatable :: xx,xz,bx,bz
real(kind=dp_kind),dimension(90) :: info 48 52 real(kind=dp_kind),dimension(90) :: info
real(kind=dp_kind),dimension(20) :: control 49 53 real(kind=dp_kind),dimension(20) :: control
integer(kind=dp_kind) :: sys 50 54 integer(kind=dp_kind) :: sys
55 real(kind=dp_kind) :: Mx,Mz,Ex
51 56
52 57
status=0 53 58 status=0
54 59
! we use a working copy of Ti and Tj to perform 1-based to 0-based translation 55 60 ! we use a working copy of Ti and Tj to perform 1-based to 0-based translation
! Tx and Tz are the real and imaginary parts of T 56 61 ! Tx and Tz are the real and imaginary parts of T
allocate(wTi(nz),wTj(nz)) 57 62 allocate(wTi(nz),wTj(nz))
allocate(Tx(nz),Tz(nz)) 58 63 allocate(Tx(nz),Tz(nz))
Tx=dble(T) 59 64 Tx=dble(T)
Tz=aimag(T) 60 65 Tz=aimag(T)
wTi=Ti-1 61 66 wTi=Ti-1
wTj=Tj-1 62 67 wTj=Tj-1
allocate(Ax(nz),Az(nz)) 63 68 allocate(Ax(nz),Az(nz))
allocate(Ap(n+1),Ai(nz)) 64 69 allocate(Ap(n+1),Ai(nz))
65 70
! perform the triplet to compressed column form -> Ap,Ai,Ax,Az 66 71 ! perform the triplet to compressed column form -> Ap,Ai,Ax,Az
call umfpack_zl_triplet_to_col(n,n,nz,wTi,wTj,Tx,Tz,Ap,Ai,Ax,Az,status) 67 72 call umfpack_zl_triplet_to_col(n,n,nz,wTi,wTj,Tx,Tz,Ap,Ai,Ax,Az,status)
! if status is not zero a problem has occured 68 73 ! if status is not zero a problem has occured
if (status /= 0) then 69 74 if (status /= 0) then
write(*,*) "Problem during umfpack_zl_triplet_to_col" 70 75 write(*,*) "Problem during umfpack_zl_triplet_to_col"
endif 71 76 endif
72 77
! Define defaults control values 73 78 ! Define defaults control values
call umfpack_zl_defaults(control) 74 79 call umfpack_zl_defaults(control)
75 80
! Symbolic analysis 76 81 ! Symbolic analysis
call umfpack_zl_symbolic(n,n,Ap,Ai,Ax,Az,symbolic, control, info) 77 82 call umfpack_zl_symbolic(n,n,Ap,Ai,Ax,Az,symbolic, control, info)
! info(1) should be zero 78 83 ! info(1) should be zero
if (info(1) /= 0) then 79 84 if (info(1) /= 0) then
write(*,*) "Problem during symbolic analysis" 80 85 write(*,*) "Problem during symbolic analysis"
status=info(1) 81 86 status=info(1)
endif 82 87 endif
83 88
! Numerical factorization 84 89 ! Numerical factorization
call umfpack_zl_numeric (Ap, Ai, Ax, Az, symbolic, numeric, control, info) 85 90 call umfpack_zl_numeric (Ap, Ai, Ax, Az, symbolic, numeric, control, info)
! info(1) should be zero 86 91 ! info(1) should be zero
if (info(1) /= 0) then 87 92 if (info(1) /= 0) then
write(*,*) "Problem during numerical factorization" 88 93 write(*,*) "Problem during numerical factorization"
status=info(1) 89 94 status=info(1)
endif 90 95 endif
91 96
! free the C symbolic pointer 92 97 ! free the C symbolic pointer
call umfpack_zl_free_symbolic (symbolic) 93 98 call umfpack_zl_free_symbolic (symbolic)
94 99
100 ! if parameter det is present, the determinant of the matrix is calculated
101 if (present(det) ) then
102 call umfpack_zl_get_determinant(Mx,Mz,Ex,numeric,info,status)
103 det=cmplx(Mx,Mz,kind=dp_kind)*10**Ex
104 ! info(1) should be zero
105 if (info(1) /= 0) then
106 write(*,*) "Problem during sparse determinant, returned code : ",info(1)
107 status=info(1)
108 endif
109 endif
110
111
112
allocate(bx(n),bz(n),xx(n),xz(n)) 95 113 allocate(bx(n),bz(n),xx(n),xz(n))
bx=dble(B) 96 114 bx=dble(B)
bz=aimag(B) 97 115 bz=aimag(B)
sys=0 98 116 sys=0
! sys may be used to define type of solving -> see umfpack.h 99 117 ! sys may be used to define type of solving -> see umfpack.h
100 118
! Solving 101 119 ! Solving
call umfpack_zl_solve (sys, Ap, Ai, Ax,Az, xx,xz, bx,bz, numeric, control, info) 102 120 call umfpack_zl_solve (sys, Ap, Ai, Ax,Az, xx,xz, bx,bz, numeric, control, info)
! info(1) should be zero 103 121 ! info(1) should be zero
if (info(1) /= 0) then 104 122 if (info(1) /= 0) then
write(*,*) "Problem during solving" 105 123 write(*,*) "Problem during solving"
status=info(1) 106 124 status=info(1)
endif 107 125 endif
108 126
109 127
! free the C numeric pointer 110 128 ! free the C numeric pointer
call umfpack_zl_free_numeric (numeric) 111 129 call umfpack_zl_free_numeric (numeric)
112 130
x=cmplx(xx,xz,dp_kind) 113 131 x=cmplx(xx,xz,dp_kind)
114 132
deallocate(bx,bz,xx,xz) 115 133 deallocate(bx,bz,xx,xz)
deallocate(Ax,Az) 116 134 deallocate(Ax,Az)
deallocate(Tx,Tz) 117 135 deallocate(Tx,Tz)
deallocate(wTi,wTj) 118 136 deallocate(wTi,wTj)
end subroutine 119 137 end subroutine
120 138
121 139
122 140
123 141
124 142
subroutine fvn_zi_sparse_solve(n,nz,T,Ti,Tj,B,x,status) 125 143 subroutine fvn_zi_sparse_solve(n,nz,T,Ti,Tj,B,x,status,det)
implicit none 126 144 implicit none
integer(kind=sp_kind), intent(in) :: n,nz 127 145 integer(kind=sp_kind), intent(in) :: n,nz
complex(kind=dp_kind),dimension(nz),intent(in) :: T 128 146 complex(kind=dp_kind),dimension(nz),intent(in) :: T
integer(kind=sp_kind),dimension(nz),intent(in) :: Ti,Tj 129 147 integer(kind=sp_kind),dimension(nz),intent(in) :: Ti,Tj
complex(kind=dp_kind),dimension(n),intent(in) :: B 130 148 complex(kind=dp_kind),dimension(n),intent(in) :: B
complex(kind=dp_kind),dimension(n),intent(out) :: x 131 149 complex(kind=dp_kind),dimension(n),intent(out) :: x
integer(kind=sp_kind), intent(out) :: status 132 150 integer(kind=sp_kind), intent(out) :: status
151 complex(kind=dp_kind), optional, intent(out) :: det
133 152
integer(kind=sp_kind),dimension(:),allocatable :: wTi,wTj 134 153 integer(kind=sp_kind),dimension(:),allocatable :: wTi,wTj
real(kind=dp_kind),dimension(:),allocatable :: Tx,Tz 135 154 real(kind=dp_kind),dimension(:),allocatable :: Tx,Tz
real(kind=dp_kind),dimension(:),allocatable :: Ax,Az 136 155 real(kind=dp_kind),dimension(:),allocatable :: Ax,Az
integer(kind=sp_kind),dimension(:),allocatable :: Ap,Ai 137 156 integer(kind=sp_kind),dimension(:),allocatable :: Ap,Ai
!integer(kind=dp_kind) :: symbolic,numeric 138 157 !integer(kind=dp_kind) :: symbolic,numeric
integer(kind=sp_kind),dimension(2) :: symbolic,numeric 139 158 integer(kind=sp_kind),dimension(2) :: symbolic,numeric
! As symbolic and numeric are used to store a C pointer, it is necessary to 140 159 ! As symbolic and numeric are used to store a C pointer, it is necessary to
! still use an integer(kind=dp_kind) for 64bits machines 141 160 ! still use an integer(kind=dp_kind) for 64bits machines
! An other possibility : integer(kind=sp_kind),dimension(2) :: symbolic,numeric 142 161 ! An other possibility : integer(kind=sp_kind),dimension(2) :: symbolic,numeric
real(kind=dp_kind),dimension(:),allocatable :: xx,xz,bx,bz 143 162 real(kind=dp_kind),dimension(:),allocatable :: xx,xz,bx,bz
real(kind=dp_kind),dimension(90) :: info 144 163 real(kind=dp_kind),dimension(90) :: info
real(kind=dp_kind),dimension(20) :: control 145 164 real(kind=dp_kind),dimension(20) :: control
integer(kind=sp_kind) :: sys 146 165 integer(kind=sp_kind) :: sys
166 real(kind=dp_kind) :: Mx,Mz,Ex
147 167
status=0 148 168 status=0
! we use a working copy of Ti and Tj to perform 1-based to 0-based translation 149 169 ! we use a working copy of Ti and Tj to perform 1-based to 0-based translation
! Tx and Tz are the real and imaginary parts of T 150 170 ! Tx and Tz are the real and imaginary parts of T
allocate(wTi(nz),wTj(nz)) 151 171 allocate(wTi(nz),wTj(nz))
allocate(Tx(nz),Tz(nz)) 152 172 allocate(Tx(nz),Tz(nz))
Tx=dble(T) 153 173 Tx=dble(T)
Tz=aimag(T) 154 174 Tz=aimag(T)
wTi=Ti-1 155 175 wTi=Ti-1
wTj=Tj-1 156 176 wTj=Tj-1
allocate(Ax(nz),Az(nz)) 157 177 allocate(Ax(nz),Az(nz))
allocate(Ap(n+1),Ai(nz)) 158 178 allocate(Ap(n+1),Ai(nz))
159 179
! perform the triplet to compressed column form -> Ap,Ai,Ax,Az 160 180 ! perform the triplet to compressed column form -> Ap,Ai,Ax,Az
call umfpack_zi_triplet_to_col(n,n,nz,wTi,wTj,Tx,Tz,Ap,Ai,Ax,Az,status) 161 181 call umfpack_zi_triplet_to_col(n,n,nz,wTi,wTj,Tx,Tz,Ap,Ai,Ax,Az,status)
! if status is not zero a problem has occured 162 182 ! if status is not zero a problem has occured
if (status /= 0) then 163 183 if (status /= 0) then
write(*,*) "Problem during umfpack_zl_triplet_to_col" 164 184 write(*,*) "Problem during umfpack_zl_triplet_to_col"
endif 165 185 endif
166 186
! Define defaults control values 167 187 ! Define defaults control values
call umfpack_zi_defaults(control) 168 188 call umfpack_zi_defaults(control)
169 189
! Symbolic analysis 170 190 ! Symbolic analysis
call umfpack_zi_symbolic(n,n,Ap,Ai,Ax,Az,symbolic, control, info) 171 191 call umfpack_zi_symbolic(n,n,Ap,Ai,Ax,Az,symbolic, control, info)
! info(1) should be zero 172 192 ! info(1) should be zero
if (info(1) /= 0) then 173 193 if (info(1) /= 0) then
write(*,*) "Problem during symbolic analysis" 174 194 write(*,*) "Problem during symbolic analysis"
status=info(1) 175 195 status=info(1)
endif 176 196 endif
177 197
! Numerical factorization 178 198 ! Numerical factorization
call umfpack_zi_numeric (Ap, Ai, Ax, Az, symbolic, numeric, control, info) 179 199 call umfpack_zi_numeric (Ap, Ai, Ax, Az, symbolic, numeric, control, info)
! info(1) should be zero 180 200 ! info(1) should be zero
if (info(1) /= 0) then 181 201 if (info(1) /= 0) then
write(*,*) "Problem during numerical factorization" 182 202 write(*,*) "Problem during numerical factorization"
status=info(1) 183 203 status=info(1)
endif 184 204 endif
185 205
! free the C symbolic pointer 186 206 ! free the C symbolic pointer
call umfpack_zi_free_symbolic (symbolic) 187 207 call umfpack_zi_free_symbolic (symbolic)
188 208
209 ! if parameter det is present, the determinant of the matrix is calculated
210 if (present(det) ) then
211 call umfpack_zi_get_determinant(Mx,Mz,Ex,numeric,info,status)
212 det=cmplx(Mx,Mz,kind=dp_kind)*10**Ex
213 ! info(1) should be zero
214 if (info(1) /= 0) then
215 write(*,*) "Problem during sparse determinant, returned code : ",info(1)
216 status=info(1)
217 endif
218 endif
219
220
221
222
allocate(bx(n),bz(n),xx(n),xz(n)) 189 223 allocate(bx(n),bz(n),xx(n),xz(n))
bx=dble(B) 190 224 bx=dble(B)
bz=aimag(B) 191 225 bz=aimag(B)
sys=0 192 226 sys=0
! sys may be used to define type of solving -> see umfpack.h 193 227 ! sys may be used to define type of solving -> see umfpack.h
194 228
! Solving 195 229 ! Solving
call umfpack_zi_solve (sys, Ap, Ai, Ax,Az, xx,xz, bx,bz, numeric, control, info) 196 230 call umfpack_zi_solve (sys, Ap, Ai, Ax,Az, xx,xz, bx,bz, numeric, control, info)
! info(1) should be zero 197 231 ! info(1) should be zero
if (info(1) /= 0) then 198 232 if (info(1) /= 0) then
write(*,*) "Problem during solving" 199 233 write(*,*) "Problem during solving"
status=info(1) 200 234 status=info(1)
endif 201 235 endif
202 236
! free the C numeric pointer 203 237 ! free the C numeric pointer
call umfpack_zi_free_numeric (numeric) 204 238 call umfpack_zi_free_numeric (numeric)
205 239
x=cmplx(xx,xz,dp_kind) 206 240 x=cmplx(xx,xz,dp_kind)
207 241
deallocate(bx,bz,xx,xz) 208 242 deallocate(bx,bz,xx,xz)
deallocate(Ax,Az) 209 243 deallocate(Ax,Az)
deallocate(Tx,Tz) 210 244 deallocate(Tx,Tz)
deallocate(wTi,wTj) 211 245 deallocate(wTi,wTj)
end subroutine 212 246 end subroutine
213 247
214 248
215 249
216 250
217 251
218 252
subroutine fvn_dl_sparse_solve(n,nz,T,Ti,Tj,B,x,status) 219 253 subroutine fvn_dl_sparse_solve(n,nz,T,Ti,Tj,B,x,status,det)
implicit none 220 254 implicit none
integer(kind=dp_kind), intent(in) :: n,nz 221 255 integer(kind=dp_kind), intent(in) :: n,nz
real(kind=dp_kind),dimension(nz),intent(in) :: T 222 256 real(kind=dp_kind),dimension(nz),intent(in) :: T
integer(kind=dp_kind),dimension(nz),intent(in) :: Ti,Tj 223 257 integer(kind=dp_kind),dimension(nz),intent(in) :: Ti,Tj
real(kind=dp_kind),dimension(n),intent(in) :: B 224 258 real(kind=dp_kind),dimension(n),intent(in) :: B
real(kind=dp_kind),dimension(n),intent(out) :: x 225 259 real(kind=dp_kind),dimension(n),intent(out) :: x
integer(kind=dp_kind), intent(out) :: status 226 260 integer(kind=dp_kind), intent(out) :: status
261 real(kind=dp_kind), optional, intent(out) :: det
227 262
integer(kind=dp_kind),dimension(:),allocatable :: wTi,wTj 228 263 integer(kind=dp_kind),dimension(:),allocatable :: wTi,wTj
real(kind=dp_kind),dimension(:),allocatable :: A 229 264 real(kind=dp_kind),dimension(:),allocatable :: A
integer(kind=dp_kind),dimension(:),allocatable :: Ap,Ai 230 265 integer(kind=dp_kind),dimension(:),allocatable :: Ap,Ai
!integer(kind=dp_kind) :: symbolic,numeric 231 266 !integer(kind=dp_kind) :: symbolic,numeric
integer(kind=dp_kind) :: symbolic,numeric 232 267 integer(kind=dp_kind) :: symbolic,numeric
real(kind=dp_kind),dimension(90) :: info 233 268 real(kind=dp_kind),dimension(90) :: info
real(kind=dp_kind),dimension(20) :: control 234 269 real(kind=dp_kind),dimension(20) :: control
integer(kind=dp_kind) :: sys 235 270 integer(kind=dp_kind) :: sys
271 real(kind=dp_kind) :: Mx,Ex
236 272
status=0 237 273 status=0
! we use a working copy of Ti and Tj to perform 1-based to 0-based translation 238 274 ! we use a working copy of Ti and Tj to perform 1-based to 0-based translation
allocate(wTi(nz),wTj(nz)) 239 275 allocate(wTi(nz),wTj(nz))
wTi=Ti-1 240 276 wTi=Ti-1
wTj=Tj-1 241 277 wTj=Tj-1
allocate(A(nz)) 242 278 allocate(A(nz))
allocate(Ap(n+1),Ai(nz)) 243 279 allocate(Ap(n+1),Ai(nz))
244 280
! perform the triplet to compressed column form -> Ap,Ai,Ax,Az 245 281 ! perform the triplet to compressed column form -> Ap,Ai,Ax,Az
call umfpack_dl_triplet_to_col(n,n,nz,wTi,wTj,T,Ap,Ai,A,status) 246 282 call umfpack_dl_triplet_to_col(n,n,nz,wTi,wTj,T,Ap,Ai,A,status)
! if status is not zero a problem has occured 247 283 ! if status is not zero a problem has occured
if (status /= 0) then 248 284 if (status /= 0) then
write(*,*) "Problem during umfpack_dl_triplet_to_col" 249 285 write(*,*) "Problem during umfpack_dl_triplet_to_col"
endif 250 286 endif
251 287
! Define defaults control values 252 288 ! Define defaults control values
call umfpack_dl_defaults(control) 253 289 call umfpack_dl_defaults(control)
254 290
! Symbolic analysis 255 291 ! Symbolic analysis
call umfpack_dl_symbolic(n,n,Ap,Ai,A,symbolic, control, info) 256 292 call umfpack_dl_symbolic(n,n,Ap,Ai,A,symbolic, control, info)
! info(1) should be zero 257 293 ! info(1) should be zero
if (info(1) /= 0) then 258 294 if (info(1) /= 0) then
write(*,*) "Problem during symbolic analysis" 259 295 write(*,*) "Problem during symbolic analysis"
status=info(1) 260 296 status=info(1)
endif 261 297 endif
262 298
! Numerical factorization 263 299 ! Numerical factorization
call umfpack_dl_numeric (Ap, Ai, A, symbolic, numeric, control, info) 264 300 call umfpack_dl_numeric (Ap, Ai, A, symbolic, numeric, control, info)
! info(1) should be zero 265 301 ! info(1) should be zero
if (info(1) /= 0) then 266 302 if (info(1) /= 0) then
write(*,*) "Problem during numerical factorization" 267 303 write(*,*) "Problem during numerical factorization"
status=info(1) 268 304 status=info(1)
endif 269 305 endif
270 306
! free the C symbolic pointer 271 307 ! free the C symbolic pointer
call umfpack_dl_free_symbolic (symbolic) 272 308 call umfpack_dl_free_symbolic (symbolic)
273 309
310 ! if parameter det is present, the determinant of the matrix is calculated
311 if (present(det) ) then
312 call umfpack_dl_get_determinant(Mx,Ex,numeric,info,status)
313 det=Mx*10**Ex
314 ! info(1) should be zero
315 if (info(1) /= 0) then
316 write(*,*) "Problem during sparse determinant, returned code : ",info(1)
317 status=info(1)
318 endif
319 endif
320
321
sys=0 274 322 sys=0
! sys may be used to define type of solving -> see umfpack.h 275 323 ! sys may be used to define type of solving -> see umfpack.h
276 324
! Solving 277 325 ! Solving
call umfpack_dl_solve (sys, Ap, Ai, A, x, B, numeric, control, info) 278 326 call umfpack_dl_solve (sys, Ap, Ai, A, x, B, numeric, control, info)
! info(1) should be zero 279 327 ! info(1) should be zero
if (info(1) /= 0) then 280 328 if (info(1) /= 0) then
write(*,*) "Problem during solving" 281 329 write(*,*) "Problem during solving"
status=info(1) 282 330 status=info(1)
endif 283 331 endif
284 332
! free the C numeric pointer 285 333 ! free the C numeric pointer
call umfpack_dl_free_numeric (numeric) 286 334 call umfpack_dl_free_numeric (numeric)
287 335
deallocate(A) 288 336 deallocate(A)
deallocate(wTi,wTj) 289 337 deallocate(wTi,wTj)
end subroutine 290 338 end subroutine
291 339
292 340
293 341
294 342
295 343
296 344
subroutine fvn_di_sparse_solve(n,nz,T,Ti,Tj,B,x,status) 297 345 subroutine fvn_di_sparse_solve(n,nz,T,Ti,Tj,B,x,status,det)
implicit none 298 346 implicit none
integer(kind=sp_kind), intent(in) :: n,nz 299 347 integer(kind=sp_kind), intent(in) :: n,nz
real(kind=dp_kind),dimension(nz),intent(in) :: T 300 348 real(kind=dp_kind),dimension(nz),intent(in) :: T
integer(kind=sp_kind),dimension(nz),intent(in) :: Ti,Tj 301 349 integer(kind=sp_kind),dimension(nz),intent(in) :: Ti,Tj
real(kind=dp_kind),dimension(n),intent(in) :: B 302 350 real(kind=dp_kind),dimension(n),intent(in) :: B
real(kind=dp_kind),dimension(n),intent(out) :: x 303 351 real(kind=dp_kind),dimension(n),intent(out) :: x
integer(kind=sp_kind), intent(out) :: status 304 352 integer(kind=sp_kind), intent(out) :: status
353 real(kind=dp_kind), optional, intent(out) :: det
305 354
integer(kind=sp_kind),dimension(:),allocatable :: wTi,wTj 306 355 integer(kind=sp_kind),dimension(:),allocatable :: wTi,wTj
real(kind=dp_kind),dimension(:),allocatable :: A 307 356 real(kind=dp_kind),dimension(:),allocatable :: A
integer(kind=sp_kind),dimension(:),allocatable :: Ap,Ai 308 357 integer(kind=sp_kind),dimension(:),allocatable :: Ap,Ai
!integer(kind=dp_kind) :: symbolic,numeric 309 358 !integer(kind=dp_kind) :: symbolic,numeric
integer(kind=sp_kind),dimension(2) :: symbolic,numeric 310 359 integer(kind=sp_kind),dimension(2) :: symbolic,numeric
! As symbolic and numeric are used to store a C pointer, it is necessary to 311 360 ! As symbolic and numeric are used to store a C pointer, it is necessary to
! still use an integer(kind=dp_kind) for 64bits machines 312 361 ! still use an integer(kind=dp_kind) for 64bits machines
! An other possibility : integer(kind=sp_kind),dimension(2) :: symbolic,numeric 313 362 ! An other possibility : integer(kind=sp_kind),dimension(2) :: symbolic,numeric
real(kind=dp_kind),dimension(90) :: info 314 363 real(kind=dp_kind),dimension(90) :: info
real(kind=dp_kind),dimension(20) :: control 315 364 real(kind=dp_kind),dimension(20) :: control
integer(kind=sp_kind) :: sys 316 365 integer(kind=sp_kind) :: sys
366 real(kind=dp_kind) :: Mx,Ex
317 367
status=0 318 368 status=0
! we use a working copy of Ti and Tj to perform 1-based to 0-based translation 319 369 ! we use a working copy of Ti and Tj to perform 1-based to 0-based translation
allocate(wTi(nz),wTj(nz)) 320 370 allocate(wTi(nz),wTj(nz))
wTi=Ti-1 321 371 wTi=Ti-1
wTj=Tj-1 322 372 wTj=Tj-1
allocate(A(nz)) 323 373 allocate(A(nz))
allocate(Ap(n+1),Ai(nz)) 324 374 allocate(Ap(n+1),Ai(nz))
325 375
! perform the triplet to compressed column form -> Ap,Ai,Ax,Az 326 376 ! perform the triplet to compressed column form -> Ap,Ai,Ax,Az
call umfpack_di_triplet_to_col(n,n,nz,wTi,wTj,T,Ap,Ai,A,status) 327 377 call umfpack_di_triplet_to_col(n,n,nz,wTi,wTj,T,Ap,Ai,A,status)
! if status is not zero a problem has occured 328 378 ! if status is not zero a problem has occured
if (status /= 0) then 329 379 if (status /= 0) then
write(*,*) "Problem during umfpack_di_triplet_to_col" 330 380 write(*,*) "Problem during umfpack_di_triplet_to_col"
endif 331 381 endif
332 382
! Define defaults control values 333 383 ! Define defaults control values
call umfpack_di_defaults(control) 334 384 call umfpack_di_defaults(control)
335 385
! Symbolic analysis 336 386 ! Symbolic analysis
call umfpack_di_symbolic(n,n,Ap,Ai,A,symbolic, control, info) 337 387 call umfpack_di_symbolic(n,n,Ap,Ai,A,symbolic, control, info)
! info(1) should be zero 338 388 ! info(1) should be zero
if (info(1) /= 0) then 339 389 if (info(1) /= 0) then
write(*,*) "Problem during symbolic analysis" 340 390 write(*,*) "Problem during symbolic analysis"
status=info(1) 341 391 status=info(1)
endif 342 392 endif
343 393
! Numerical factorization 344 394 ! Numerical factorization
call umfpack_di_numeric (Ap, Ai, A, symbolic, numeric, control, info) 345 395 call umfpack_di_numeric (Ap, Ai, A, symbolic, numeric, control, info)
! info(1) should be zero 346 396 ! info(1) should be zero
if (info(1) /= 0) then 347 397 if (info(1) /= 0) then
write(*,*) "Problem during numerical factorization" 348 398 write(*,*) "Problem during numerical factorization"
status=info(1) 349 399 status=info(1)
endif 350 400 endif
351 401
! free the C symbolic pointer 352 402 ! free the C symbolic pointer
call umfpack_di_free_symbolic (symbolic) 353 403 call umfpack_di_free_symbolic (symbolic)
354 404
405 ! if parameter det is present, the determinant of the matrix is calculated
406 if (present(det) ) then
407 call umfpack_di_get_determinant(Mx,Ex,numeric,info,status)
408 det=Mx*10**Ex
409 ! info(1) should be zero
410 if (info(1) /= 0) then
411 write(*,*) "Problem during sparse determinant, returned code : ",info(1)
412 status=info(1)
413 endif
414 endif
415
sys=0 355 416 sys=0
! sys may be used to define type of solving -> see umfpack.h 356 417 ! sys may be used to define type of solving -> see umfpack.h
357
! Solving 358 418 ! Solving
call umfpack_di_solve (sys, Ap, Ai, A, x, B, numeric, control, info) 359 419 call umfpack_di_solve (sys, Ap, Ai, A, x, B, numeric, control, info)
! info(1) should be zero 360 420 ! info(1) should be zero
if (info(1) /= 0) then 361 421 if (info(1) /= 0) then
write(*,*) "Problem during solving" 362 422 write(*,*) "Problem during solving"
status=info(1) 363 423 status=info(1)
endif 364 424 endif
365 425
! free the C numeric pointer 366 426 ! free the C numeric pointer
call umfpack_di_free_numeric (numeric) 367 427 call umfpack_di_free_numeric (numeric)
368 428
deallocate(A) 369 429 deallocate(A)
deallocate(wTi,wTj) 370 430 deallocate(wTi,wTj)
end subroutine 371 431 end subroutine
432
433
434 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
435 !
436 ! SPARSE DETERMINANT
437 !
438 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
439 subroutine fvn_zl_sparse_det(n,nz,T,Ti,Tj,det,status)
440 implicit none
441 integer(kind=dp_kind), intent(in) :: n,nz
442 complex(kind=dp_kind),dimension(nz),intent(in) :: T
443 integer(kind=dp_kind),dimension(nz),intent(in) :: Ti,Tj
444 complex(kind=dp_kind),intent(out) :: det
445 integer(kind=dp_kind), intent(out) :: status
446
447 integer(kind=dp_kind),dimension(:),allocatable :: wTi,wTj
448 real(kind=dp_kind),dimension(:),allocatable :: Tx,Tz
449 real(kind=dp_kind),dimension(:),allocatable :: Ax,Az
450 integer(kind=dp_kind),dimension(:),allocatable :: Ap,Ai
451 integer(kind=dp_kind) :: symbolic,numeric
452 real(kind=dp_kind),dimension(90) :: info
453 real(kind=dp_kind),dimension(20) :: control
454 real(kind=dp_kind) :: Mx,Mz,Ex
455
456
457 status=0
458
459 ! we use a working copy of Ti and Tj to perform 1-based to 0-based translation
460 ! Tx and Tz are the real and imaginary parts of T
461 allocate(wTi(nz),wTj(nz))
462 allocate(Tx(nz),Tz(nz))
463 Tx=dble(T)
464 Tz=aimag(T)
465 wTi=Ti-1
466 wTj=Tj-1
467 allocate(Ax(nz),Az(nz))
468 allocate(Ap(n+1),Ai(nz))
469
470 ! perform the triplet to compressed column form -> Ap,Ai,Ax,Az
471 call umfpack_zl_triplet_to_col(n,n,nz,wTi,wTj,Tx,Tz,Ap,Ai,Ax,Az,status)
472 ! if status is not zero a problem has occured
473 if (status /= 0) then
474 write(*,*) "Problem during umfpack_zl_triplet_to_col"
475 endif
476
477 ! Define defaults control values
478 call umfpack_zl_defaults(control)
479
480 ! Symbolic analysis
481 call umfpack_zl_symbolic(n,n,Ap,Ai,Ax,Az,symbolic, control, info)
482 ! info(1) should be zero
483 if (info(1) /= 0) then
484 write(*,*) "Problem during symbolic analysis"
485 status=info(1)
486 endif
487
488 ! Numerical factorization
489 call umfpack_zl_numeric (Ap, Ai, Ax, Az, symbolic, numeric, control, info)
490 ! info(1) should be zero
491 if (info(1) /= 0) then
492 write(*,*) "Problem during numerical factorization"
493 status=info(1)
494 endif
495
496 ! free the C symbolic pointer
497 call umfpack_zl_free_symbolic (symbolic)
498
499 call umfpack_zl_get_determinant(Mx,Mz,Ex,numeric,info,status)
500 ! info(1) should be zero
501 if (info(1) /= 0) then
502 write(*,*) "Problem during sparse determinant, returned code : ",info(1)
503 status=info(1)
504 endif
505 det=cmplx(Mx,Mz,kind=dp_kind)*10**Ex
506
507 ! free the C numeric pointer
508 call umfpack_zl_free_numeric (numeric)
509
510 deallocate(Ax,Az)
511 deallocate(Tx,Tz)
512 deallocate(wTi,wTj)
513 end subroutine
514
515
516 subroutine fvn_zi_sparse_det(n,nz,T,Ti,Tj,det,status)
517 implicit none
518 integer(kind=sp_kind), intent(in) :: n,nz
519 complex(kind=dp_kind),dimension(nz),intent(in) :: T
520 integer(kind=sp_kind),dimension(nz),intent(in) :: Ti,Tj
521 integer(kind=sp_kind), intent(out) :: status
522 complex(kind=dp_kind), intent(out) :: det
523
524 integer(kind=sp_kind),dimension(:),allocatable :: wTi,wTj
525 real(kind=dp_kind),dimension(:),allocatable :: Tx,Tz
526 real(kind=dp_kind),dimension(:),allocatable :: Ax,Az
527 integer(kind=sp_kind),dimension(:),allocatable :: Ap,Ai
528 !integer(kind=dp_kind) :: symbolic,numeric
529 integer(kind=sp_kind),dimension(2) :: symbolic,numeric
530 ! As symbolic and numeric are used to store a C pointer, it is necessary to
531 ! still use an integer(kind=dp_kind) for 64bits machines
532 ! An other possibility : integer(kind=sp_kind),dimension(2) :: symbolic,numeric
533 real(kind=dp_kind),dimension(90) :: info
534 real(kind=dp_kind),dimension(20) :: control
535 real(kind=dp_kind) :: Mx,Mz,Ex
536
537 status=0
538 ! we use a working copy of Ti and Tj to perform 1-based to 0-based translation
539 ! Tx and Tz are the real and imaginary parts of T
540 allocate(wTi(nz),wTj(nz))
541 allocate(Tx(nz),Tz(nz))
542 Tx=dble(T)
543 Tz=aimag(T)
544 wTi=Ti-1
545 wTj=Tj-1
546 allocate(Ax(nz),Az(nz))
547 allocate(Ap(n+1),Ai(nz))
548
549 ! perform the triplet to compressed column form -> Ap,Ai,Ax,Az
550 call umfpack_zi_triplet_to_col(n,n,nz,wTi,wTj,Tx,Tz,Ap,Ai,Ax,Az,status)
551 ! if status is not zero a problem has occured
552 if (status /= 0) then
553 write(*,*) "Problem during umfpack_zl_triplet_to_col"
554 endif
555
556 ! Define defaults control values
557 call umfpack_zi_defaults(control)
558
559 ! Symbolic analysis
560 call umfpack_zi_symbolic(n,n,Ap,Ai,Ax,Az,symbolic, control, info)
561 ! info(1) should be zero
562 if (info(1) /= 0) then
563 write(*,*) "Problem during symbolic analysis"
564 status=info(1)
565 endif
566
567 ! Numerical factorization
568 call umfpack_zi_numeric (Ap, Ai, Ax, Az, symbolic, numeric, control, info)
569 ! info(1) should be zero
570 if (info(1) /= 0) then
571 write(*,*) "Problem during numerical factorization"
572 status=info(1)
573 endif
574
575 ! free the C symbolic pointer
576 call umfpack_zi_free_symbolic (symbolic)
577
578 call umfpack_zi_get_determinant(Mx,Mz,Ex,numeric,info,status)
579 ! info(1) should be zero
580 if (info(1) /= 0) then
581 write(*,*) "Problem during sparse determinant, returned code : ",info(1)
582 status=info(1)
583 endif
584 det=cmplx(Mx,Mz,kind=dp_kind)*10**Ex
585
586 ! free the C numeric pointer
587 call umfpack_zi_free_numeric (numeric)
588
589 deallocate(Ax,Az)
590 deallocate(Tx,Tz)
591 deallocate(wTi,wTj)
592 end subroutine
593
594 subroutine fvn_dl_sparse_det(n,nz,T,Ti,Tj,det,status)
595 implicit none
596 integer(kind=dp_kind), intent(in) :: n,nz
597 real(kind=dp_kind),dimension(nz),intent(in) :: T
598 integer(kind=dp_kind),dimension(nz),intent(in) :: Ti,Tj
599 integer(kind=dp_kind), intent(out) :: status
600 real(kind=dp_kind), intent(out) :: det
601
602 integer(kind=dp_kind),dimension(:),allocatable :: wTi,wTj
603 real(kind=dp_kind),dimension(:),allocatable :: A
604 integer(kind=dp_kind),dimension(:),allocatable :: Ap,Ai
605 !integer(kind=dp_kind) :: symbolic,numeric
606 integer(kind=dp_kind) :: symbolic,numeric
607 real(kind=dp_kind),dimension(90) :: info
608 real(kind=dp_kind),dimension(20) :: control
609 real(kind=dp_kind) :: Mx,Ex
610
611 status=0
612 ! we use a working copy of Ti and Tj to perform 1-based to 0-based translation
613 allocate(wTi(nz),wTj(nz))
614 wTi=Ti-1
615 wTj=Tj-1
616 allocate(A(nz))
617 allocate(Ap(n+1),Ai(nz))
618
619 ! perform the triplet to compressed column form -> Ap,Ai,Ax,Az
620 call umfpack_dl_triplet_to_col(n,n,nz,wTi,wTj,T,Ap,Ai,A,status)
621 ! if status is not zero a problem has occured
622 if (status /= 0) then
623 write(*,*) "Problem during umfpack_dl_triplet_to_col"
624 endif
625
626 ! Define defaults control values
627 call umfpack_dl_defaults(control)
628
629 ! Symbolic analysis
630 call umfpack_dl_symbolic(n,n,Ap,Ai,A,symbolic, control, info)
631 ! info(1) should be zero
632 if (info(1) /= 0) then
633 write(*,*) "Problem during symbolic analysis"
634 status=info(1)
635 endif
636
637 ! Numerical factorization
638 call umfpack_dl_numeric (Ap, Ai, A, symbolic, numeric, control, info)
639 ! info(1) should be zero
640 if (info(1) /= 0) then
641 write(*,*) "Problem during numerical factorization"
642 status=info(1)
643 endif
644
645 ! free the C symbolic pointer
646 call umfpack_dl_free_symbolic (symbolic)
647
648 call umfpack_dl_get_determinant(Mx,Ex,numeric,info,status)
649 ! info(1) should be zero
650 if (info(1) /= 0) then
651 write(*,*) "Problem during sparse determinant, returned code : ",info(1)
652 status=info(1)
653 endif
654 det=Mx*10**Ex
655
656 ! free the C numeric pointer
657 call umfpack_dl_free_numeric (numeric)
658
659 deallocate(A)
660 deallocate(wTi,wTj)
661 end subroutine
662
663
664 subroutine fvn_di_sparse_det(n,nz,T,Ti,Tj,det,status)
665 implicit none
666 integer(kind=sp_kind), intent(in) :: n,nz
667 real(kind=dp_kind),dimension(nz),intent(in) :: T
668 integer(kind=sp_kind),dimension(nz),intent(in) :: Ti,Tj
669 integer(kind=sp_kind), intent(out) :: status
670 real(kind=dp_kind), intent(out) :: det
671
672 integer(kind=sp_kind),dimension(:),allocatable :: wTi,wTj
673 real(kind=dp_kind),dimension(:),allocatable :: A
674 integer(kind=sp_kind),dimension(:),allocatable :: Ap,Ai
675 !integer(kind=dp_kind) :: symbolic,numeric
676 integer(kind=sp_kind),dimension(2) :: symbolic,numeric
677 ! As symbolic and numeric are used to store a C pointer, it is necessary to
fvn_sparse/umfpack_wrapper.c
#include "umfpack.h" 1 1 #include "umfpack.h"
#include <ctype.h> 2 2 #include <ctype.h>
#include <stdio.h> 3 3 #include <stdio.h>
#ifdef NULL 4 4 #ifdef NULL
#undef NULL 5 5 #undef NULL
#endif 6 6 #endif
#define NULL 0 7 7 #define NULL 0
#define LEN 200 8 8 #define LEN 200
9 9
/* for umfpack 4.1 */ 10 10 /* for umfpack 4.1 */
/* #define UF_long long */ 11 11 /* #define UF_long long */
/* 12 12 /*
13 13
set of routines used by fvn_sparse 14 14 set of routines used by fvn_sparse
15 15
complex(8) and integer(8) 16 16 complex(8) and integer(8)
17 17
*/ 18 18 */
19 19
/* defaults */ 20 20 /* defaults */
21 21
void umfpack_zl_defaults_ (double Control [UMFPACK_CONTROL]) 22 22 void umfpack_zl_defaults_ (double Control [UMFPACK_CONTROL])
{ 23 23 {
umfpack_zl_defaults (Control) ; 24 24 umfpack_zl_defaults (Control) ;
} 25 25 }
26 26
/* free the Numeric object */ 27 27 /* free the Numeric object */
void umfpack_zl_free_numeric_(void **Numeric) 28 28 void umfpack_zl_free_numeric_(void **Numeric)
{ 29 29 {
umfpack_zl_free_numeric (Numeric) ; 30 30 umfpack_zl_free_numeric (Numeric) ;
} 31 31 }
32 32
/* free th Symbolic object */ 33 33 /* free th Symbolic object */
void umfpack_zl_free_symbolic_(void **Symbolic) 34 34 void umfpack_zl_free_symbolic_(void **Symbolic)
{ 35 35 {
umfpack_zl_free_symbolic (Symbolic) ; 36 36 umfpack_zl_free_symbolic (Symbolic) ;
} 37 37 }
38 38
/* numeric factorization */ 39 39 /* numeric factorization */
void umfpack_zl_numeric_ (UF_long Ap [ ], UF_long Ai [ ], double Ax [ ], double Az [ ], 40 40 void umfpack_zl_numeric_ (UF_long Ap [ ], UF_long Ai [ ], double Ax [ ], double Az [ ],
void **Symbolic, void **Numeric, 41 41 void **Symbolic, void **Numeric,
double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO]) 42 42 double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO])
{ 43 43 {
(void) umfpack_zl_numeric (Ap, Ai, Ax, Az, *Symbolic, Numeric, Control, Info); 44 44 (void) umfpack_zl_numeric (Ap, Ai, Ax, Az, *Symbolic, Numeric, Control, Info);
} 45 45 }
46 46
/* pre-ordering and symbolic factorization */ 47 47 /* pre-ordering and symbolic factorization */
void umfpack_zl_symbolic_ (UF_long *m, UF_long *n, UF_long Ap [ ], UF_long Ai [ ], 48 48 void umfpack_zl_symbolic_ (UF_long *m, UF_long *n, UF_long Ap [ ], UF_long Ai [ ],
double Ax [ ], double Az [ ], void **Symbolic, 49 49 double Ax [ ], double Az [ ], void **Symbolic,
double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO]) 50 50 double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO])
{ 51 51 {
(void) umfpack_zl_symbolic (*m, *n, Ap, Ai, Ax, Az, Symbolic, Control, Info) ; 52 52 (void) umfpack_zl_symbolic (*m, *n, Ap, Ai, Ax, Az, Symbolic, Control, Info) ;
} 53 53 }
54 54
/* solve a linear system */ 55 55 /* solve a linear system */
56 56
void umfpack_zl_solve_ (UF_long *sys, UF_long Ap [ ], UF_long Ai [ ], double Ax [ ], double Az [ ], 57 57 void umfpack_zl_solve_ (UF_long *sys, UF_long Ap [ ], UF_long Ai [ ], double Ax [ ], double Az [ ],
double x [ ], double xz [ ], double b [ ], double bz [ ], void **Numeric, 58 58 double x [ ], double xz [ ], double b [ ], double bz [ ], void **Numeric,
double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO]) 59 59 double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO])
{ 60 60 {
(void) umfpack_zl_solve (*sys, Ap, Ai, Ax, Az, x, xz, b, bz, 61 61 (void) umfpack_zl_solve (*sys, Ap, Ai, Ax, Az, x, xz, b, bz,
*Numeric, Control, Info) ; 62 62 *Numeric, Control, Info) ;
} 63 63 }
64 64
/* triplet 2 col */ 65 65 /* triplet 2 col */
66 66
void umfpack_zl_triplet_to_col_ (UF_long *m, UF_long *n, UF_long *nz, UF_long Ti [ ], UF_long Tj [ ], 67 67 void umfpack_zl_triplet_to_col_ (UF_long *m, UF_long *n, UF_long *nz, UF_long Ti [ ], UF_long Tj [ ],
double Tx [ ], double Tz [ ], UF_long Ap [ ], UF_long Ai [ ], 68 68 double Tx [ ], double Tz [ ], UF_long Ap [ ], UF_long Ai [ ],
double Ax [ ], double Az [ ], UF_long *status) 69 69 double Ax [ ], double Az [ ], UF_long *status)
{ 70 70 {
*status = umfpack_zl_triplet_to_col (*m, *n, *nz, Ti, Tj, Tx, Tz, Ap, Ai, Ax, Az, (UF_long *) NULL); 71 71 *status = umfpack_zl_triplet_to_col (*m, *n, *nz, Ti, Tj, Tx, Tz, Ap, Ai, Ax, Az, (UF_long *) NULL);
} 72 72 }
73 73
74 74
75 /* get determinant */
76 void umfpack_zl_get_determinant_ ( double *Mx, double *Mz, double *Ex, void **Numeric, double Info [UMFPACK_INFO], UF_long *status )
77 {
78 *status = umfpack_zl_get_determinant (Mx,Mz,Ex,*Numeric, Info);
79 }
75 80
76 81
/* complex(8) and integer(4) */ 77 82 /* complex(8) and integer(4) */
78 83
/* defaults */ 79 84 /* defaults */
80 85
void umfpack_zi_defaults_ (double Control [UMFPACK_CONTROL]) 81 86 void umfpack_zi_defaults_ (double Control [UMFPACK_CONTROL])
{ 82 87 {
umfpack_zi_defaults (Control) ; 83 88 umfpack_zi_defaults (Control) ;
} 84 89 }
85 90
86 91
/* free the Numeric object */ 87 92 /* free the Numeric object */
void umfpack_zi_free_numeric_(void **Numeric) 88 93 void umfpack_zi_free_numeric_(void **Numeric)
{ 89 94 {
umfpack_zi_free_numeric (Numeric) ; 90 95 umfpack_zi_free_numeric (Numeric) ;
} 91 96 }
92 97
/* free the Symbolic object */ 93 98 /* free the Symbolic object */
void umfpack_zi_free_symbolic_(void **Symbolic) 94 99 void umfpack_zi_free_symbolic_(void **Symbolic)
{ 95 100 {
umfpack_zi_free_symbolic (Symbolic) ; 96 101 umfpack_zi_free_symbolic (Symbolic) ;
} 97 102 }
98 103
/* numeric factorization */ 99 104 /* numeric factorization */
void umfpack_zi_numeric_ (int Ap [ ], int Ai [ ], double Ax [ ], double Az [ ], 100 105 void umfpack_zi_numeric_ (int Ap [ ], int Ai [ ], double Ax [ ], double Az [ ],
void **Symbolic, void **Numeric, 101 106 void **Symbolic, void **Numeric,
double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO]) 102 107 double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO])
{ 103 108 {
(void) umfpack_zi_numeric (Ap, Ai, Ax, Az, *Symbolic, Numeric, Control, Info); 104 109 (void) umfpack_zi_numeric (Ap, Ai, Ax, Az, *Symbolic, Numeric, Control, Info);
} 105 110 }
106 111
/* pre-ordering and symbolic factorization */ 107 112 /* pre-ordering and symbolic factorization */
void umfpack_zi_symbolic_ (int *m, int *n, int Ap [ ], int Ai [ ], 108 113 void umfpack_zi_symbolic_ (int *m, int *n, int Ap [ ], int Ai [ ],
double Ax [ ], double Az [ ], void **Symbolic, 109 114 double Ax [ ], double Az [ ], void **Symbolic,
double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO]) 110 115 double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO])
{ 111 116 {
(void) umfpack_zi_symbolic (*m, *n, Ap, Ai, Ax, Az, Symbolic, Control, Info) ; 112 117 (void) umfpack_zi_symbolic (*m, *n, Ap, Ai, Ax, Az, Symbolic, Control, Info) ;
} 113 118 }
114 119
/* solve a linear system */ 115 120 /* solve a linear system */
116 121
void umfpack_zi_solve_ (int *sys, int Ap [ ], int Ai [ ], double Ax [ ], double Az [ ], 117 122 void umfpack_zi_solve_ (int *sys, int Ap [ ], int Ai [ ], double Ax [ ], double Az [ ],
double x [ ], double xz [ ], double b [ ], double bz [ ], void **Numeric, 118 123 double x [ ], double xz [ ], double b [ ], double bz [ ], void **Numeric,
double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO]) 119 124 double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO])
{ 120 125 {
(void) umfpack_zi_solve (*sys, Ap, Ai, Ax, Az, x, xz, b, bz, 121 126 (void) umfpack_zi_solve (*sys, Ap, Ai, Ax, Az, x, xz, b, bz,
*Numeric, Control, Info) ; 122 127 *Numeric, Control, Info) ;
} 123 128 }
124 129
/* triplet 2 col */ 125 130 /* triplet 2 col */
126 131
void umfpack_zi_triplet_to_col_ (int *m, int *n, int *nz, int Ti [ ], int Tj [ ], 127 132 void umfpack_zi_triplet_to_col_ (int *m, int *n, int *nz, int Ti [ ], int Tj [ ],
double Tx [ ], double Tz [ ], int Ap [ ], int Ai [ ], 128 133 double Tx [ ], double Tz [ ], int Ap [ ], int Ai [ ],
double Ax [ ], double Az [ ], int *status) 129 134 double Ax [ ], double Az [ ], int *status)
{ 130 135 {
*status = umfpack_zi_triplet_to_col (*m, *n, *nz, Ti, Tj, Tx, Tz, Ap, Ai, Ax, Az, (int *) NULL); 131 136 *status = umfpack_zi_triplet_to_col (*m, *n, *nz, Ti, Tj, Tx, Tz, Ap, Ai, Ax, Az, (int *) NULL);
} 132 137 }
133 138
139
140 /* get determinant */
141 void umfpack_zi_get_determinant_ ( double *Mx, double *Mz, double *Ex, void **Numeric, double Info [UMFPACK_INFO], int *status )
142 {
143 *status = umfpack_zi_get_determinant (Mx,Mz,Ex,*Numeric, Info);
144 }
145
146
/* real(8) and integer(8) */ 134 147 /* real(8) and integer(8) */
135 148
/* defaults */ 136 149 /* defaults */
137 150
void umfpack_dl_defaults_ (double Control [UMFPACK_CONTROL]) 138 151 void umfpack_dl_defaults_ (double Control [UMFPACK_CONTROL])
{ 139 152 {
umfpack_dl_defaults (Control) ; 140 153 umfpack_dl_defaults (Control) ;
} 141 154 }
142 155
void umfpack_dl_free_numeric_ (void **Numeric) 143 156 void umfpack_dl_free_numeric_ (void **Numeric)
{ 144 157 {
umfpack_dl_free_numeric (Numeric) ; 145 158 umfpack_dl_free_numeric (Numeric) ;
} 146 159 }
147 160
void umfpack_dl_free_symbolic_ (void **Symbolic) 148 161 void umfpack_dl_free_symbolic_ (void **Symbolic)
{ 149 162 {
umfpack_dl_free_symbolic (Symbolic) ; 150 163 umfpack_dl_free_symbolic (Symbolic) ;
} 151 164 }
152 165
void umfpack_dl_numeric_ (UF_long Ap [ ], UF_long Ai [ ], double Ax [ ], 153 166 void umfpack_dl_numeric_ (UF_long Ap [ ], UF_long Ai [ ], double Ax [ ],
void **Symbolic, void **Numeric, 154 167 void **Symbolic, void **Numeric,
double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO]) 155 168 double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO])
{ 156 169 {
(void) umfpack_dl_numeric (Ap, Ai, Ax, *Symbolic, Numeric, Control, Info); 157 170 (void) umfpack_dl_numeric (Ap, Ai, Ax, *Symbolic, Numeric, Control, Info);
} 158 171 }
159 172
void umfpack_dl_symbolic_ (UF_long *m, UF_long *n, UF_long Ap [ ], UF_long Ai [ ], 160 173 void umfpack_dl_symbolic_ (UF_long *m, UF_long *n, UF_long Ap [ ], UF_long Ai [ ],
double Ax [ ], void **Symbolic, 161 174 double Ax [ ], void **Symbolic,
double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO]) 162 175 double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO])
{ 163 176 {
(void) umfpack_dl_symbolic (*m, *n, Ap, Ai, Ax, Symbolic, Control, Info) ; 164 177 (void) umfpack_dl_symbolic (*m, *n, Ap, Ai, Ax, Symbolic, Control, Info) ;
} 165 178 }
166 179
void umfpack_dl_solve_ (UF_long *sys, UF_long Ap [ ], UF_long Ai [ ], double Ax [ ], 167 180 void umfpack_dl_solve_ (UF_long *sys, UF_long Ap [ ], UF_long Ai [ ], double Ax [ ],
double x [ ], double b [ ], void **Numeric, 168 181 double x [ ], double b [ ], void **Numeric,
double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO]) 169 182 double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO])
{ 170 183 {
(void) umfpack_dl_solve (*sys, Ap, Ai, Ax, x, b, *Numeric, Control, Info) ; 171 184 (void) umfpack_dl_solve (*sys, Ap, Ai, Ax, x, b, *Numeric, Control, Info) ;
} 172 185 }
173 186
void umfpack_dl_triplet_to_col_ (UF_long *m, UF_long *n, UF_long *nz, UF_long Ti [ ], UF_long Tj [ ], 174 187 void umfpack_dl_triplet_to_col_ (UF_long *m, UF_long *n, UF_long *nz, UF_long Ti [ ], UF_long Tj [ ],
double T [ ], UF_long Ap [ ], UF_long Ai [ ], 175 188 double T [ ], UF_long Ap [ ], UF_long Ai [ ],
double A [ ], UF_long *status) 176 189 double A [ ], UF_long *status)
{ 177 190 {
*status = umfpack_dl_triplet_to_col (*m, *n, *nz, Ti, Tj, T, Ap, Ai, A, (UF_long *) NULL); 178 191 *status = umfpack_dl_triplet_to_col (*m, *n, *nz, Ti, Tj, T, Ap, Ai, A, (UF_long *) NULL);
} 179 192 }
180 193
194 /* get determinant */
195 void umfpack_dl_get_determinant_ ( double *Mx, double *Ex, void **Numeric, double Info [UMFPACK_INFO], UF_long *status )
196 {
197 *status = umfpack_dl_get_determinant (Mx,Ex,*Numeric, Info);
198 }
199
200
201
/* real(8) and integer(4) */ 181 202 /* real(8) and integer(4) */
182 203
/* defaults */ 183 204 /* defaults */
184 205
void umfpack_di_defaults_ (double Control [UMFPACK_CONTROL]) 185 206 void umfpack_di_defaults_ (double Control [UMFPACK_CONTROL])
1 1
include $(BTREE)/Make.inc 2 2 include $(BTREE)/Make.inc
3 3
programs = test_fac$(exext) test_matinv$(exext) test_specfunc$(exext) \ 4 4 programs = test_fac$(exext) test_matinv$(exext) test_specfunc$(exext) \
test_det$(exext) test_matcon$(exext) test_matev$(exext) test_sparse$(exext) test_inter1d$(exext) \ 5 5 test_det$(exext) test_matcon$(exext) test_matev$(exext) test_inter1d$(exext) \
test_inter2d$(exext) test_inter3d$(exext) test_akima$(exext) test_lsp$(exext) test_muller$(exext) \ 6 6 test_inter2d$(exext) test_inter3d$(exext) test_akima$(exext) test_lsp$(exext) test_muller$(exext) \
test_integ$(exext) test_bsyn$(exext) test_bsjn$(exext) test_bskn$(exext) test_bsin$(exext) test_operators$(exext) test_ze1$(exext) \ 7 7 test_integ$(exext) test_bsyn$(exext) test_bsjn$(exext) test_bskn$(exext) test_bsin$(exext) test_operators$(exext) test_ze1$(exext) \
test_besri$(exext) test_besrj$(exext) test_bestime$(exext) 8 8 test_besri$(exext) test_besrj$(exext) test_bestime$(exext) \
9 test_sparse_zi$(exext) test_sparse_zl$(exext) test_sparse_di$(exext) test_sparse_dl$(exext)
9 10
prog:$(programs) 10 11 prog:$(programs)
11 12
clean: 12 13 clean:
rm -f {*.o,*.oo,*.ipo,*.a,*.mod,*.dat} 13 14 rm -f {*.o,*.oo,*.ipo,*.a,*.mod,*.dat}
rm -f $(programs) 14 15 rm -f $(programs)
15 16
%$(exext): %.o 16 17 %$(exext): %.o
$(LINK) $(LINKFLAGS) $< init_random_seed.o $(LINKFVN) -o $@ 17 18 $(LINK) $(LINKFLAGS) $< init_random_seed.o $(LINKFVN) -o $@
fvn_test/test_sparse.f90
program test_sparse 1 File was deleted
use fvn_sparse 2
implicit none 3
integer(kind=ip_kind), parameter :: nz=12 4
integer(kind=ip_kind), parameter :: n=5 5
real(kind=dp_kind),dimension(nz) :: A 6
real(kind=dp_kind),dimension(n,n) :: As 7
integer(kind=ip_kind),dimension(nz) :: Ti,Tj 8
real(kind=dp_kind),dimension(n) :: B,x 9
integer(kind=ip_kind) :: status,i 10
! Description of the matrix in triplet form 11
A = (/ 2.,3.,3.,-1.,4.,4.,-3.,1.,2.,2.,6.,1. /) 12
B = (/ 8., 45., -3., 3., 19./) 13
Ti = (/ 1,2,1,3,5,2,3,4,5,3,2,5 /) 14
Tj = (/ 1,1,2,2,2,3,3,3,3,4,5,5 /) 15
16
! Reconstruction of the matrix in standard form 17
! just needed for printing the matrix here 18
As=0. 19
do i=1,nz 20
As(Ti(i),Tj(i))=A(i) 21
end do 22
write(*,*) "Matrix in standard representation :" 23
do i=1,5 24
write(*,'(5f8.4)') As(i,:) 25
end do 26
write(*,*) 27
write(*,'("Right hand side :",5f8.4)') B 28
29
!specific routine that will be used here 30
!call fvn_di_sparse_solve(n,nz,A,Ti,Tj,B,x,status) 31
call fvn_di_sparse_solve(n,nz,A,Ti,Tj,B,x,status) 32
write(*,'("Solution :",5f8.4)') x 33
fvn_test/test_sparse_di.f90
File was created 1 program test_sparse
2 ! test sparse routine di, real(8) and integer(4)
3 use fvn
4 implicit none
5 integer(kind=sp_kind), parameter :: nz=12
6 integer(kind=sp_kind), parameter :: n=5
7 real(kind=dp_kind),dimension(nz) :: A
8 real(kind=dp_kind),dimension(n,n) :: As
9 integer(kind=sp_kind),dimension(nz) :: Ti,Tj
10 real(kind=dp_kind),dimension(n) :: B,x
11 integer(kind=sp_kind) :: status,i
12 real(kind=dp_kind) :: det
13 ! Description of the matrix in triplet form
14 A = (/ 2.,3.,3.,-1.,4.,4.,-3.,1.,2.,2.,6.,1. /)
15 B = (/ 8., 45., -3., 3., 19./)
16 Ti = (/ 1,2,1,3,5,2,3,4,5,3,2,5 /)
17 Tj = (/ 1,1,2,2,2,3,3,3,3,4,5,5 /)
18
19 ! Reconstruction of the matrix in standard form
20 ! just needed for printing the matrix here
21 As=0.
22 do i=1,nz
23 As(Ti(i),Tj(i))=A(i)
24 end do
25 write(*,*) "Matrix in standard representation :"
26 do i=1,5
27 write(*,'(5f8.4)') As(i,:)
28 end do
29 write(*,*)
30 write(*,*) "Standard determinant =", fvn_det(5,As)
31 write(*,*)
32 write(*,'("Right hand side :",5f8.4)') B
33
34 ! can use either specific interface, fvn_di_sparse_det
35 ! either generic one fvn_sparse_det
36 call fvn_di_sparse_det(n,nz,A,Ti,Tj,det,status)
37 write(*,*)
38 write(*,*) "Sparse Det = ",det
39 ! can use either specific interface fvn_di_sparse_solve
40 ! either generic one fvn_sparse_solve
41 ! parameter det is optional
42 call fvn_di_sparse_solve(n,nz,A,Ti,Tj,B,x,status,det)
43 write(*,*)
44 write(*,*) "Sparse Det as solve option = ",det
45 write(*,*)
46 write(*,'("Solution :",5f8.4)') x
47 write(*,*)
fvn_test/test_sparse_dl.f90
File was created 1 program test_sparse
2 ! test sparse routine dl, real(8) and integer(8)
3 use fvn
4 implicit none
5 integer(kind=dp_kind), parameter :: nz=12
6 integer(kind=dp_kind), parameter :: n=5
7 real(kind=dp_kind),dimension(nz) :: A
8 real(kind=dp_kind),dimension(n,n) :: As
9 integer(kind=dp_kind),dimension(nz) :: Ti,Tj
10 real(kind=dp_kind),dimension(n) :: B,x
11 integer(kind=dp_kind) :: status,i
12 real(kind=dp_kind) :: det
13 ! Description of the matrix in triplet form
14 A = (/ 2.,3.,3.,-1.,4.,4.,-3.,1.,2.,2.,6.,1. /)
15 B = (/ 8., 45., -3., 3., 19./)
16 Ti = (/ 1,2,1,3,5,2,3,4,5,3,2,5 /)
17 Tj = (/ 1,1,2,2,2,3,3,3,3,4,5,5 /)
18
19 ! Reconstruction of the matrix in standard form
20 ! just needed for printing the matrix here
21 As=0.
22 do i=1,nz
23 As(Ti(i),Tj(i))=A(i)
24 end do
25 write(*,*) "Matrix in standard representation :"
26 do i=1,5
27 write(*,'(5f8.4)') As(i,:)
28 end do
29 write(*,*)
30 write(*,*) "Standard determinant =", fvn_det(5,As)
31 write(*,*)
32 write(*,'("Right hand side :",5f8.4)') B
33
34 ! can use either specific interface, fvn_dl_sparse_det
35 ! either generic one fvn_sparse_det
36 call fvn_dl_sparse_det(n,nz,A,Ti,Tj,det,status)
37 write(*,*)
38 write(*,*) "Sparse Det = ",det
39 ! can use either specific interface fvn_dl_sparse_solve
40 ! either generic one fvn_sparse_solve
41 ! parameter det is optional
42 call fvn_dl_sparse_solve(n,nz,A,Ti,Tj,B,x,status,det)
43 write(*,*)
44 write(*,*) "Sparse Det as solve option = ",det
45 write(*,*)
46 write(*,'("Solution :",5f8.4)') x
47 write(*,*)
fvn_test/test_sparse_zi.f90
File was created 1 program test_sparse
2 use fvn
3 implicit none
4 integer(kind=sp_kind), parameter :: nz=12
5 integer(kind=sp_kind), parameter :: n=5
6 complex(kind=dp_kind),dimension(nz) :: A
7 complex(kind=dp_kind),dimension(n,n) :: As
8 integer(kind=sp_kind),dimension(nz) :: Ti,Tj
9 complex(kind=dp_kind),dimension(n) :: B,x
10 integer(kind=sp_kind) :: status,i
11 complex(kind=dp_kind) :: det
12 character(len=80) :: fmcmplx
13
14 fmcmplx='(5("(",f8.5,",",f8.5,") "))'
15
16 ! Description of the matrix in triplet form
17 A = (/ (2.,-1.),(3.,2.),(3.,1.),(-1.,5.),(4.,-7.),(4.,0.),(-3.,-4.),(1.,3.),(2.,0.),(2.,-2.),(6.,4.),(1.,0.) /)
18 B = (/ (8.,3.), (45.,1.), (-3.,-2.), (3.,0.), (19.,2.) /)
19 Ti = (/ 1,2,1,3,5,2,3,4,5,3,2,5 /)
20 Tj = (/ 1,1,2,2,2,3,3,3,3,4,5,5 /)
21
22 ! Reconstruction of the matrix in standard form
23 As=0.
24 do i=1,nz
25 As(Ti(i),Tj(i))=A(i)
26 end do
27
28 write(*,*) "Matrix in standard representation :"
29 do i=1,5
30 write(*,fmcmplx) As(i,:)
31 end do
32 write(*,*)
33 write(*,*) "Standard determinant : ",fvn_det(5,As)
34 write(*,*)
35 write(*,*) "Right hand side :"
36 write(*,fmcmplx) B
37
38 ! can use either specific interface, fvn_zi_sparse_det
39 ! either generic one fvn_sparse_det
40 call fvn_zi_sparse_det(n,nz,A,Ti,Tj,det,status)
41 write(*,*)
42 write(*,*) "Sparse Det = ",det
43 ! can use either specific interface fvn_zi_sparse_solve
44 ! either generic one fvn_sparse_solve
45 ! parameter det is optional
46 call fvn_zi_sparse_solve(n,nz,A,Ti,Tj,B,x,status,det)
47 write(*,*)
48 write(*,*) "Sparse Det as solve option= ",det
49 write(*,*)
50 write(*,*) "Solution :"
fvn_test/test_sparse_zl.f90
File was created 1 program test_sparse
2 ! test sparse routine zl, complex(8) and integer(8)
3 use fvn
4 implicit none
5 integer(kind=dp_kind), parameter :: nz=12
6 integer(kind=dp_kind), parameter :: n=5
7 complex(kind=dp_kind),dimension(nz) :: A
8 complex(kind=dp_kind),dimension(n,n) :: As
9 integer(kind=dp_kind),dimension(nz) :: Ti,Tj
10 complex(kind=dp_kind),dimension(n) :: B,x
11 integer(kind=dp_kind) :: status,i
12 complex(kind=dp_kind) :: det
13 character(len=80) :: fmcmplx
14
15 fmcmplx='(5("(",f8.5,",",f8.5,") "))'
16
17 ! Description of the matrix in triplet form
18 A = (/ (2.,-1.),(3.,2.),(3.,1.),(-1.,5.),(4.,-7.),(4.,0.),(-3.,-4.),(1.,3.),(2.,0.),(2.,-2.),(6.,4.),(1.,0.) /)
19 B = (/ (8.,3.), (45.,1.), (-3.,-2.), (3.,0.), (19.,2.) /)
20 Ti = (/ 1,2,1,3,5,2,3,4,5,3,2,5 /)
21 Tj = (/ 1,1,2,2,2,3,3,3,3,4,5,5 /)
22
23 ! Reconstruction of the matrix in standard form
24 As=0.
25 do i=1,nz
26 As(Ti(i),Tj(i))=A(i)
27 end do
28
29 write(*,*) "Matrix in standard representation :"
30 do i=1,5
31 write(*,fmcmplx) As(i,:)
32 end do
33 write(*,*)
34 write(*,*) "Standard determinant : ",fvn_det(5,As)
35 write(*,*)
36 write(*,*) "Right hand side :"
37 write(*,fmcmplx) B
38 ! can use either specific interface, fvn_zl_sparse_det
39 ! either generic one fvn_sparse_det
40 call fvn_zl_sparse_det(n,nz,A,Ti,Tj,det,status)
41 write(*,*)
42 write(*,*) "Sparse Det = ",det
43 ! can use either specific interface fvn_zl_sparse_solve
44 ! either generic one fvn_sparse_solve
45 ! parameter det is optional
46 call fvn_zl_sparse_solve(n,nz,A,Ti,Tj,B,x,status,det)
47 write(*,*)
48 write(*,*) "Sparse Det as solve option= ",det
49 write(*,*)
50 write(*,*) "Solution :"
51 write(*,fmcmplx) x