1
C====================================================================
3
C Wrapper routine for inverting generic complex matrix g_za.
5
subroutine zmat_inv (g_za, g_zainv)
10
#include "mafdecls.fh"
12
#include "matutils.fh"
16
integer, intent(in) :: g_za !complex matrix to invert
20
integer, intent(in) :: g_zainv !inverse of matrix
24
character(*), parameter :: pname = "zmat_inv: "
28
integer dim1, dim2, dtype
33
C Get dims of GAs and check that they are correct types
35
C Check the matrix (input 1).
37
call ga_check_handle (g_za,
38
$ "first argument of "//pname//"() is not a valid GA")
39
call ga_inquire (g_za, dtype, dim1, dim2)
40
if (dtype .ne. mt_dcpl) call errquit (pname//
41
$ "expecting complex-valued GA as first argument", 0, 0)
43
$ call errquit (pname//"dim1 must equal dim2", 0, 0)
46
C The size of all matricies must be n x n.
52
C Check the inverse (output) matrix.
54
call ga_check_handle (g_zainv,
55
$ "second argument of "//pname//"() is not a valid GA")
56
call ga_inquire (g_zainv, dtype, dim1, dim2)
57
if (dtype .ne. mt_dcpl) call errquit (pname//
58
$ "expecting complex-valued GA as second argument", 0, 0)
60
$ call errquit (pname//"dim1 must equal dim2", 0, 0)
62
$ call errquit (pname//"size of ainv must match size of a")
65
CXXX [KAL]: only serial inverse routine works for now
66
call zmat_inv_serial (n, g_za, g_zainv)
71
C====================================================================
72
subroutine zmat_inv_serial (n, g_za, g_zainv)
77
#include "mafdecls.fh"
79
#include "matutils.fh"
83
integer, intent(in) :: n !size of mats
84
integer, intent(in) :: g_za !input matrix
88
integer, intent(in) :: g_zainv !inverse of matrix
92
character(*), parameter :: pname = "zmat_inv_serial: "
101
integer izident, lzident
103
integer lzainv, izainv
104
integer lpivot, ipivot
110
C Do all work on all processors (wasteful but works).
119
ok=ok.and.ma_push_get(mt_dcpl, n*n, "complex mat A", lza,iza)
120
ok=ok.and.ma_push_get(mt_dcpl, n*n, "complex mat Ainv",
122
ok=ok.and.ma_push_get(mt_dcpl, n*n, "complex ident mat",
124
ok=ok.and.ma_push_get(mt_int, n, "pivot indices", lpivot, ipivot)
126
ok = ok .and. ga_duplicate (g_za, g_zident, "ident")
127
if (.not.ok) call errquit (pname//"alloc failed", 0, 0)
131
C Unpack buffer to GA
133
call pack_ga2buffer_dcpl (g_za, dcpl_mb(iza))
139
call zgetrf (n, n, dcpl_mb(iza), n, int_mb(ipivot), info)
142
$ call errquit (pname//"LU factorization failed", 0, 0)
146
C Make complex identity matrix buffer.
148
call ga_zero (g_zident)
149
call mat_set_ident (g_zident)
150
call pack_ga2buffer_dcpl (g_zident, dcpl_mb(izident))
154
C Compute inverse by solving AX = I (I is the nxn ident mat)
156
C SUBROUTINE ZGETRS( TRANS, N, NRHS, A, LDA, IPIV, B, LDB, INFO )
158
call zgetrs ("N", n, n, dcpl_mb(iza), n, int_mb(ipivot),
159
$ dcpl_mb(izident), n, info)
162
$ call errquit (pname//"Inversion failed", 0, 0)
166
C Pack solution (stored in zident buffer) into output GA.
168
call pack_buffer2ga_dcpl (dcpl_mb(izident), g_zainv)
175
ok = ok .and. ma_chop_stack (lza)
176
ok = ok .and. ga_destroy (g_zident)
177
if (.not.ok) call errquit (pname//"free failed", 0, 0)
182
C====================================================================
183
subroutine zmat_inv_check (g_za, g_zainv)
187
#include "errquit.fh"
188
#include "mafdecls.fh"
190
#include "matutils.fh"
193
integer, intent(in) :: g_za !complex matrix to invert
194
integer, intent(in) :: g_zainv !inverse of matrix
198
character(*), parameter :: pname = "zmat_inv_check: "
199
double complex, parameter :: z1 = (1d0, 0d0)
200
double complex, parameter :: z0 = (0d0, 0d0)
201
double precision, parameter :: thresh = 1d-8
205
integer dim1, dim2, dtype
211
C Get dims of GAs and check that they are correct types
213
C Check the matrix (input 1).
215
call ga_check_handle (g_za,
216
$ "first argument of "//pname//"() is not a valid GA")
217
call ga_inquire (g_za, dtype, dim1, dim2)
218
if (dtype .ne. mt_dcpl) call errquit (pname//
219
$ "expecting complex-valued GA as first argument", 0, 0)
221
$ call errquit (pname//"dim1 must equal dim2", 0, 0)
224
C The size of all matricies must be n x n.
230
C Check the inverse (output) matrix.
232
call ga_check_handle (g_zainv,
233
$ "second argument of "//pname//"() is not a valid GA")
234
call ga_inquire (g_zainv, dtype, dim1, dim2)
235
if (dtype .ne. mt_dcpl) call errquit (pname//
236
$ "expecting complex-valued GA as second argument", 0, 0)
238
$ call errquit (pname//"dim1 must equal dim2", 0, 0)
240
$ call errquit (pname//"size of ainv must match size of a")
246
if (.not. ga_duplicate (g_za, g_zprod, "prod"))
247
$ call errquit (pname//"failed to alloc prod", 0, GA_ERR)
252
C Check that A^-1 A = I
254
call ga_zgemm ("N", "N", n, n, n, z1, g_zainv, g_za, z0, g_zprod)
255
if (.not. mat_is_ident (g_zprod, thresh))
256
$ call errquit (pname//"inversion check failed", 0, 0)
262
if (.not. ga_destroy (g_zprod))
263
$ call errquit (pname//"destroy failed", 0, 0)
268
C====================================================================
269
subroutine zmat_inv_example_driver ()
273
#include "errquit.fh"
274
#include "mafdecls.fh"
279
character(*), parameter :: pname = "zmat_inv_example_driver: "
284
integer g_zmat, g_zmatinv
294
C octave:1> A=[[1,2,0];[0,3,0];[2,-4,2]]
301
C octave:2> inverse(A)
304
C 1.00000 -0.66667 0.00000
305
C 0.00000 0.33333 0.00000
306
C -1.00000 1.33333 0.50000
312
call util_print_centered (luout, "Inversion example one",
320
if (.not. ga_create(mt_dcpl,3,3,"matrix" , 0, 0, g_zmat))
321
$ call errquit ("failed to create mat", 0, 0)
323
if (.not. ga_create(mt_dcpl,3,3,"matrix inv" , 0, 0, g_zmatinv))
324
$ call errquit ("failed to create mat inv", 0, 0)
326
call ga_zero (g_zmat)
328
val = dcmplx (1d0, 0d0)
329
call ga_put (g_zmat, 1, 1, 1, 1, val, 1)
331
val = dcmplx (2d0, 0d0)
332
call ga_put (g_zmat, 1, 1, 2, 2, val, 1)
334
val = dcmplx (3d0, 0d0)
335
call ga_put (g_zmat, 2, 2, 2, 2, val, 1)
337
val = dcmplx (2d0, 0d0)
338
call ga_put (g_zmat, 3, 3, 1, 1, val, 1)
340
val = dcmplx (-4d0, 0d0)
341
call ga_put (g_zmat, 3, 3, 2, 2, val, 1)
343
val = dcmplx (2d0, 0d0)
344
call ga_put (g_zmat, 3, 3, 3, 3, val, 1)
350
call zmat_inv (g_zmat, g_zmatinv)
351
call zmat_inv_check (g_zmat, g_zmatinv)
352
call ga_print (g_zmat)
353
call ga_print (g_zmatinv)
359
C octave:1> A=[[1.2+i,1,i];[0,3,-0.98*i];[2+3.2*i,-4,2.5+8*i]]
362
C 1.20000 + 1.00000i 1.00000 + 0.00000i 0.00000 + 1.00000i
363
C 0.00000 + 0.00000i 3.00000 + 0.00000i -0.00000 - 0.98000i
364
C 2.00000 + 3.20000i -4.00000 + 0.00000i 2.50000 + 8.00000i
366
C octave:2> inverse(A)
369
C 0.867525 - 0.256532i -0.512594 + 0.069857i -0.167565 - 0.011740i
370
C -0.073269 - 0.137812i 0.419917 + 0.105576i 0.046621 + 0.044729i
371
C -0.421875 + 0.224292i 0.323190 - 0.265053i 0.136924 - 0.142717i
377
call util_print_centered (luout, "Inversion example two",
381
call ga_zero (g_zmat)
383
val = dcmplx (1.2d0, 1d0)
384
call ga_put (g_zmat, 1, 1, 1, 1, val, 1)
386
val = dcmplx (1.0d0, 0d0)
387
call ga_put (g_zmat, 1, 1, 2, 2, val, 1)
389
val = dcmplx (0d0, 1d0)
390
call ga_put (g_zmat, 1, 1, 3, 3, val, 1)
392
val = dcmplx (0d0, 0d0)
393
call ga_put (g_zmat, 2, 2, 1, 1, val, 1)
395
val = dcmplx (3d0, 0d0)
396
call ga_put (g_zmat, 2, 2, 2, 2, val, 1)
398
val = dcmplx (0d0, -0.98d0)
399
call ga_put (g_zmat, 2, 2, 3, 3, val, 1)
401
val = dcmplx (2d0, 3.2d0)
402
call ga_put (g_zmat, 3, 3, 1, 1, val, 1)
404
val = dcmplx (-4d0, 0d0)
405
call ga_put (g_zmat, 3, 3, 2, 2, val, 1)
407
val = dcmplx (2.5d0, 8d0)
408
call ga_put (g_zmat, 3, 3, 3, 3, val, 1)
414
call zmat_inv (g_zmat, g_zmatinv)
415
call zmat_inv_check (g_zmat, g_zmatinv)
416
call ga_print (g_zmat)
417
call ga_print (g_zmatinv)
423
if (.not. ga_destroy (g_zmat))
424
$ call errquit (pname//"failed to destroy g_zmat",0,0)
425
if (.not. ga_destroy (g_zmatinv))
426
$ call errquit (pname//"failed to destroy g_zmatinv",0,0)