MODULE prec_m INTEGER,PARAMETER:: wp=SELECTED_REAL_KIND(12) END MODULE prec_m ! ! tridiag. matrix | B1 A2 | ! | A2 B2 A3 | ! | A3 B3 | ! | ... | ! | AN BN | ! ! is stored in a(:,:) as follows: ! ! B1 B2 B3 .... BN ! * A2 A3 .... AN ! MODULE tridiag_m USE prec_m IMPLICIT NONE CONTAINS SUBROUTINE tridiag_cholesky_factor( a, info ) INTEGER, INTENT(OUT) :: info REAL(wp), INTENT(INOUT):: a(:,:) REAL(wp):: tmp INTEGER:: i, n info = -1 n = SIZE(a,2) IF ( a(1,1) < 0.0 ) RETURN a(1,1) = SQRT(a(1,1)) DO i=2,n a(2,i) = a(2,i)/a(1,i-1) tmp = a(1,i) - a(2,i)*a(2,i) IF ( tmp < 0.0 ) RETURN a(1,i) = SQRT( tmp ) END DO info = 0 RETURN END SUBROUTINE tridiag_cholesky_factor SUBROUTINE tridiag_cholesky_solve( a, x, b ) REAL(wp), INTENT(IN) :: a(:,:), b(:) REAL(wp), INTENT(OUT):: x(:) INTEGER:: i, n n = SIZE(a,2) x(1) = b(1)/a(1,1) DO i=2,n x(i) = (b(i)-a(2,i)*x(i-1))/a(1,i) END DO x(n) = x(n)/a(1,n) DO i=n-1,1,-1 x(i) = (x(i)-a(2,i+1)*x(i+1))/a(1,i) END DO END SUBROUTINE tridiag_cholesky_solve SUBROUTINE tridiag_mxv( a, x, ax ) REAL(wp), INTENT(IN) :: a(:,:), x(:) REAL(wp), INTENT(OUT):: ax(:) INTEGER:: i, n n = SIZE(a,2) ax(1) = a(1,1)*x(1) + a(2,1)*x(2) DO i=2,n-1 ax(i) = a(2,i)*x(i-1) + a(1,i)*x(i) + a(2,i+1)*x(i+1) END DO ax(n) = a(2,n)*x(n-1) + a(1,n)*x(n) END SUBROUTINE tridiag_mxv END MODULE tridiag_m ! ! Solves 2D heat equation in a unit square ! ! u_t - c*(u_xx + u_yy) = 0 0