Example #1
0
/*-----------------------------------------------------------------
  cvDlsDenseDQJac 
  -----------------------------------------------------------------
  This routine generates a dense difference quotient approximation 
  to the Jacobian of f(t,y). It assumes that a dense SUNMatrix is 
  stored column-wise, and that elements within each column are 
  contiguous. The address of the jth column of J is obtained via
  the accessor function SUNDenseMatrix_Column, and this pointer 
  is associated with an N_Vector using the N_VSetArrayPointer
  function.  Finally, the actual computation of the jth column of 
  the Jacobian is done with a call to N_VLinearSum.
  -----------------------------------------------------------------*/ 
int cvDlsDenseDQJac(realtype t, N_Vector y, N_Vector fy, 
                    SUNMatrix Jac, CVodeMem cv_mem, N_Vector tmp1)
{
  realtype fnorm, minInc, inc, inc_inv, yjsaved, srur;
  realtype *y_data, *ewt_data;
  N_Vector ftemp, jthCol;
  sunindextype j, N;
  int retval = 0;
  CVDlsMem cvdls_mem;

  /* access DlsMem interface structure */
  cvdls_mem = (CVDlsMem) cv_mem->cv_lmem;

  /* access matrix dimension */
  N = SUNDenseMatrix_Rows(Jac);

  /* Rename work vector for readibility */
  ftemp = tmp1;

  /* Create an empty vector for matrix column calculations */
  jthCol = N_VCloneEmpty(tmp1);

  /* Obtain pointers to the data for ewt, y */
  ewt_data = N_VGetArrayPointer(cv_mem->cv_ewt);
  y_data   = N_VGetArrayPointer(y);

  /* Set minimum increment based on uround and norm of f */
  srur = SUNRsqrt(cv_mem->cv_uround);
  fnorm = N_VWrmsNorm(fy, cv_mem->cv_ewt);
  minInc = (fnorm != ZERO) ?
    (MIN_INC_MULT * SUNRabs(cv_mem->cv_h) * cv_mem->cv_uround * N * fnorm) : ONE;

  for (j = 0; j < N; j++) {

    /* Generate the jth col of J(tn,y) */

    N_VSetArrayPointer(SUNDenseMatrix_Column(Jac,j), jthCol);

    yjsaved = y_data[j];
    inc = SUNMAX(srur*SUNRabs(yjsaved), minInc/ewt_data[j]);
    y_data[j] += inc;

    retval = cv_mem->cv_f(t, y, ftemp, cv_mem->cv_user_data);
    cvdls_mem->nfeDQ++;
    if (retval != 0) break;
    
    y_data[j] = yjsaved;

    inc_inv = ONE/inc;
    N_VLinearSum(inc_inv, ftemp, -inc_inv, fy, jthCol);

    /* DENSE_COL(Jac,j) = N_VGetArrayPointer(jthCol);   /\*UNNECESSARY?? *\/ */
  }

  /* Destroy jthCol vector */
  N_VSetArrayPointer(NULL, jthCol);  /* SHOULDN'T BE NEEDED */
  N_VDestroy(jthCol);

  return(retval);
}
/* ----------------------------------------------------------------------
 * Main SUNMatrix Testing Routine
 * --------------------------------------------------------------------*/
int main(int argc, char *argv[])
{
  int          fails=0;                    /* counter for test failures  */
  sunindextype matrows, matcols;           /* matrix dims                */
  int          mattype;                    /* matrix storage type        */
  N_Vector     x, y, z;                    /* test vectors               */
  realtype*    vecdata;                    /* pointers to vector data    */
  SUNMatrix    A, B, C, D, I;              /* test matrices              */
  realtype*    matdata;                    /* pointer to matrix data     */
  sunindextype i, j, k, kstart, kend, N, uband, lband;
  sunindextype *colptrs, *rowindices;
  sunindextype *rowptrs, *colindices;
  int          print_timing, square;

  /* check input and set vector length */
  if (argc < 5){
    printf("ERROR: FOUR (4) Input required: matrix rows, matrix cols, matrix type (0/1), print timing \n");
    return(-1);
  }

  matrows = atol(argv[1]);
  if (matrows < 1) {
    printf("ERROR: number of rows must be a positive integer\n");
    return(-1);
  }

  matcols = atol(argv[2]);
  if (matcols < 1) {
    printf("ERROR: number of cols must be a positive integer\n");
    return(-1);
  }

  k = atol(argv[3]);
  if ((k != 0) && (k != 1)) {
    printf("ERROR: matrix type must be 0 or 1\n");
    return(-1);
  }
  mattype = (k == 0) ? CSC_MAT : CSR_MAT;

  print_timing = atoi(argv[4]);
  SetTiming(print_timing);

  square = (matrows == matcols) ? 1 : 0;
  printf("\nSparse matrix test: size %ld by %ld, type = %i\n\n",
         (long int) matrows, (long int) matcols, mattype);

  /* Initialize vectors and matrices to NULL */
  x = NULL;
  y = NULL;
  z = NULL;
  A = NULL;
  B = NULL;
  C = NULL;
  D = NULL;
  I = NULL;

  /* check creating sparse matrix from dense matrix */
  B = SUNDenseMatrix(5,6);

  matdata = SUNDenseMatrix_Data(B);
  matdata[2]  = RCONST(1.0);    /* [ 0 2 0 0 7 0 ] */
  matdata[5]  = RCONST(2.0);    /* [ 0 0 4 0 8 0 ] */
  matdata[9]  = RCONST(3.0);    /* [ 1 0 0 0 0 0 ] */
  matdata[11] = RCONST(4.0);    /* [ 0 0 5 6 0 0 ] */
  matdata[13] = RCONST(5.0);    /* [ 0 3 0 0 0 9 ] */
  matdata[18] = RCONST(6.0);
  matdata[20] = RCONST(7.0);
  matdata[21] = RCONST(8.0);
  matdata[29] = RCONST(9.0);

  if (mattype == CSR_MAT) {

    /* Check CSR */
    C = SUNSparseMatrix(5, 6, 9, CSR_MAT);
    rowptrs = SUNSparseMatrix_IndexPointers(C);
    colindices = SUNSparseMatrix_IndexValues(C);
    matdata = SUNSparseMatrix_Data(C);
    rowptrs[0] = 0;
    matdata[0] = RCONST(2.0);   colindices[0] = 1;
    matdata[1] = RCONST(7.0);   colindices[1] = 4;
    rowptrs[1] = 2;
    matdata[2] = RCONST(4.0);   colindices[2] = 2;
    matdata[3] = RCONST(8.0);   colindices[3] = 4;
    rowptrs[2] = 4;
    matdata[4] = RCONST(1.0);   colindices[4] = 0;
    rowptrs[3] = 5;
    matdata[5] = RCONST(5.0);   colindices[5] = 2;
    matdata[6] = RCONST(6.0);   colindices[6] = 3;
    rowptrs[4] = 7;
    matdata[7] = RCONST(3.0);   colindices[7] = 1;
    matdata[8] = RCONST(9.0);   colindices[8] = 5;
    rowptrs[5] = 9;

    A = SUNSparseFromDenseMatrix(B, ZERO, CSR_MAT);
    fails += check_matrix(A, C, 1e-15);

    if (fails) {
      printf("FAIL: SUNMatrix SparseFromDense CSR conversion failed\n");
      return(1);
    }

    SUNMatDestroy(A);
    SUNMatDestroy(C);

  } else {

    /* Check CSC */
    D = SUNSparseMatrix(5, 6, 9, CSC_MAT);
    colptrs = SUNSparseMatrix_IndexPointers(D);
    rowindices = SUNSparseMatrix_IndexValues(D);
    matdata = SUNSparseMatrix_Data(D);
    colptrs[0] = 0;
    matdata[0] = RCONST(1.0);   rowindices[0] = 2;
    colptrs[1] = 1;
    matdata[1] = RCONST(2.0);   rowindices[1] = 0;
    matdata[2] = RCONST(3.0);   rowindices[2] = 4;
    colptrs[2] = 3;
    matdata[3] = RCONST(4.0);   rowindices[3] = 1;
    matdata[4] = RCONST(5.0);   rowindices[4] = 3;
    colptrs[3] = 5;
    matdata[5] = RCONST(6.0);   rowindices[5] = 3;
    colptrs[4] = 6;
    matdata[6] = RCONST(7.0);   rowindices[6] = 0;
    matdata[7] = RCONST(8.0);   rowindices[7] = 1;
    colptrs[5] = 8;
    matdata[8] = RCONST(9.0);   rowindices[8] = 4;
    colptrs[6] = 9;

    A = SUNSparseFromDenseMatrix(B, 1e-15, CSC_MAT);
    fails += check_matrix(A, D, 1e-15);

    if (fails) {
      printf("FAIL: SUNMatrix SparseFromDense CSC conversion failed\n");
      return(1);
    }

    SUNMatDestroy(A);
    SUNMatDestroy(D);

  }
  SUNMatDestroy(B);


  /* check creating sparse matrix from banded matrix */
  N = 7;
  uband = 1;
  lband = 2;                                   /* B(i,j) = j + (j-i) */
  B = SUNBandMatrix(N, uband, lband);          /* B = [  0  2  0  0  0  0  0 ] */
  for (j=0; j<N; j++) {                        /*     [ -1  1  3  0  0  0  0 ] */
    matdata = SUNBandMatrix_Column(B, j);      /*     [ -2  0  2  4  0  0  0 ] */
    kstart = (j<uband) ? -j : -uband;          /*     [  0 -1  1  3  5  0  0 ] */
    kend = (j>N-1-lband) ? N-1-j: lband;       /*     [  0  0  0  2  4  6  0 ] */
    for (k=kstart; k<=kend; k++)               /*     [  0  0  0  1  3  5  7 ] */
      matdata[k] = j - k;                      /*     [  0  0  0  0  2  4  6 ] */
  }

  if (mattype == CSR_MAT) {

    /* CSR */
    C = SUNSparseMatrix(7, 7, 21, CSR_MAT);
    rowptrs = SUNSparseMatrix_IndexPointers(C);
    colindices = SUNSparseMatrix_IndexValues(C);
    matdata = SUNSparseMatrix_Data(C);
    rowptrs[ 0] = 0;
    matdata[ 0] = RCONST(2.0);   colindices[ 0] = 1;
    rowptrs[ 1] = 1;
    matdata[ 1] = RCONST(-1.0);  colindices[ 1] = 0;
    matdata[ 2] = RCONST(1.0);   colindices[ 2] = 1;
    matdata[ 3] = RCONST(3.0);   colindices[ 3] = 2;
    rowptrs[ 2] = 4;
    matdata[ 4] = RCONST(-2.0);  colindices[ 4] = 0;
    matdata[ 5] = RCONST(2.0);   colindices[ 5] = 2;
    matdata[ 6] = RCONST(4.0);   colindices[ 6] = 3;
    rowptrs[ 3] = 7;
    matdata[ 7] = RCONST(-1.0);  colindices[ 7] = 1;
    matdata[ 8] = RCONST(1.0);   colindices[ 8] = 2;
    matdata[ 9] = RCONST(3.0);   colindices[ 9] = 3;
    matdata[10] = RCONST(5.0);   colindices[10] = 4;
    rowptrs[ 4] = 11;
    matdata[11] = RCONST(2.0);   colindices[11] = 3;
    matdata[12] = RCONST(4.0);   colindices[12] = 4;
    matdata[13] = RCONST(6.0);   colindices[13] = 5;
    rowptrs[ 5] = 14;
    matdata[14] = RCONST(1.0);   colindices[14] = 3;
    matdata[15] = RCONST(3.0);   colindices[15] = 4;
    matdata[16] = RCONST(5.0);   colindices[16] = 5;
    matdata[17] = RCONST(7.0);   colindices[17] = 6;
    rowptrs[ 6] = 18;
    matdata[18] = RCONST(2.0);   colindices[18] = 4;
    matdata[19] = RCONST(4.0);   colindices[19] = 5;
    matdata[20] = RCONST(6.0);   colindices[20] = 6;
    rowptrs[ 7] = 21;

    A = SUNSparseFromBandMatrix(B, ZERO, CSR_MAT);
    fails += check_matrix(A, C, 1e-15);

    if (fails) {
      printf("FAIL: SUNMatrix SparseFromBand CSR conversion failed\n");
      return(1);
    }

    SUNMatDestroy(A);
    SUNMatDestroy(C);

  } else {

    /* Check CSC */
    D = SUNSparseMatrix(7, 7, 21, CSC_MAT);
    colptrs = SUNSparseMatrix_IndexPointers(D);
    rowindices = SUNSparseMatrix_IndexValues(D);
    matdata = SUNSparseMatrix_Data(D);
    colptrs[ 0] = 0;
    matdata[ 0] = RCONST(-1.0);  rowindices[ 0] = 1;
    matdata[ 1] = RCONST(-2.0);  rowindices[ 1] = 2;
    colptrs[ 1] = 2;
    matdata[ 2] = RCONST(2.0);   rowindices[ 2] = 0;
    matdata[ 3] = RCONST(1.0);   rowindices[ 3] = 1;
    matdata[ 4] = RCONST(-1.0);  rowindices[ 4] = 3;
    colptrs[ 2] = 5;
    matdata[ 5] = RCONST(3.0);   rowindices[ 5] = 1;
    matdata[ 6] = RCONST(2.0);   rowindices[ 6] = 2;
    matdata[ 7] = RCONST(1.0);   rowindices[ 7] = 3;
    colptrs[ 3] = 8;
    matdata[ 8] = RCONST(4.0);   rowindices[ 8] = 2;
    matdata[ 9] = RCONST(3.0);   rowindices[ 9] = 3;
    matdata[10] = RCONST(2.0);   rowindices[10] = 4;
    matdata[11] = RCONST(1.0);   rowindices[11] = 5;
    colptrs[ 4] = 12;
    matdata[12] = RCONST(5.0);   rowindices[12] = 3;
    matdata[13] = RCONST(4.0);   rowindices[13] = 4;
    matdata[14] = RCONST(3.0);   rowindices[14] = 5;
    matdata[15] = RCONST(2.0);   rowindices[15] = 6;
    colptrs[ 5] = 16;
    matdata[16] = RCONST(6.0);   rowindices[16] = 4;
    matdata[17] = RCONST(5.0);   rowindices[17] = 5;
    matdata[18] = RCONST(4.0);   rowindices[18] = 6;
    colptrs[ 6] = 19;
    matdata[19] = RCONST(7.0);   rowindices[19] = 5;
    matdata[20] = RCONST(6.0);   rowindices[20] = 6;
    colptrs[ 7] = 21;

    A = SUNSparseFromBandMatrix(B, 1e-15, CSC_MAT);
    fails += check_matrix(A, D, 1e-15);

    if (fails) {
      printf("FAIL: SUNMatrix SparseFromBand CSC conversion failed\n");
      return(1);
    }

    SUNMatDestroy(A);
    SUNMatDestroy(D);
  }

  SUNMatDestroy(B);


  /* Create/fill I matrix */
  I = NULL;
  if (square) {
    I = SUNSparseMatrix(matrows, matcols, matcols, mattype);
    matdata    = SUNSparseMatrix_Data(I);
    colindices = SUNSparseMatrix_IndexValues(I);
    rowptrs    = SUNSparseMatrix_IndexPointers(I);
    for(i=0; i<matrows; i++) {
      matdata[i] = ONE;
      colindices[i] = i;
      rowptrs[i] = i;
    }
    rowptrs[matrows] = matrows;
  }

  /* Create/fill random dense matrices, create sparse from them */
  C = SUNDenseMatrix(matrows, matcols);
  D = SUNDenseMatrix(matrows, matcols);
  for (k=0; k<3*matrows; k++) {
    i = rand() % matrows;
    j = rand() % matcols;
    matdata = SUNDenseMatrix_Column(D,j);
    matdata[i] = (realtype) rand() / (realtype) RAND_MAX;
  }
  for (k=0; k<matrows; k++) {
    i = rand() % matrows;
    j = rand() % matcols;
    matdata = SUNDenseMatrix_Column(C,j);
    matdata[i] = (realtype) rand() / (realtype) RAND_MAX;
  }
  A = SUNSparseFromDenseMatrix(C, ZERO, mattype);
  B = SUNSparseFromDenseMatrix(D, ZERO, mattype);

  /* Create vectors and fill */
  x = N_VNew_Serial(matcols);
  y = N_VNew_Serial(matrows);
  z = N_VNew_Serial(matrows);
  vecdata = N_VGetArrayPointer(x);
  for(i=0; i<matcols; i++)
    vecdata[i] = (realtype) rand() / (realtype) RAND_MAX;
  if (SUNMatMatvec(C, x, y) != 0) {
    printf("FAIL: SUNMatrix module Dense matvec failure \n \n");
    SUNMatDestroy(A);  SUNMatDestroy(B);
    SUNMatDestroy(C);  SUNMatDestroy(D);
    N_VDestroy(x);  N_VDestroy(y);  N_VDestroy(z);
    if (square)
      SUNMatDestroy(I);
    return(1);
  }
  if (SUNMatMatvec(D, x, z) != 0) {
    printf("FAIL: SUNMatrix module Dense matvec failure \n \n");
    SUNMatDestroy(A);  SUNMatDestroy(B);
    SUNMatDestroy(C);  SUNMatDestroy(D);
    N_VDestroy(x);  N_VDestroy(y);  N_VDestroy(z);
    if (square)
      SUNMatDestroy(I);
    return(1);
  }

  /* SUNMatrix Tests */
  fails += Test_SUNMatGetID(A, SUNMATRIX_SPARSE, 0);
  fails += Test_SUNMatClone(A, 0);
  fails += Test_SUNMatCopy(A, 0);
  fails += Test_SUNMatZero(A, 0);
  fails += Test_SUNMatScaleAdd(A, I, 0);
  fails += Test_SUNMatScaleAdd2(A, B, x, y, z);
  if (square) {
    fails += Test_SUNMatScaleAddI(A, I, 0);
    fails += Test_SUNMatScaleAddI2(A, x, y);
  }
  fails += Test_SUNMatMatvec(A, x, y, 0);
  fails += Test_SUNMatSpace(A, 0);

  /* Print result */
  if (fails) {
    printf("FAIL: SUNMatrix module failed %i tests \n \n", fails);
    printf("\nA =\n");
    SUNSparseMatrix_Print(A,stdout);
    printf("\nB =\n");
    SUNSparseMatrix_Print(B,stdout);
    if (square) {
      printf("\nI =\n");
      SUNSparseMatrix_Print(I,stdout);
    }
    printf("\nx =\n");
    N_VPrint_Serial(x);
    printf("\ny =\n");
    N_VPrint_Serial(y);
    printf("\nz =\n");
    N_VPrint_Serial(z);
  } else {
    printf("SUCCESS: SUNMatrix module passed all tests \n \n");
  }

  /* Free vectors and matrices */
  N_VDestroy(x);
  N_VDestroy(y);
  N_VDestroy(z);
  SUNMatDestroy(A);
  SUNMatDestroy(B);
  SUNMatDestroy(C);
  SUNMatDestroy(D);
  if (square)
    SUNMatDestroy(I);

  return(fails);
}
/* ----------------------------------------------------------------------
 * SUNLinSol_Dense Testing Routine
 * --------------------------------------------------------------------*/
int main(int argc, char *argv[]) 
{
  int             fails = 0;          /* counter for test failures  */
  sunindextype    cols, rows;         /* matrix columns, rows       */
  SUNLinearSolver LS;                 /* solver object              */
  SUNMatrix       A, B, I;            /* test matrices              */
  N_Vector        x, y, b;            /* test vectors               */
  int             print_timing;
  sunindextype    j, k;
  realtype        *colj, *xdata, *colIj;

  /* check input and set matrix dimensions */
  if (argc < 3){
    printf("ERROR: TWO (2) Inputs required: matrix cols, print timing \n");
    return(-1);
  }

  cols = atol(argv[1]); 
  if (cols <= 0) {
    printf("ERROR: number of matrix columns must be a positive integer \n");
    return(-1); 
  }

  rows = cols;

  print_timing = atoi(argv[2]);
  SetTiming(print_timing);

  printf("\nDense linear solver test: size %ld\n\n",
         (long int) cols);

  /* Create matrices and vectors */
  A = SUNDenseMatrix(rows, cols);
  B = SUNDenseMatrix(rows, cols);
  I = SUNDenseMatrix(rows, cols);
  x = N_VNew_Serial(cols);
  y = N_VNew_Serial(cols);
  b = N_VNew_Serial(cols);

  /* Fill A matrix with uniform random data in [0,1/cols] */
  for (j=0; j<cols; j++) {
    colj = SUNDenseMatrix_Column(A, j);
    for (k=0; k<rows; k++)
      colj[k] = (realtype) rand() / (realtype) RAND_MAX / cols;    
  }

  /* Create anti-identity matrix */
  j=cols-1;
  for (k=0; k<rows; k++) {
    colj = SUNDenseMatrix_Column(I,j);
    colj[k] = 1;
    j = j-1;
  }    
  
  /* Add anti-identity to ensure the solver needs to do row-swapping */
  for (k=0; k<rows; k++){
    for(j=0; j<cols; j++){
      colj = SUNDenseMatrix_Column(A,j);
      colIj = SUNDenseMatrix_Column(I,j);
      colj[k]  = colj[k] + colIj[k]; 
   }
  }

  /* Fill x vector with uniform random data in [0,1] */
  xdata = N_VGetArrayPointer(x);
  for (j=0; j<cols; j++) {
    xdata[j] = (realtype) rand() / (realtype) RAND_MAX;
  } 

  /* copy A and x into B and y to print in case of solver failure */
  SUNMatCopy(A, B);
  N_VScale(ONE, x, y);

  /* create right-hand side vector for linear solve */
  fails = SUNMatMatvec(A, x, b);
  if (fails) {
    printf("FAIL: SUNLinSol SUNMatMatvec failure\n");

    /* Free matrices and vectors */
    SUNMatDestroy(A);
    SUNMatDestroy(B);
    SUNMatDestroy(I);
    N_VDestroy(x);
    N_VDestroy(y);
    N_VDestroy(b);

    return(1);
  }

  /* Create dense linear solver */
  LS = SUNLinSol_Dense(x, A);
  
  /* Run Tests */
  fails += Test_SUNLinSolInitialize(LS, 0);
  fails += Test_SUNLinSolSetup(LS, A, 0);
  fails += Test_SUNLinSolSolve(LS, A, x, b, 10*UNIT_ROUNDOFF, 0);
 
  fails += Test_SUNLinSolGetType(LS, SUNLINEARSOLVER_DIRECT, 0);
  fails += Test_SUNLinSolLastFlag(LS, 0);
  fails += Test_SUNLinSolSpace(LS, 0);

  /* Print result */
  if (fails) {
    printf("FAIL: SUNLinSol module failed %i tests \n \n", fails);
    printf("\nA (original) =\n");
    SUNDenseMatrix_Print(B,stdout);
    printf("\nA (factored) =\n");
    SUNDenseMatrix_Print(A,stdout);
    printf("\nx (original) =\n");
    N_VPrint_Serial(y);
    printf("\nx (computed) =\n");
    N_VPrint_Serial(x);
  } else {
    printf("SUCCESS: SUNLinSol module passed all tests \n \n");
  }

  /* Free solver, matrix and vectors */
  SUNLinSolFree(LS);
  SUNMatDestroy(A);
  SUNMatDestroy(B);
  SUNMatDestroy(I);
  N_VDestroy(x);
  N_VDestroy(y);
  N_VDestroy(b);

  return(fails);
}