!>
!> @file tsparse2.f90
!>
!> @brief
!>
!> @copyright
!> Copyright (©) 2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
!> SPC (Swiss Plasma Center)
!>
!> SPClibs is free software: you can redistribute it and/or modify it under
!> the terms of the GNU Lesser General Public License as published by the Free
!> Software Foundation, either version 3 of the License, or (at your option)
!> any later version.
!>
!> SPClibs is distributed in the hope that it will be useful, but WITHOUT ANY
!> WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
!> FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
!>
!> You should have received a copy of the GNU Lesser General Public License
!> along with this program. If not, see .
!>
!> @author
!> (in alphabetical order)
!> @author Trach-Minh Tran
!>
PROGRAM main
!
! Simple 2D Poisson using 5 points FD
!
USE pardiso_bsplines
IMPLICIT NONE
!
TYPE(pardiso_mat) :: amat, bmat
DOUBLE PRECISION, ALLOCATABLE :: arow(:), rhs(:), sol(:)
DOUBLE PRECISION, ALLOCATABLE :: arown(:,:), rhsn(:,:), soln(:,:)
INTEGER :: nx=5, ny=4, n
INTEGER :: i, j, irow, jcol
!
DOUBLE PRECISION :: mem, seconds
!
n = nx*ny
CALL init(n, 1, amat) ! Non-symmetric matrix
CALL init(n, 1, bmat, nlsym=.TRUE.) ! Symmetric matrix
ALLOCATE(arow(n), arown(n,2))
ALLOCATE(rhs(n), rhsn(n,2))
ALLOCATE(sol(n), soln(n,2))
!
! Construct the FD matrix amat, using sparse rows (linked lists)
!
DO j=1,ny
DO i=1,nx
arow = 0.0d0
irow = numb(i,j)
arow(irow) = 4.0d0
IF(i.GT.1) arow(numb(i-1,j)) = -1.0d0
IF(i.LT.nx) arow(numb(i+1,j)) = -1.0d0
IF(j.GT.1) arow(numb(i,j-1)) = -1.0d0
IF(j.LT.ny) arow(numb(i,j+1)) = -1.0d0
rhs(irow) = SUM(arow)
CALL putrow(amat, irow, arow) ! General matrix
CALL putrow(bmat, irow, arow) ! Symmetric matrix
END DO
END DO
!
! Print the matrices
!
WRITE(*,'(/a)') 'Matrix A'
DO i=1,n
CALL getrow(amat, i, arow)
WRITE(*,'(30f4.0)') arow
END DO
PRINT*, 'nnz from get_count', get_count(amat)
!
WRITE(*,'(/a)') 'Matrix B'
DO i=1,n
CALL getrow(bmat, i, arow)
WRITE(*,'(30f4.0)') arow
END DO
PRINT*, 'nnz from get_count', get_count(bmat)
!
! Factor the matrix using Pardiso
!
CALL factor(amat, nlmetis=.TRUE.)
WRITE(*,'(/a,i5)') 'Number of nonzeros in factors of A = ',amat%p%iparm(18)
WRITE(*,'(a,i5)') 'Number of factorization MFLOPS = ',amat%p%iparm(19)
!
CALL factor(bmat, nlmetis=.TRUE.)
WRITE(*,'(/a,i5)') 'Number of nonzeros in factors of B = ',bmat%p%iparm(18)
WRITE(*,'(a,i5)') 'Number of factorization MFLOPS = ',bmat%p%iparm(19)
!
WRITE(*,'(/a/(10f8.4))') 'rhs', rhs
!
! Backsolve Ax = b, using Pardiso
!
sol = rhs
CALL bsolve(amat, sol, debug=.FALSE.)
WRITE(*,'(/a/(10f8.4))') 'sol (non-sym)', sol
WRITE(*,'(a,1pe12.3)') 'Error', MAXVAL(ABS(sol-1.0d0))
!
! Backsolve Bx = b, using Pardiso
!
sol = rhs
CALL bsolve(bmat, sol, debug=.FALSE.)
WRITE(*,'(/a/(10f8.4))') 'sol (sym)', sol
WRITE(*,'(a,1pe12.3)') 'Error', MAXVAL(ABS(sol-1.0d0))
!
arow = vmx(amat, sol)
WRITE(*,'(/a/(10f8.4))') 'A*x (non-sym)', arow
WRITE(*,'(a,1pe12.3)') 'Error', MAXVAL(ABS(arow-rhs))
!
arow = vmx(bmat, sol)
WRITE(*,'(/a/(10f8.4))') 'B*x (sym)', arow
WRITE(*,'(a,1pe12.3)') 'Error', MAXVAL(ABS(arow-rhs))
!
! Multiple RHS
!
rhsn(:,1) = -rhs(:)
rhsn(:,2) = 2.d0*rhs(:)
CALL bsolve(amat, rhsn, soln)
WRITE(*,'(/a/(10f8.4))') 'soln (non-sym)', soln
WRITE(*,'(a,2(1pe12.3))') 'Error', MAXVAL(ABS(soln(:,1)+1.0d0)), &
& MAXVAL(ABS(soln(:,2)-2.0d0))
!
CALL bsolve(bmat, rhsn, soln)
WRITE(*,'(/a/(10f8.4))') 'soln (sym)', soln
WRITE(*,'(a,2(1pe12.3))') 'Error', MAXVAL(ABS(soln(:,1)+1.0d0)), &
& MAXVAL(ABS(soln(:,2)-2.0d0))
!
arown = vmx(amat, soln)
WRITE(*,'(/a/(10f8.4))') 'A*x (non-sym)', arown
WRITE(*,'(a,1pe12.3)') 'Error', MAXVAL(ABS(arown-rhsn))
!
arown = vmx(bmat, soln)
WRITE(*,'(/a/(10f8.4))') 'A*x (sym)', arown
WRITE(*,'(a,1pe12.3)') 'Error', MAXVAL(ABS(arown-rhsn))
!
! Clean up
!
DEALLOCATE(arow,arown)
DEALLOCATE(rhs,rhsn)
DEALLOCATE(sol,soln)
CALL destroy(amat)
CALL destroy(bmat)
CONTAINS
INTEGER FUNCTION numb(i,j)
INTEGER, INTENT(in) :: i, j
numb = (j-1)*nx + i
END FUNCTION numb
!
END PROGRAM main