SUBROUTINE SMATVEC( NCOLS, NROWS, NCOFF, NX, IX, CX, U, V )
      INTEGER, INTENT(IN   ) :: NCOLS       ! length of input vector
      INTEGER, INTENT(IN   ) :: NROWS       ! length of output vector
      INTEGER, INTENT(IN   ) :: NCOFF       ! max number of coefficients
      INTEGER, INTENT(IN   ) :: NX( NROWS ) ! number of entries per row
      INTEGER, INTENT(IN   ) :: IX( NCOFF ) ! columns list
      REAL   , INTENT(IN   ) :: CX( NCOFF ) ! coefficient array
      REAL   , INTENT(IN   ) :: U( NCOLS )  !  input vector
      REAL   , INTENT(  OUT) :: V( NROWS )  ! output vector
    SUBROUTINE SMATVECP( NCOLS, NROWS, NCOFF, NX, IX, CX, U, V )
      INTEGER, INTENT(IN   ) :: NCOLS           ! length of input vector
      INTEGER, INTENT(IN   ) :: NROWS           ! length of output vector
      INTEGER, INTENT(IN   ) :: NCOFF           ! max number of coefficients
      INTEGER, INTENT(IN   ) :: NN( 0:NROWS )   ! cumulative number of entries per row
      INTEGER, INTENT(IN   ) :: IX(   NCOFF )   ! columns list
      REAL   , INTENT(IN   ) :: CX(   NCOFF )   ! coefficient array
      REAL   , INTENT(IN   ) ::  U(   NCOLS )   !  input vector
      REAL   , INTENT(  OUT) ::  V(   NROWS )   ! output vector
SMATVEC() multiplies input vector U  by
    sparse matrix  <NX,IX,CX>  and returns the
    resulting output vector V, as is  done in area-source
    gridding.
    V(R) = ΣK=NX(R-1)-1NX(R) CX(K) U(IX(K))
SMATVECP() is I/O API-3.2 or later only, is 
    OpenMP parallel, using cumulative-count
    NN(0:NROWS) defined below, instead of
    SMATVEC NX:
    NN(0) = 0NOTES:
NN(R) = ΣK=1R NX(K)
INTERFACEs
         in MODULE M3UTILIO, since main-program declaration, 
         single-indexing usage, and I/O for the sparse matrix
         <NX,IX,CX> needs F77/C style "void
         pointer"  arguments.
    SMATVECP() is more efficient).
    See also subroutines
Bilinear interpolation packageand programsGRID2INDX(), PNTS2INDX(), and INDXMULT()fromMODULE MODGCTPBMATVEC and BILIN, DMATVEC, PMATVEC, and UNGRIDB
MTXBLEND, MTXBUILD, MTXCALC, MTXCPLE.
    !!  Multiply ABUF(NC1,NR1) by MATX to get ZBUF(NC2,NR2)
    ...
    INTEGER :: NR,  NC    !!  for matrix
    INTEGER :: NR1, NC1      !!  for input grid
    INTEGER :: NR2, NC2      !!  for input grid
    INTEGER, ALLOCATABLE :: MATX(:)
    INTEGER, ALLOCATABLE :: MCNT(:)
    REAL,    ALLOCATABLE :: ABUF(:,:)
    REAL,    ALLOCATABLE :: ZBUF(:,:)
    ...
    !!  [Get dimensions (NC1,NR1), (NC2,NR2) for input and output grids]
    ...
    IF ( DESC3( MTXFILE ) ) THEN
        NR = NROWS3D
        NC = NCOLS3D
    ...
    IF ( NR .NE. NC2*NR2 )...   !!  consistency-check for dimensions
    ...
    ALLOCATE( MATX( NR+2*NC ),  &
              MCNT( 0:NR ),     &
              ABUF(NC1,NR1),    &
              ZBUF(NC2,NR2), STAT=ISTAT )
    ...
    IF ( .NOT.READ3( MTXFILE, ALLVAR3, 1,0,0, MATX ) ) ...
    ...
    IF ( .NOT.READ3( DATAFILE, 'FOO', 1,0,0, ABUF ) ) ...
    ...
    CALL SMATVEC( NC1*NR1, NR, NCOEF,                   &
                  MATX(1), MATX(NR+1), MATX(NC+NR+1),   &
                  ABUF, ZBUF )
    ...
    !!  or equivalently, for a time-stepped input:
    ...
    MCNT(0) = 0
    DO K = 1, NR
        MCNT(K) = MCNT(K-1) + MATX(K)
    END DO
    ...
    DO T = 1, NSTEPS
        ...
        IF ( .NOT.READ3( ..., JDATE, JTIME, ABUF ) ) ...
        ...
        CALL SMATVECP( NC1*NR1, NR, NCOEF,              &
                       MCNT, MATX(NR+1), MATX(NC+NR+1), &
                       ABUF, ZBUF )
        ...
    END DO 
    ...    
To: Models-3/EDSS I/O API: The Help Pages