Example #1
0
/*---------------------------------------------------------------
  CVodeSetLinearSolver specifies the linear solver
  ---------------------------------------------------------------*/
int CVodeSetLinearSolver(void *cvode_mem, SUNLinearSolver LS,
                         SUNMatrix A)
{
  CVodeMem cv_mem;
  CVLsMem  cvls_mem;
  int      retval, LSType;

  /* Return immediately if either cvode_mem or LS inputs are NULL */
  if (cvode_mem == NULL) {
    cvProcessError(NULL, CVLS_MEM_NULL, "CVLS",
                   "CVodeSetLinearSolver", MSG_LS_CVMEM_NULL);
    return(CVLS_MEM_NULL);
  }
  if (LS == NULL) {
    cvProcessError(NULL, CVLS_ILL_INPUT, "CVLS",
                   "CVodeSetLinearSolver",
                    "LS must be non-NULL");
    return(CVLS_ILL_INPUT);
  }
  cv_mem = (CVodeMem) cvode_mem;

  /* Test if solver is compatible with LS interface */
  if ( (LS->ops->gettype == NULL) ||
       (LS->ops->initialize == NULL) ||
       (LS->ops->setup == NULL) ||
       (LS->ops->solve == NULL) ) {
    cvProcessError(cv_mem, CVLS_ILL_INPUT, "CVLS",
                   "CVodeSetLinearSolver",
                   "LS object is missing a required operation");
    return(CVLS_ILL_INPUT);
  }

  /* Test if vector is compatible with LS interface */
  if ( (cv_mem->cv_tempv->ops->nvconst == NULL) ||
       (cv_mem->cv_tempv->ops->nvdotprod == NULL) ) {
    cvProcessError(cv_mem, CVLS_ILL_INPUT, "CVLS",
                    "CVodeSetLinearSolver", MSG_LS_BAD_NVECTOR);
    return(CVLS_ILL_INPUT);
  }

  /* Retrieve the LS type */
  LSType = SUNLinSolGetType(LS);

  /* Check for compatible LS type, matrix and "atimes" support */
  if ((LSType == SUNLINEARSOLVER_ITERATIVE) && (LS->ops->setatimes == NULL)) {
    cvProcessError(cv_mem, CVLS_ILL_INPUT, "CVLS", "CVodeSetLinearSolver",
                    "Incompatible inputs: iterative LS must support ATimes routine");
    return(CVLS_ILL_INPUT);
  }
  if ((LSType == SUNLINEARSOLVER_DIRECT) && (A == NULL)) {
    cvProcessError(cv_mem, CVLS_ILL_INPUT, "CVLS", "CVodeSetLinearSolver",
                    "Incompatible inputs: direct LS requires non-NULL matrix");
    return(CVLS_ILL_INPUT);
  }
  if ((LSType == SUNLINEARSOLVER_MATRIX_ITERATIVE) && (A == NULL)) {
    cvProcessError(cv_mem, CVLS_ILL_INPUT, "CVLS", "CVodeSetLinearSolver",
                    "Incompatible inputs: matrix-iterative LS requires non-NULL matrix");
    return(CVLS_ILL_INPUT);
  }

  /* free any existing system solver attached to CVode */
  if (cv_mem->cv_lfree)  cv_mem->cv_lfree(cv_mem);

  /* Set four main system linear solver function fields in cv_mem */
  cv_mem->cv_linit  = cvLsInitialize;
  cv_mem->cv_lsetup = cvLsSetup;
  cv_mem->cv_lsolve = cvLsSolve;
  cv_mem->cv_lfree  = cvLsFree;

  /* Allocate memory for CVLsMemRec */
  cvls_mem = NULL;
  cvls_mem = (CVLsMem) malloc(sizeof(struct CVLsMemRec));
  if (cvls_mem == NULL) {
    cvProcessError(cv_mem, CVLS_MEM_FAIL, "CVLS",
                    "CVodeSetLinearSolver", MSG_LS_MEM_FAIL);
    return(CVLS_MEM_FAIL);
  }
  memset(cvls_mem, 0, sizeof(struct CVLsMemRec));

  /* set SUNLinearSolver pointer */
  cvls_mem->LS = LS;

  /* Set defaults for Jacobian-related fields */
  if (A != NULL) {
    cvls_mem->jacDQ  = SUNTRUE;
    cvls_mem->jac    = cvLsDQJac;
    cvls_mem->J_data = cv_mem;
  } else {
    cvls_mem->jacDQ  = SUNFALSE;
    cvls_mem->jac    = NULL;
    cvls_mem->J_data = NULL;
  }
  cvls_mem->jtimesDQ = SUNTRUE;
  cvls_mem->jtsetup  = NULL;
  cvls_mem->jtimes   = cvLsDQJtimes;
  cvls_mem->jt_data  = cv_mem;

  /* Set defaults for preconditioner-related fields */
  cvls_mem->pset   = NULL;
  cvls_mem->psolve = NULL;
  cvls_mem->pfree  = NULL;
  cvls_mem->P_data = cv_mem->cv_user_data;

  /* Initialize counters */
  cvLsInitializeCounters(cvls_mem);

  /* Set default values for the rest of the LS parameters */
  cvls_mem->msbj      = CVLS_MSBJ;
  cvls_mem->jbad      = SUNTRUE;
  cvls_mem->eplifac   = CVLS_EPLIN;
  cvls_mem->last_flag = CVLS_SUCCESS;

  /* If LS supports ATimes, attach CVLs routine */
  if (LS->ops->setatimes) {
    retval = SUNLinSolSetATimes(LS, cv_mem, cvLsATimes);
    if (retval != SUNLS_SUCCESS) {
      cvProcessError(cv_mem, CVLS_SUNLS_FAIL, "CVLS",
                     "CVodeSetLinearSolver",
                     "Error in calling SUNLinSolSetATimes");
      free(cvls_mem); cvls_mem = NULL;
      return(CVLS_SUNLS_FAIL);
    }
  }

  /* If LS supports preconditioning, initialize pset/psol to NULL */
  if (LS->ops->setpreconditioner) {
    retval = SUNLinSolSetPreconditioner(LS, cv_mem, NULL, NULL);
    if (retval != SUNLS_SUCCESS) {
      cvProcessError(cv_mem, CVLS_SUNLS_FAIL, "CVLS",
                     "CVodeSetLinearSolver",
                     "Error in calling SUNLinSolSetPreconditioner");
      free(cvls_mem); cvls_mem = NULL;
      return(CVLS_SUNLS_FAIL);
    }
  }

  /* When using a non-NULL SUNMatrix object, store pointer to A and create saved_J */
  if (A != NULL) {
    cvls_mem->A = A;
    cvls_mem->savedJ = SUNMatClone(A);
    if (cvls_mem->savedJ == NULL) {
      cvProcessError(cv_mem, CVLS_MEM_FAIL, "CVLS",
                     "CVodeSetLinearSolver", MSG_LS_MEM_FAIL);
      free(cvls_mem); cvls_mem = NULL;
      return(CVLS_MEM_FAIL);
    }
  }
  /* Allocate memory for ytemp and x */
  cvls_mem->ytemp = N_VClone(cv_mem->cv_tempv);
  if (cvls_mem->ytemp == NULL) {
    cvProcessError(cv_mem, CVLS_MEM_FAIL, "CVLS",
                    "CVodeSetLinearSolver", MSG_LS_MEM_FAIL);
    SUNMatDestroy(cvls_mem->savedJ);
    free(cvls_mem); cvls_mem = NULL;
    return(CVLS_MEM_FAIL);
  }

  cvls_mem->x = N_VClone(cv_mem->cv_tempv);
  if (cvls_mem->x == NULL) {
    cvProcessError(cv_mem, CVLS_MEM_FAIL, "CVLS",
                    "CVodeSetLinearSolver", MSG_LS_MEM_FAIL);
    SUNMatDestroy(cvls_mem->savedJ);
    N_VDestroy(cvls_mem->ytemp);
    free(cvls_mem); cvls_mem = NULL;
    return(CVLS_MEM_FAIL);
  }

  /* For iterative LS, compute sqrtN from a dot product */
  if ( (LSType == SUNLINEARSOLVER_ITERATIVE) ||
       (LSType == SUNLINEARSOLVER_MATRIX_ITERATIVE) ) {
    N_VConst(ONE, cvls_mem->ytemp);
    cvls_mem->sqrtN = SUNRsqrt( N_VDotProd(cvls_mem->ytemp,
                                           cvls_mem->ytemp) );
  }

  /* Attach linear solver memory to integrator memory */
  cv_mem->cv_lmem = cvls_mem;

  return(CVLS_SUCCESS);
}
/* ----------------------------------------------------------------------
 * Extra ScaleAddI tests for sparse matrices:
 *    A should not contain values on the diagonal, nor should it contain
 *      sufficient storage to add those in
 *    y should already equal A*x
 * --------------------------------------------------------------------*/
int Test_SUNMatScaleAddI2(SUNMatrix A, N_Vector x, N_Vector y)
{
  int       failure;
  SUNMatrix B, C, D;
  N_Vector  w, z;
  realtype  tol=100*UNIT_ROUNDOFF;

  /* create clones for test */
  B = SUNMatClone(A);
  z = N_VClone(x);
  w = N_VClone(x);

  /* test 1: add I to a matrix with insufficient storage */
  failure = SUNMatCopy(A, B);
  if (failure) {
    printf(">>> FAILED test -- SUNMatCopy returned %d \n",
           failure);
    SUNMatDestroy(B);  N_VDestroy(z);  N_VDestroy(w);  return(1);
  }
  failure = SUNMatScaleAddI(NEG_ONE, B);   /* B = I-A */
  if (failure) {
    printf(">>> FAILED test -- SUNMatScaleAddI returned %d \n",
           failure);
    SUNMatDestroy(B);  N_VDestroy(z);  N_VDestroy(w);  return(1);
  }
  failure = SUNMatMatvec(B, x, z);
  if (failure) {
    printf(">>> FAILED test -- SUNMatMatvec returned %d \n",
           failure);
    SUNMatDestroy(B);  N_VDestroy(z);  N_VDestroy(w);  return(1);
  }
  N_VLinearSum(ONE,x,NEG_ONE,y,w);
  failure = check_vector(z, w, tol);
  if (failure) {
    printf(">>> FAILED test -- SUNMatScaleAddI2 check 1 \n");
    printf("\nA =\n");
    SUNSparseMatrix_Print(A,stdout);
    printf("\nB =\n");
    SUNSparseMatrix_Print(B,stdout);
    printf("\nz =\n");
    N_VPrint_Serial(z);
    printf("\nw =\n");
    N_VPrint_Serial(w);
    SUNMatDestroy(B);  N_VDestroy(z);  N_VDestroy(w);  return(1);
  }
  else {
    printf("    PASSED test -- SUNMatScaleAddI2 check 1 \n");
  }

  /* test 2: add I to a matrix with sufficient but misplaced
     storage */
  C = SUNMatClone(A);
  failure = SUNSparseMatrix_Reallocate(C, SM_NNZ_S(A)+SM_ROWS_S(A));
  failure = SUNMatCopy(A, C);
  if (failure) {
    printf(">>> FAILED test -- SUNMatCopy returned %d \n",
           failure);
    SUNMatDestroy(B);  SUNMatDestroy(C);
    N_VDestroy(z);  N_VDestroy(w);  return(1);
  }
  failure = SUNMatScaleAddI(NEG_ONE, C);   /* C = I-A */
  if (failure) {
    printf(">>> FAILED test -- SUNMatScaleAddI returned %d \n",
           failure);
    SUNMatDestroy(B);  SUNMatDestroy(C);
    N_VDestroy(z);  N_VDestroy(w);  return(1);
  }
  failure = SUNMatMatvec(C, x, z);
  if (failure) {
    printf(">>> FAILED test -- SUNMatMatvec returned %d \n",
           failure);
    SUNMatDestroy(B);  SUNMatDestroy(C);
    N_VDestroy(z);  N_VDestroy(w);  return(1);
  }
  N_VLinearSum(ONE,x,NEG_ONE,y,w);
  failure = check_vector(z, w, tol);
  if (failure) {
    printf(">>> FAILED test -- SUNMatScaleAddI2 check 2 \n");
    printf("\nA =\n");
    SUNSparseMatrix_Print(A,stdout);
    printf("\nC =\n");
    SUNSparseMatrix_Print(C,stdout);
    printf("\nz =\n");
    N_VPrint_Serial(z);
    printf("\nw =\n");
    N_VPrint_Serial(w);
    SUNMatDestroy(B);  SUNMatDestroy(C);
    N_VDestroy(z);  N_VDestroy(w);  return(1);
  }
  else {
    printf("    PASSED test -- SUNMatScaleAddI2 check 2 \n");
  }


  /* test 3: add I to a matrix with appropriate structure already in place */
  D = SUNMatClone(C);
  failure = SUNMatCopy(C, D);
  if (failure) {
    printf(">>> FAILED test -- SUNMatCopy returned %d \n",
           failure);
    SUNMatDestroy(B);  SUNMatDestroy(C);  SUNMatDestroy(D);
    N_VDestroy(z);  N_VDestroy(w);  return(1);
  }
  failure = SUNMatScaleAddI(NEG_ONE, D);   /* D = A */
  if (failure) {
    printf(">>> FAILED test -- SUNMatScaleAddI returned %d \n",
           failure);
    SUNMatDestroy(B);  SUNMatDestroy(C);  SUNMatDestroy(D);
    N_VDestroy(z);  N_VDestroy(w);  return(1);
  }
  failure = SUNMatMatvec(D, x, z);
  if (failure) {
    printf(">>> FAILED test -- SUNMatMatvec returned %d \n",
           failure);
    SUNMatDestroy(B);  SUNMatDestroy(C);  SUNMatDestroy(D);
    N_VDestroy(z);  N_VDestroy(w);  return(1);
  }
  failure = check_vector(z, y, tol);
  if (failure) {
    printf(">>> FAILED test -- SUNMatScaleAddI2 check 3 \n");
    printf("\nA =\n");
    SUNSparseMatrix_Print(A,stdout);
    printf("\nD =\n");
    SUNSparseMatrix_Print(D,stdout);
    printf("\nz =\n");
    N_VPrint_Serial(z);
    printf("\ny =\n");
    N_VPrint_Serial(y);
    SUNMatDestroy(B);  SUNMatDestroy(C);  SUNMatDestroy(D);
    N_VDestroy(z);  N_VDestroy(w);  return(1);
  }
  else {
    printf("    PASSED test -- SUNMatScaleAddI2 check 3 \n");
  }

  SUNMatDestroy(B);
  SUNMatDestroy(C);
  SUNMatDestroy(D);
  N_VDestroy(z);
  N_VDestroy(w);
  return(0);
}
Example #3
0
/*---------------------------------------------------------------
 CVDlsSetLinearSolver specifies the direct linear solver.
---------------------------------------------------------------*/
int CVDlsSetLinearSolver(void *cvode_mem, SUNLinearSolver LS,
                         SUNMatrix A)
{
  CVodeMem cv_mem;
  CVDlsMem cvdls_mem;

  /* Return immediately if any input is NULL */
  if (cvode_mem == NULL) {
    cvProcessError(NULL, CVDLS_MEM_NULL, "CVDLS", 
                   "CVDlsSetLinearSolver", MSGD_CVMEM_NULL);
    return(CVDLS_MEM_NULL);
  }
  if ( (LS == NULL)  || (A == NULL) ) {
    cvProcessError(NULL, CVDLS_ILL_INPUT, "CVDLS", 
                   "CVDlsSetLinearSolver",
                    "Both LS and A must be non-NULL");
    return(CVDLS_ILL_INPUT);
  }
  cv_mem = (CVodeMem) cvode_mem;

  /* Test if solver and vector are compatible with DLS */
  if (SUNLinSolGetType(LS) != SUNLINEARSOLVER_DIRECT) {
    cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVDLS", 
                   "CVDlsSetLinearSolver", 
                   "Non-direct LS supplied to CVDls interface");
    return(CVDLS_ILL_INPUT);
  }
  if (cv_mem->cv_tempv->ops->nvgetarraypointer == NULL ||
      cv_mem->cv_tempv->ops->nvsetarraypointer == NULL) {
    cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVDLS", 
                   "CVDlsSetLinearSolver", MSGD_BAD_NVECTOR);
    return(CVDLS_ILL_INPUT);
  }

  /* free any existing system solver attached to CVode */
  if (cv_mem->cv_lfree)  cv_mem->cv_lfree(cv_mem);

  /* Set four main system linear solver function fields in cv_mem */
  cv_mem->cv_linit  = cvDlsInitialize;
  cv_mem->cv_lsetup = cvDlsSetup;
  cv_mem->cv_lsolve = cvDlsSolve;
  cv_mem->cv_lfree  = cvDlsFree;
  
  /* Get memory for CVDlsMemRec */
  cvdls_mem = NULL;
  cvdls_mem = (CVDlsMem) malloc(sizeof(struct CVDlsMemRec));
  if (cvdls_mem == NULL) {
    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVDLS", 
                    "CVDlsSetLinearSolver", MSGD_MEM_FAIL);
    return(CVDLS_MEM_FAIL);
  }

  /* set SUNLinearSolver pointer */
  cvdls_mem->LS = LS;
  
  /* Initialize Jacobian-related data */
  cvdls_mem->jacDQ = SUNTRUE;
  cvdls_mem->jac = cvDlsDQJac;
  cvdls_mem->J_data = cv_mem;
  cvdls_mem->last_flag = CVDLS_SUCCESS;

  /* Initialize counters */
  cvDlsInitializeCounters(cvdls_mem);

  /* Store pointer to A and create saved_J */
  cvdls_mem->A = A;
  cvdls_mem->savedJ = SUNMatClone(A);
  if (cvdls_mem->savedJ == NULL) {
    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVDLS", 
                    "CVDlsSetLinearSolver", MSGD_MEM_FAIL);
    free(cvdls_mem); cvdls_mem = NULL;
    return(CVDLS_MEM_FAIL);
  }

  /* Allocate memory for x */
  cvdls_mem->x = N_VClone(cv_mem->cv_tempv);
  if (cvdls_mem->x == NULL) {
    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVDLS", 
                    "CVDlsSetLinearSolver", MSGD_MEM_FAIL);
    SUNMatDestroy(cvdls_mem->savedJ);
    free(cvdls_mem); cvdls_mem = NULL;
    return(CVDLS_MEM_FAIL);
  }
  /* Attach linear solver memory to integrator memory */
  cv_mem->cv_lmem = cvdls_mem;

  return(CVDLS_SUCCESS);
}
/* ----------------------------------------------------------------------
 * Extra ScaleAdd tests for sparse matrices:
 *    A and B should have different sparsity patterns, and neither should
 *      contain sufficient storage to for their sum
 *    y should already equal A*x
 *    z should already equal B*x
 * --------------------------------------------------------------------*/
int Test_SUNMatScaleAdd2(SUNMatrix A, SUNMatrix B, N_Vector x,
                         N_Vector y, N_Vector z)
{
  int       failure;
  SUNMatrix C, D, E;
  N_Vector  u, v;
  realtype  tol=100*UNIT_ROUNDOFF;

  /* create clones for test */
  C = SUNMatClone(A);
  u = N_VClone(y);
  v = N_VClone(y);

  /* test 1: add A to B (output must be enlarged) */
  failure = SUNMatCopy(A, C);            /* C = A */
  if (failure) {
    printf(">>> FAILED test -- SUNMatCopy returned %d \n",
           failure);
    SUNMatDestroy(C);  N_VDestroy(u);  N_VDestroy(v);  return(1);
  }
  failure = SUNMatScaleAdd(ONE, C, B);   /* C = A+B */
  if (failure) {
    printf(">>> FAILED test -- SUNMatScaleAdd returned %d \n",
           failure);
    SUNMatDestroy(C);  N_VDestroy(u);  N_VDestroy(v);  return(1);
  }
  failure = SUNMatMatvec(C, x, u);       /* u = Cx = Ax+Bx */
  if (failure) {
    printf(">>> FAILED test -- SUNMatMatvec returned %d \n",
           failure);
    SUNMatDestroy(C);  N_VDestroy(u);  N_VDestroy(v);  return(1);
  }
  N_VLinearSum(ONE,y,ONE,z,v);           /* v = y+z */
  failure = check_vector(u, v, tol);     /* u ?= v */
  if (failure) {
    printf(">>> FAILED test -- SUNMatScaleAdd2 check 1 \n");
    printf("\nA =\n");
    SUNSparseMatrix_Print(A,stdout);
    printf("\nB =\n");
    SUNSparseMatrix_Print(B,stdout);
    printf("\nC =\n");
    SUNSparseMatrix_Print(C,stdout);
    printf("\nx =\n");
    N_VPrint_Serial(x);
    printf("\ny =\n");
    N_VPrint_Serial(y);
    printf("\nz =\n");
    N_VPrint_Serial(z);
    printf("\nu =\n");
    N_VPrint_Serial(u);
    printf("\nv =\n");
    N_VPrint_Serial(v);
    SUNMatDestroy(C);  N_VDestroy(u);  N_VDestroy(v);  return(1);
  }
  else {
    printf("    PASSED test -- SUNMatScaleAdd2 check 1 \n");
  }

  /* test 2: add A to a matrix with sufficient but misplaced storage */
  D = SUNMatClone(A);
  failure = SUNSparseMatrix_Reallocate(D, SM_NNZ_S(A)+SM_NNZ_S(B));
  failure = SUNMatCopy(A, D);            /* D = A */
  if (failure) {
    printf(">>> FAILED test -- SUNMatCopy returned %d \n",
           failure);
    SUNMatDestroy(C);  SUNMatDestroy(D);
    N_VDestroy(u);  N_VDestroy(v);  return(1);
  }
  failure = SUNMatScaleAdd(ONE, D, B);   /* D = A+B */
  if (failure) {
    printf(">>> FAILED test -- SUNMatScaleAdd returned %d \n",
           failure);
    SUNMatDestroy(C);  SUNMatDestroy(D);
    N_VDestroy(u);  N_VDestroy(v);  return(1);
  }
  failure = SUNMatMatvec(D, x, u);       /* u = Cx = Ax+Bx */
  if (failure) {
    printf(">>> FAILED test -- SUNMatMatvec returned %d \n",
           failure);
    SUNMatDestroy(C);  SUNMatDestroy(D);
    N_VDestroy(u);  N_VDestroy(v);  return(1);
  }
  N_VLinearSum(ONE,y,ONE,z,v);           /* v = y+z */
  failure = check_vector(u, v, tol);     /* u ?= v */
  if (failure) {
    printf(">>> FAILED test -- SUNMatScaleAdd2 check 2 \n");
    printf("\nA =\n");
    SUNSparseMatrix_Print(A,stdout);
    printf("\nB =\n");
    SUNSparseMatrix_Print(B,stdout);
    printf("\nD =\n");
    SUNSparseMatrix_Print(D,stdout);
    printf("\nx =\n");
    N_VPrint_Serial(x);
    printf("\ny =\n");
    N_VPrint_Serial(y);
    printf("\nz =\n");
    N_VPrint_Serial(z);
    printf("\nu =\n");
    N_VPrint_Serial(u);
    printf("\nv =\n");
    N_VPrint_Serial(v);
    SUNMatDestroy(C);  SUNMatDestroy(D);
    N_VDestroy(u);  N_VDestroy(v);  return(1);
  }
  else {
    printf("    PASSED test -- SUNMatScaleAdd2 check 2 \n");
  }


  /* test 3: add A to a matrix with the appropriate structure already in place */
  E = SUNMatClone(C);
  failure = SUNMatCopy(C, E);                /* E = A + B */
  if (failure) {
    printf(">>> FAILED test -- SUNMatCopy returned %d \n",
           failure);
    SUNMatDestroy(C);  SUNMatDestroy(D);  SUNMatDestroy(E);
    N_VDestroy(u);  N_VDestroy(v);  return(1);
  }
  failure = SUNMatScaleAdd(NEG_ONE, E, B);   /* E = -A */
  if (failure) {
    printf(">>> FAILED test -- SUNMatScaleAdd returned %d \n",
           failure);
    SUNMatDestroy(C);  SUNMatDestroy(D);  SUNMatDestroy(E);
    N_VDestroy(u);  N_VDestroy(v);  return(1);
  }
  failure = SUNMatMatvec(E, x, u);           /* u = Ex = -Ax */
  if (failure) {
    printf(">>> FAILED test -- SUNMatMatvec returned %d \n",
           failure);
    SUNMatDestroy(C);  SUNMatDestroy(D);  SUNMatDestroy(E);
    N_VDestroy(u);  N_VDestroy(v);  return(1);
  }
  N_VLinearSum(NEG_ONE,y,ZERO,z,v);          /* v = -y */
  failure = check_vector(u, v, tol);         /* v ?= u */
  if (failure) {
    printf(">>> FAILED test -- SUNMatScaleAdd2 check 3 \n");
    printf("\nA =\n");
    SUNSparseMatrix_Print(A,stdout);
    printf("\nB =\n");
    SUNSparseMatrix_Print(B,stdout);
    printf("\nC =\n");
    SUNSparseMatrix_Print(C,stdout);
    printf("\nE =\n");
    SUNSparseMatrix_Print(E,stdout);
    printf("\nx =\n");
    N_VPrint_Serial(x);
    printf("\ny =\n");
    N_VPrint_Serial(y);
    printf("\nu =\n");
    N_VPrint_Serial(u);
    printf("\nv =\n");
    N_VPrint_Serial(v);
    SUNMatDestroy(C);  SUNMatDestroy(D);  SUNMatDestroy(E);
    N_VDestroy(u);  N_VDestroy(v);  return(1);
  }
  else {
    printf("    PASSED test -- SUNMatScaleAdd2 check 3 \n");
  }

  SUNMatDestroy(C);
  SUNMatDestroy(D);
  SUNMatDestroy(E);
  N_VDestroy(u);
  N_VDestroy(v);
  return(0);
}