!/*****************************************************************************/1! *2! * Elmer, A Finite Element Software for Multiphysical Problems3! *4! * Copyright 1st April 1995 - , CSC - IT Center for Science Ltd., Finland5! *6! * This library is free software; you can redistribute it and/or7! * modify it under the terms of the GNU Lesser General Public8! * License as published by the Free Software Foundation; either9! * version 2.1 of the License, or (at your option) any later version.10! *11! * This library is distributed in the hope that it will be useful,12! * but WITHOUT ANY WARRANTY; without even the implied warranty of13! * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU14! * Lesser General Public License for more details.15! *16! * You should have received a copy of the GNU Lesser General Public17! * License along with this library (in file ../LGPL-2.1); if not, write18! * to the Free Software Foundation, Inc., 51 Franklin Street,19! * Fifth Floor, Boston, MA 02110-1301 USA20! *21! *****************************************************************************/22!23!/******************************************************************************24! *25! * Authors: Juha Ruokolainen26! * Email: [email protected]27! * Web: http://www.csc.fi/elmer28! * Address: CSC - IT Center for Science Ltd.29! * Keilaranta 1430! * 02101 Espoo, Finland31! *32! * Original Date: 01 Oct 199833! *34! *****************************************************************************/3536#include "huti_fdefs.h"3738!> \ingroup ElmerLib39!> \{4041!-------------------------------------------------------------------------------42!> Module defining utility routines & matrix storage for band matrix format.43!> This module is currently of no or, only little use as the default44!> matrix storage format is CRS.45!-------------------------------------------------------------------------------4647MODULE BandMatrix4849USE GeneralUtils5051IMPLICIT NONE5253CONTAINS5455#define BAND_INDEX(i,j) (((j)-1)*(3*A % Subband+1) + (i)-(j)+2*A % Subband+1)56#define SBAND_INDEX(i,j) (((j)-1)*(A % Subband+1) + (i)-(j)+1)5758!------------------------------------------------------------------------------59!> Zero a Band format matrix60!------------------------------------------------------------------------------61SUBROUTINE Band_ZeroMatrix(A)62!------------------------------------------------------------------------------63TYPE(Matrix_t) :: A !< Structure holding matrix6465A % Values = 0.0D066IF ( ASSOCIATED( A % MassValues ) ) A % MassValues = 0.0d067IF ( ASSOCIATED( A % DampValues ) ) A % DampValues = 0.0d068END SUBROUTINE Band_ZeroMatrix69!------------------------------------------------------------------------------707172!------------------------------------------------------------------------------73!> Zero given row from a Band format matrix74!------------------------------------------------------------------------------75SUBROUTINE Band_ZeroRow( A,n )76!------------------------------------------------------------------------------77TYPE(Matrix_t) :: A !< Structure holding matrix78INTEGER :: n !< Row number to be zerod79!------------------------------------------------------------------------------8081INTEGER :: j,k8283IF ( A % Format == MATRIX_BAND ) THEN84DO j=MAX(1,n-A % Subband), MIN(A % NumberOfRows, n+A % Subband)85A % Values(BAND_INDEX(n,j)) = 0.0d086END DO87ELSE88DO j=MAX(1,n-A % Subband),n89A % Values(SBAND_INDEX(n,j)) = 0.0d090END DO91END IF92END SUBROUTINE Band_ZeroRow93!------------------------------------------------------------------------------9495!------------------------------------------------------------------------------96!> Add a given element to the band matrix.97!------------------------------------------------------------------------------98SUBROUTINE Band_AddToMatrixElement( A,i,j,value )99!------------------------------------------------------------------------------100TYPE(Matrix_t) :: A !< Structure holding matrix101INTEGER :: i !< row number of the matrix element102INTEGER :: j !< column number of the matrix element103REAL(KIND=dp) :: value !< Value to be added104!------------------------------------------------------------------------------105INTEGER :: k106!------------------------------------------------------------------------------107IF ( A % Format == MATRIX_BAND ) THEN108k = BAND_INDEX(i,j)109A % Values(k) = A % Values(k) + Value110ELSE111IF ( j <= i ) THEN112k = SBAND_INDEX(i,j)113A % Values(k) = A % Values(k) + Value114END IF115END IF116END SUBROUTINE Band_AddToMatrixElement117!------------------------------------------------------------------------------118119120!------------------------------------------------------------------------------121!> Set a given element in the band matrix.122!------------------------------------------------------------------------------123SUBROUTINE Band_SetMatrixElement( A,i,j,value )124!------------------------------------------------------------------------------125TYPE(Matrix_t) :: A !< Structure holding matrix126INTEGER :: i !< row number of the matrix element127INTEGER :: j !< column number of the matrix element128REAL(KIND=dp) :: value !< Value to be set129!------------------------------------------------------------------------------130131IF ( A % Format == MATRIX_BAND ) THEN132A % Values(BAND_INDEX(i,j)) = Value133ELSE134IF ( j <= i ) A % Values(SBAND_INDEX(i,j)) = Value135END IF136END SUBROUTINE Band_SetMatrixElement137!------------------------------------------------------------------------------138139!------------------------------------------------------------------------------140!> Get a given matrix element of a band matrix format.141!------------------------------------------------------------------------------142FUNCTION Band_GetMatrixElement( A,i,j ) RESULT ( value )143!------------------------------------------------------------------------------144TYPE(Matrix_t) :: A !< Structure holding matrix145INTEGER :: i !< row number of the matrix element146INTEGER :: j !< column number of the matrix element147REAL(KIND=dp) :: value !< Value to be obtained148!------------------------------------------------------------------------------149IF ( A % Format == MATRIX_BAND ) THEN150Value = A % Values(BAND_INDEX(i,j))151ELSE152IF ( j <= i ) Value = A % Values(SBAND_INDEX(i,j))153END IF154END FUNCTION Band_GetMatrixElement155!------------------------------------------------------------------------------156157158!------------------------------------------------------------------------------159!> Add a set of values (.i.e. element stiffness matrix) to a Band format matrix.160!------------------------------------------------------------------------------161SUBROUTINE Band_GlueLocalMatrix( A,N,Dofs,Indeces,LocalMatrix )162!------------------------------------------------------------------------------163REAL(KIND=dp) :: LocalMatrix(:,:) !< A (N x Dofs) x ( N x Dofs) matrix holding the values to be164!! added to the Band format matrix165TYPE(Matrix_t) :: A !< Structure holding matrix, values are affected in the process166INTEGER :: N !< Number of nodes in element167INTEGER :: Dofs !< Number of degrees of freedom for one node168INTEGER :: Indeces(:) !< Maps element node numbers to global (or partition) node numbers169!! (to matrix rows and columns, if Dofs = 1)170!------------------------------------------------------------------------------171! Local variables172!------------------------------------------------------------------------------173INTEGER :: i,j,k,l,c,ind,Row,Col174REAL(KIND=dp), POINTER :: Values(:)175!------------------------------------------------------------------------------176177Values => A % Values178179IF ( A % Format == MATRIX_BAND ) THEN180DO i=1,N181DO k=0,Dofs-1182Row = Dofs * Indeces(i) - k183DO j=1,N184DO l=0,Dofs-1185Col = Dofs * Indeces(j) - l186ind = BAND_INDEX(Row,Col)187Values(ind) = &188Values(ind) + LocalMatrix(Dofs*i-k,Dofs*j-l)189END DO190END DO191END DO192END DO193ELSE194DO i=1,N195DO k=0,Dofs-1196Row = Dofs * Indeces(i) - k197DO j=1,N198DO l=0,Dofs-1199Col = Dofs * Indeces(j) - l200IF ( Col <= Row ) THEN201ind = SBAND_INDEX(Row,Col)202Values(ind) = &203Values(ind) + LocalMatrix(Dofs*i-k,Dofs*j-l)204END IF205END DO206END DO207END DO208END DO209END IF210211END SUBROUTINE Band_GlueLocalMatrix212!------------------------------------------------------------------------------213214215!------------------------------------------------------------------------------216!> Set value of unknown x_n to given value for symmetric band matrix. This is217!> done by replacing the equation of the unknown by x_n = Value (i.e.218!> zeroing the row of the unknown in the matrix, and setting diagonal to219!> identity). Also the respective column is set to zero (except for the220!> diagonal) to preserve symmetry, while also substituting the rhs by221!> by rhs(i) = rhs(i) - A(i,n) * Value.222!------------------------------------------------------------------------------223SUBROUTINE SBand_SetDirichlet( A, b, n, Value )224!------------------------------------------------------------------------------225TYPE(Matrix_t) :: A !< Structure holding matrix, values are affected in the process226REAL(KIND=dp) :: b(:) !< RHS vector227REAL(KIND=dp), INTENT(IN) :: Value !< Value for the unknown228INTEGER, INTENT(IN) :: n !< Ordered number of the unknown (i.e. matrix row and column number)229!------------------------------------------------------------------------------230231INTEGER :: j232!------------------------------------------------------------------------------233234DO j=MAX(1,n-A % Subband),n-1235b(j) = b(j) - Value * A % Values(SBAND_INDEX(n,j))236A % Values(SBAND_INDEX(n,j)) = 0.0d0237END DO238239DO j=n+1,MIN(n+A % Subband, A % NumberOfRows)240b(j) = b(j) - Value * A % Values(SBAND_INDEX(j,n))241A % Values(SBAND_INDEX(j,n)) = 0.0d0242END DO243244b(n) = Value245A % Values(SBAND_INDEX(n,n)) = 1.0d0246!------------------------------------------------------------------------------247END SUBROUTINE SBand_SetDirichlet248!------------------------------------------------------------------------------249250251252!------------------------------------------------------------------------------253!> Create the structures required for a Band format matrix.254!------------------------------------------------------------------------------255FUNCTION Band_CreateMatrix( N,Subband,Symmetric,AllocValues ) RESULT(A)256!------------------------------------------------------------------------------257INTEGER :: N !< Number of rows for the matrix258INTEGER :: Subband !< Max(ABS(Col-Diag(Row))) of the matrix259LOGICAL :: Symmetric !< Symmetric or not260LOGICAL :: AllocValues !< Should the values arrays be allocated ?261TYPE(Matrix_t), POINTER :: A !< Pointer to the created Matrix_t structure.262!------------------------------------------------------------------------------263INTEGER :: i,j,k,istat264!------------------------------------------------------------------------------265266A => AllocateMatrix()267268A % Subband = Subband269A % NumberOfRows = N270271IF ( AllocValues ) THEN272IF ( Symmetric ) THEN273ALLOCATE( A % Values((A % Subband+1)*N), STAT=istat )274ELSE275ALLOCATE( A % Values((3*A % Subband+1)*N), STAT=istat )276END IF277END IF278279IF ( istat /= 0 ) THEN280CALL Fatal( 'Band_CreateMatrix', 'Memory allocation error.' )281END IF282283NULLIFY( A % ILUValues )284END FUNCTION Band_CreateMatrix285!------------------------------------------------------------------------------286287288!------------------------------------------------------------------------------289!> Matrix vector product (v = Au) for a matrix given in Band format.290!------------------------------------------------------------------------------291SUBROUTINE Band_MatrixVectorMultiply( A,u,v )292!------------------------------------------------------------------------------293REAL(KIND=dp), DIMENSION(*) :: u !< vector to be multiplied294REAL(KIND=dp), DIMENSION(*) :: v !< result vector295TYPE(Matrix_t) :: A !< Structure holding the matrix296!------------------------------------------------------------------------------297REAL(KIND=dp), POINTER :: Values(:)298299INTEGER :: i,j,k,n300REAL(KIND=dp) :: s301!------------------------------------------------------------------------------302303Values => A % Values304n = A % NumberOfRows305306IF ( A % Format == MATRIX_BAND ) THEN307DO i=1,n308s = 0.0d0309DO j=MAX(1,i-A % Subband), MIN(n,i+A % Subband)310s = s + u(j) * Values(BAND_INDEX(i,j))311END DO312v(i) = s313END DO314ELSE315DO i=1,n316s = 0.0d0317DO j=MAX(1,i-A % Subband),i318s = s + u(j) * Values(SBAND_INDEX(i,j))319END DO320321DO j=i+1,MIN(i+A % Subband, A % NumberOfRows)322s = s + u(j) * Values(SBAND_INDEX(j,i))323END DO324v(i) = s325END DO326END IF327328END SUBROUTINE Band_MatrixVectorMultiply329!------------------------------------------------------------------------------330331332!------------------------------------------------------------------------------333!> Matrix vector product (v = Au) for a matrix given in Band format. The334!> matrix is accessed from a global variable GlobalMatrix.335!------------------------------------------------------------------------------336SUBROUTINE Band_MatrixVectorProd( u,v,ipar )337!------------------------------------------------------------------------------338REAL(KIND=dp), DIMENSION(*) :: u !< Vector to be multiplied339REAL(KIND=dp), DIMENSION(*) :: v !< Result vector of the multiplication340INTEGER, DIMENSION(*) :: ipar !< structure holding info from (HUTIter-iterative solver package)341!------------------------------------------------------------------------------342REAL(KIND=dp), POINTER :: Values(:)343344TYPE(Matrix_t), POINTER :: A345INTEGER :: i,j,k,n346REAL(KIND=dp) :: s347!------------------------------------------------------------------------------348A => GlobalMatrix349350Values => A % Values351n = A % NumberOfRows352353IF ( A % Format == MATRIX_BAND ) THEN354IF ( HUTI_EXTOP_MATTYPE == HUTI_MAT_NOTTRPSED ) THEN355DO i=1,n356s = 0.0d0357DO j=MAX(1,i-A % Subband), MIN(n,i+A % Subband)358s = s + u(j) * Values(BAND_INDEX(i,j))359END DO360v(i) = s361END DO362ELSE363v(1:n) = 0.0d0364DO i=1,n365s = u(i)366DO j=MAX(1,i-A % Subband), MIN(n,i+A % Subband)367v(j) = v(j) + s * Values(BAND_INDEX(i,j))368END DO369END DO370END IF371ELSE372DO i=1,n373s = 0.0d0374DO j=MAX(1,i-A % Subband),i375s = s + u(j) * Values(SBAND_INDEX(i,j))376END DO377378DO j=i+1,MIN(i+A % Subband, A % NumberOfRows)379s = s + u(j) * Values(SBAND_INDEX(j,i))380END DO381v(i) = s382END DO383END IF384385END SUBROUTINE Band_MatrixVectorProd386!------------------------------------------------------------------------------387388389390!------------------------------------------------------------------------------391!> Diagonal preconditioning of a Band format matrix.392!------------------------------------------------------------------------------393SUBROUTINE Band_DiagPrecondition( u,v,ipar )394!------------------------------------------------------------------------------395REAL(KIND=dp), DIMENSION(*) :: u !< Vector to be multiplied396REAL(KIND=dp), DIMENSION(*) :: v !< Result vector of the multiplication397INTEGER, DIMENSION(*) :: ipar !< structure holding info from (HUTIter-iterative solver package)398!------------------------------------------------------------------------------399INTEGER :: i,j,k,n400TYPE(Matrix_t), POINTER :: A401402REAL(KIND=dp), POINTER :: Values(:)403404A => GlobalMatrix405Values => GlobalMatrix % Values406407n = A % NumberOfRows408409IF ( A % Format == MATRIX_BAND ) THEN410DO i=1,n411k = BAND_INDEX(i,i)412IF ( ABS(Values(k)) > AEPS ) THEN413u(i) = v(i) / Values(k)414ELSE415u(i) = v(i)416END IF417END DO418ELSE419DO i=1,n420k = SBAND_INDEX(i,i)421IF ( ABS(Values(k)) > AEPS ) THEN422u(i) = v(i) / Values(k)423ELSE424u(i) = v(i)425END IF426END DO427END IF428END SUBROUTINE Band_DiagPrecondition429!------------------------------------------------------------------------------430431END MODULE BandMatrix432433!> \} ElmerLib434435436437