Hi Thomas,
----- Mensaje original -----
> De: "Thomas Koenig"
> Para: "Jorge D'Elia" , "Gfortran List" <[email protected]>
> CC: "Jorge D'Elia"
> Enviado: MiƩrcoles, 29 de Septiembre 2021 3:02:46
> Asunto: Re: DGBSV: incorrect numerical results with -L/usr/lib64/atlas ?
>
> Hi Jorge,
>
>> I do not know if this forum is the most appropriate, but as it based
>> using gfortran I will try to start here.
>>
>> I usually build the ATLAS library in some beta version without any
>> numerical problem that I remember. In a circumstantial way, I have to
>> use the system ATLAS library and, today, I am getting some incorrect
>> numerical results with the DGBSV lapack fortran subroutine, which is
>> described below with a simple test.
>>
>> Perhaps, I am not using the correct sintaxis in the interface, maybe
>> in the compiler flags or the link ones? Please, any ideas?
>> Thanks in advance.
>
> I tried your code against the reference LAPACK and got the result below,
> which also has info=1 at the end. There is no argument mismatch
> (at least) in the called routine, I checked that by including the
> refblas routine into the source.
Ok. Thanks for those checks.
> So, I don't know what's wrong. Possibly something with the numerics,
> or a wrong size of an argument? It would be possible to compile the
> reference LAPACK and BLAS with debugging and check with a debugger
> where the info flag is set.
>
> If I may guess, it's probably an error in one of the array sizes -
Good catch! (see below).
> LAPACK is notorious that way. I wish they would use modern
> Fortran's array passing mechanism.
I agree. That update would be very welcome looking to the future.
> Best regards
>
> Thomas
Well. After a couple of coffees, it turns out that it
was a false alarm because the end user wrongly used
the lapack' subroutines.
As often happens it was an oversight: in the test I forgot
to insert a call to some routine that converts the usual
representation of an array to the BLAS-General-Band Storage
format. Below I copy the corrected test and everything
returned to normal.
Sorry for the noise. Thus, atlas and gfortran work
very well, as long as they are used correctly ...
Many thanks for your time in addressing this issue.
Best regards.
Jorge.
!begin (fixed) test
! BLAS-general-band storage mode:
! the storage mode packs the matrix elements by columns into
! a two-dimensional array, such that each diagonal of the
! matrix appears as a row in the packed array.
module m_interfase
implicit none
private
public :: idp, iin, dgbsv, conversor_agb
integer, parameter :: idp = kind (1.0d0)
integer, parameter :: iin = kind (1)
!
interface
subroutine dgbsv (n, kl, ku, nrhs, ab, ldab, ipiv, b, ldb, info)
integer info, kl, ku, ldab, ldb, n, nrhs
integer ipiv (*)
double precision ab (ldab,*), b (ldb,*)
external dgbtrf, dgbtrs, xerbla
intrinsic max
end subroutine dgbsv
end interface
!
contains
!
! ................................................................
! A conversor from the general band matrix AAA (mm,nn) to
! the BLAS-general-band storage mode AGB (lda,nn) for dgbsv,
! where AGB has klo extra rows (i.e. lda = (ku + 1 + klo) + klo)
! needed for the dgbsv solution. Ref.
! https://www.ibm.com/docs/en/essl/
! /6.2?topic=representation-blas-general-band-storage-mode
! ................................................................
subroutine conversor_agb (mm,nn,lda,kup,klo,aaa,agb)
integer (iin), intent (in) :: mm, nn, lda, kup, klo
real (idp), intent (in) :: aaa (mm,nn)
real (idp), intent (out) :: agb (lda,nn)
integer (iin) :: i, j, k, p
agb = 0.0_idp
do j = 1, nn
k = kup + 1 - j
do i = max (1,j-kup), min (mm,j+klo)
p = klo + (k + i)
agb (p,j) = aaa (i,j)
end do
end do
end subroutine conversor_agb
!
end module m_interfase
!
program extrouble
use m_interfase, only: iin, idp, dgbsv, conversor_agb
implicit none
!
real (idp), parameter :: cero = 0.0_idp
real (idp), parameter :: uno = 1.0_idp
real (idp), parameter :: dos = 2.0_idp
real (idp), parameter :: tres = 3.0_idp
real (idp), parameter :: cuat = 4.0_idp
real (idp), parameter :: cinc = 5.0_idp
real (idp), parameter :: seis = 6.0_idp
real (idp), parameter :: siet = 7.0_idp
real (idp), parameter :: ocho = 8.0_idp
real (idp), parameter :: nuev = 9.0_idp
real (idp), dimension (9,9), parameter :: &
ccc = reshape ( [ &
uno, dos, tres, cero, cero, cero, cero, cero, cero, & ! 1
dos, uno, dos, tres, cero, cero, cero, cero, cero, & ! 2
tres, dos, uno, dos, tres, cero, cero, cero, cero, & ! 3
cuat, tres, dos, uno, dos, tres, cero, cero, cero, & ! 4
cero, cuat, tres, dos, uno, dos, tres, cero, cero, & ! 5
cero, cero, cuat, tres, dos, uno, dos, tres, cero, & ! 6
cero, cero, cero, cuat, tres, dos, uno, dos, tres, & ! 7
cero, cero, cero, cero, cuat, tres, dos, uno, dos, & ! 8
cero, cero, cero, cero, cero, cuat, tres, dos, uno & ! 9
], [9,9])
!
real (idp), dimension (9,3), parameter :: &
vvv = reshape ( [ &
uno, uno, uno, uno, uno, uno, uno, uno, uno, & ! 1
uno, -uno, uno, -uno, uno, -uno, uno, -uno, uno, & ! 2
uno, dos, tres, cuat, cinc, seis, siet, ocho, nuev & ! 3
], [9,3])
!
real (idp), dimension (8,9) :: aaa
real (idp), dimension (9,3) :: bbb
integer (iin), dimension (9) :: ipiv
integer (iin) :: mm, nn, klo, kup, nrhs, lda, ldb, info
integer (iin) :: i
!
nn = size (aaa,2)
mm = nn
klo = 2
kup = 3
nrhs = size (bbb,2)
lda = 2 * klo + kup + 1
ldb = nn
!
call conversor_agb (mm,nn,lda,kup,klo,ccc,aaa)
bbb = vvv
ipiv = 0
!
write (*,*)
write (*,*)" dgbsv (General Band Side) test "
write (*,*)
write (*,*)" system matrix: aaa (lda,n) "
do i = 1, lda
write (*,*) real (aaa (i,:))
end do
write (*,*)
write (*,*)" source: bbb (ldb,nrhs) "
do i = 1, ldb
write (*,*) real (bbb (i,:))
end do
write (*,*)" nn = ", nn
write (*,*)" klo = ", klo
write (*,*)" kup = ", kup
write (*,*)" nrhs = ", nrhs
write (*,*)" lda = ", lda
write (*,*)" ldb = ", ldb
! N KL KU NRHS A LDA IPIV B LDB INFO)
! | | | | | | | | | |
!call dgbsv (9 , 2 , 3 , 3 , aaa, 8 , ipiv, bbb, 9, info)
call dgbsv (nn, klo, kup, nrhs, aaa, lda, ipiv, bbb, ldb, info)
!
write (*,*)
write (*,*)" output aaa: "
do i = 1, lda
write (*,*) real (aaa (i,:))
end do
write (*,*)
write (*,*)" output bbb: "
do i = 1, ldb
write (*,*) real (bbb (i,:))
end do
write (*,*)
write (*,*)" output ipiv: ", ipiv
write (*,*)
write (*,*)" info = ", info
end program extrouble
!end fixed test