      SUBROUTINE MVMMCD( TRANS, N, M, X, LDX, Y, LDY )
*     ..
*     .. Scalar Arguments ..
      INTEGER            LDY, LDX, M, N, TRANS
*     ..
*     .. Array Arguments ..
      DOUBLE PRECISION   Y( LDY, * ), X( LDX, * )
*     ..
*
*  Purpose
*  =======
*
*  Compute
*
*               Y(:,1:M) = op(A)*X(:,1:M)
*
*  where op(A) is A or A' (the transpose of A). The matrix A is a block
*  tridiagonal matrix resulted from the finite difference discretization       
*  of a 2-D model convection diffusion operator,
*
*           L[u] = - u_xx - u_yy + 2p_1 u_x + 2p_2 u_y - p_3 u.
*
*  The constant parameters p1, p2 and p3 in the convection-diffusion 
*  operator may be changed.  
*
*  The convection-diffusion operator is discretized on a K x K square 
*  grid, and resulted in the matrix A of order N = K^2. 
*
*  Arguments
*  =========
*
*  TRANS   (input) INTEGER
*          If TRANS = 0, compute Y(:,1:M) = A*X(:,1:M) 
*          If TRANS = 1, compute Y(:,1:M) = A'*X(:,1:M) 
*           
*  N       (input) INTEGER
*          The order of the matrix A. N has to be K*K for an integer K.
*
*  M       (input) INTEGERS
*          The number of columns of X to multiply.
*
*  X       (input) DOUBLE PRECISION array, dimension ( LDX, M )
*          X contains the matrix (vectors) X.
*
*  LDX     (input) INTEGER
*          The leading dimension of array X, LDX >= max( 1, N )
*
*  Y       (output) DOUBLE PRECISION array, dimension (LDY, M )
*          contains the product of the matrix and vectors. 
*
*  LDY     (input) INTEGER
*          The leading dimension of array Y, LDY >= max( 1, N )
*
*  ===================================================================
*
*     .. Parameters ..
      DOUBLE PRECISION   ONE, FOUR
      PARAMETER          ( ONE = 1.0D+0, FOUR = 4.0D+0 )
      DOUBLE PRECISION   P1, P2, P3
      PARAMETER          ( P1 = 1.0D+0, P2 = 1.0D+0, P3 = 1.0D+0 )
*     ..
*     .. Local Scalars ..
      INTEGER            I, II, K, NS
      DOUBLE PRECISION   BETA, GAMMA, HSTEP, SIGMA
*     ..
*     .. Intrinsic Functions ..
      INTRINSIC          REAL, SQRT
*     ..
*     .. Executable Statements ..
*
      NS = SQRT( REAL( N ) )
      HSTEP = ONE / ( REAL( NS )+ONE )
      SIGMA = P3*HSTEP*HSTEP
      GAMMA = P2*HSTEP
      BETA = P1*HSTEP
*
      IF ( TRANS.EQ.0 ) THEN 
         DO 70 K = 1, M
*
*           Compute the vector Y(1:N,K) = A*X(1:N,K)
*
            DO 60 I = 1, NS
*
*              diagonal elements
*
               DO 10 II = ( I-1 )*NS + 1, I*NS
                  Y( II, K ) = ( FOUR-SIGMA )*X( II, K )
   10          CONTINUE
*
*              sub diagonal elements
*
               DO 20 II = ( I-1 )*NS + 1 + 1, I*NS
                  Y( II, K ) = Y( II, K ) + 
     $                                  ( -GAMMA-ONE )*X( II-1, K )
   20          CONTINUE
*
*              super diagonal elements 
*
               DO 30 II = ( I-1 )*NS + 1, I*NS - 1
                  Y( II, K ) = Y( II, K ) + 
     $                                  ( GAMMA-ONE )*X( II+1, K ) 
   30          CONTINUE
*
*              (NS+1)th sub diagonal 
*
               IF( I.GT.1 ) THEN
                  DO 40 II = ( I-1 )*NS + 1, I*NS
                     Y( II, K ) = Y( II, K ) + 
     $                                  ( BETA-ONE )*X( II-NS, K )
   40             CONTINUE
               END IF
*
*              (NS+1)th super diagonal 
*
               IF( I.LT.NS ) THEN
                  DO 50 II = ( I-1 )*NS + 1, I*NS
                     Y( II, K ) = Y( II, K ) + 
     $                                  ( -BETA-ONE )*X( II+NS, K )
   50             CONTINUE
               END IF
*
   60       CONTINUE
*
   70    CONTINUE
*
      ELSE IF ( TRANS.EQ.1 ) THEN 
*
         DO 140 K = 1, M
*
*           Compute the vector Y(1:N,K) = trans(A)*X(1:N,K)
*
            DO 130 I = 1, NS
*
               DO 80 II = ( I-1 )*NS + 1, I*NS
                  Y( II, K ) = ( FOUR-SIGMA )*X( II, K )
   80          CONTINUE
*
               DO 90 II = ( I-1 )*NS + 1, I*NS - 1
                  Y( II, K ) = Y( II, K ) + 
     $                                  ( -GAMMA-ONE )*X( II+1, K )       
   90          CONTINUE
*
               DO 100 II = ( I-1 )*NS + 1 + 1, I*NS
                  Y( II, K ) = Y( II, K ) + 
     $                                  ( GAMMA-ONE )*X( II-1, K )
  100          CONTINUE
*
*              (NS+1)th sub diagonal
*
               IF( I.GT.1 ) THEN
                  DO 110 II = ( I-1 )*NS + 1, I*NS
                     Y( II, K ) = Y( II, K ) + 
     $                                  (-BETA-ONE )*X( II-NS, K )
  110             CONTINUE
               END IF
*
*              (NS+1)th super diagonal
*
               IF( I.LT.NS ) THEN
                  DO 120 II = ( I-1 )*NS + 1, I*NS
                     Y( II, K ) = Y( II, K ) + 
     $                                  ( BETA-ONE )*X( II+NS, K )
  120             CONTINUE
               END IF
*
  130       CONTINUE
*
  140    CONTINUE
*
      END IF 
*
      RETURN
*
*     End of MVMMCD
      END
