コード例 #1
0
ファイル: ida_nls.c プロジェクト: polymec/polymec-dev
static int idaNlsConvTest(SUNNonlinearSolver NLS, N_Vector ycor, N_Vector del,
                          realtype tol, N_Vector ewt, void* ida_mem)
{
  IDAMem IDA_mem;
  int m, retval;
  realtype delnrm;
  realtype rate;

  if (ida_mem == NULL) {
    IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "idaNlsConvTest", MSG_NO_MEM);
    return(IDA_MEM_NULL);
  }
  IDA_mem = (IDAMem) ida_mem;

  /* compute the norm of the correction */
  delnrm = N_VWrmsNorm(del, ewt);

  /* get the current nonlinear solver iteration count */
  retval = SUNNonlinSolGetCurIter(NLS, &m);
  if (retval != IDA_SUCCESS) return(IDA_MEM_NULL);

  /* test for convergence, first directly, then with rate estimate. */
  if (m == 0){
    IDA_mem->ida_oldnrm = delnrm;
    if (delnrm <= PT0001 * IDA_mem->ida_toldel) return(SUN_NLS_SUCCESS);
  } else {
    rate = SUNRpowerR( delnrm/IDA_mem->ida_oldnrm, ONE/m );
    if (rate > RATEMAX) return(SUN_NLS_CONV_RECVR);
    IDA_mem->ida_ss = rate/(ONE - rate);
  }

  if (IDA_mem->ida_ss*delnrm <= tol) return(SUN_NLS_SUCCESS);

  /* not yet converged */
  return(SUN_NLS_CONTINUE);
}
コード例 #2
0
ファイル: ida_klu.c プロジェクト: MaveriQ/AMICI
static int IDAKLUSetup(IDAMem IDA_mem, N_Vector yyp, N_Vector ypp,
		       N_Vector rrp, N_Vector tmp1, N_Vector tmp2,
		       N_Vector tmp3)
{
  int retval;
  realtype tn, cj;
  IDASlsMem idasls_mem;
  IDASlsSparseJacFn jaceval;
  KLUData klu_data;
  SlsMat JacMat;
  void *jacdata;
  
  realtype uround_twothirds;

  uround_twothirds = SUNRpowerR(IDA_mem->ida_uround,TWOTHIRDS);

  idasls_mem = (IDASlsMem) (IDA_mem->ida_lmem);
  tn = IDA_mem->ida_tn; 
  cj = IDA_mem->ida_cj;

  klu_data = (KLUData) idasls_mem->s_solver_data;

  jaceval = idasls_mem->s_jaceval;
  jacdata = idasls_mem->s_jacdata;
  JacMat = idasls_mem->s_JacMat;

  /* Check that Jacobian eval routine is set */
  if (jaceval == NULL) {
    IDAProcessError(IDA_mem, IDASLS_JAC_NOSET, "IDASLS", "IDAKLUSetup", 
		    MSGSP_JAC_NOSET);
    free(idasls_mem); idasls_mem = NULL;
    return(IDASLS_JAC_NOSET);
  }

  /* Increment nje counter and call Jacobian eval routine. */
  idasls_mem->s_nje++;
  retval = jaceval(tn, cj, yyp, ypp, rrp, JacMat, jacdata, 
		   tmp1, tmp2, tmp3);

  if (retval < 0) {
    IDAProcessError(IDA_mem, IDASLS_JACFUNC_UNRECVR, "IDASLS", 
		    "IDAKLUSetup", MSGSP_JACFUNC_FAILED);
    idasls_mem->s_last_flag = IDASLS_JACFUNC_UNRECVR;
    return(IDASLS_JACFUNC_UNRECVR);
  }
  if (retval > 0) {
    idasls_mem->s_last_flag = IDASLS_JACFUNC_RECVR;
    return(+1);
  }

  if (idasls_mem->s_first_factorize) {
    /* ------------------------------------------------------------
       Get the symbolic factorization
       ------------------------------------------------------------*/ 
    /* Update the ordering option with any user-updated values from 
       calls to IDAKLUSetOrdering */
    klu_data->s_Common.ordering = klu_data->s_ordering;

    klu_data->s_Symbolic = klu_analyze(JacMat->N, JacMat->colptrs, 
				       JacMat->rowvals, &(klu_data->s_Common));
    if (klu_data->s_Symbolic == NULL) {
      IDAProcessError(IDA_mem, IDASLS_PACKAGE_FAIL, "IDASLS", "IDAKLUSetup", 
		      MSGSP_PACKAGE_FAIL);
      return(IDASLS_PACKAGE_FAIL);
    }

    /* ------------------------------------------------------------
       Compute the LU factorization of  the Jacobian.
       ------------------------------------------------------------*/
    klu_data->s_Numeric = klu_factor(JacMat->colptrs, JacMat->rowvals, JacMat->data, 
				     klu_data->s_Symbolic, &(klu_data->s_Common));

    if (klu_data->s_Numeric == NULL) {
      IDAProcessError(IDA_mem, IDASLS_PACKAGE_FAIL, "IDASLS", "IDAKLUSetup", 
		      MSGSP_PACKAGE_FAIL);
      return(IDASLS_PACKAGE_FAIL);
    }

    idasls_mem->s_first_factorize = 0;
  }
  else {

    retval = klu_refactor(JacMat->colptrs, JacMat->rowvals, JacMat->data, 
			  klu_data->s_Symbolic, klu_data->s_Numeric,
			  &(klu_data->s_Common));
    if (retval == 0) {
      IDAProcessError(IDA_mem, IDASLS_PACKAGE_FAIL, "IDASLS", "idaKLUSetup", 
		      MSGSP_PACKAGE_FAIL);
      return(IDASLS_PACKAGE_FAIL);
    }
    
    /*-----------------------------------------------------------
      Check if a cheap estimate of the reciprocal of the condition 
      number is getting too small.  If so, delete
      the prior numeric factorization and recompute it.
      -----------------------------------------------------------*/
    
    retval = klu_rcond(klu_data->s_Symbolic, klu_data->s_Numeric,
		       &(klu_data->s_Common));
    if (retval == 0) {
      IDAProcessError(IDA_mem, IDASLS_PACKAGE_FAIL, "IDASLS", "idaKLUSetup", 
		      MSGSP_PACKAGE_FAIL);
      return(IDASLS_PACKAGE_FAIL);
    }

    if ( (klu_data->s_Common.rcond)  < uround_twothirds ) {
      
      /* Condition number may be getting large.  
	 Compute more accurate estimate */
      retval = klu_condest(JacMat->colptrs, JacMat->data, 
			   klu_data->s_Symbolic, klu_data->s_Numeric,
			   &(klu_data->s_Common));
      if (retval == 0) {
	IDAProcessError(IDA_mem, IDASLS_PACKAGE_FAIL, "IDASLS", "idaKLUSetup", 
			MSGSP_PACKAGE_FAIL);
	return(IDASLS_PACKAGE_FAIL);
      }
      
      if ( (klu_data->s_Common.condest) > 
	   (1.0/uround_twothirds) ) {

	/* More accurate estimate also says condition number is 
	   large, so recompute the numeric factorization */

	klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
	
	klu_data->s_Numeric = klu_factor(JacMat->colptrs, JacMat->rowvals, 
					 JacMat->data, klu_data->s_Symbolic, 
					 &(klu_data->s_Common));

	if (klu_data->s_Numeric == NULL) {
	  IDAProcessError(IDA_mem, IDASLS_PACKAGE_FAIL, "IDASLS", 
			  "IDAKLUSetup", MSGSP_PACKAGE_FAIL);
	  return(IDASLS_PACKAGE_FAIL);
	}
      }
    }
  }

  idasls_mem->s_last_flag = IDASLS_SUCCESS;

  return(0);
}
コード例 #3
0
ファイル: arkode_klu.c プロジェクト: luca-heltai/sundials
/*---------------------------------------------------------------
 arkMassKLUSetup:

  This routine does the setup operations for the ARKMassKLU 
  linear solver module.  It calls the mass matrix evaluation 
  routine, updates counters, and calls the LU factorization 
  routine.  The return value is either
     ARkSLS_SUCCESS = 0  if successful,
     +1  if the Meval routine failed recoverably or the
         LU factorization failed, or
     -1  if the Meval routine failed unrecoverably.
---------------------------------------------------------------*/
static int arkMassKLUSetup(ARKodeMem ark_mem, N_Vector vtemp1, 
			   N_Vector vtemp2, N_Vector vtemp3)
{
  ARKSlsMassMem arksls_mem;
  KLUData klu_data;
  int retval;
  
  realtype uround_twothirds;
  
  uround_twothirds = SUNRpowerR(ark_mem->ark_uround,TWOTHIRDS);

  arksls_mem = (ARKSlsMassMem) ark_mem->ark_mass_mem;
  klu_data = (KLUData) arksls_mem->s_solver_data;
  
  /* Check that mass matrix eval routine is set */
  if (arksls_mem->s_Meval == NULL) {
    arkProcessError(ark_mem, ARKSLS_MASS_NOSET, "ARKSLS", 
		    "arkMassKLUSetup", MSGSP_MASS_NOSET);
    free(arksls_mem); arksls_mem = NULL;
    return(ARKSLS_MASS_NOSET);
  }

  /* call Meval routine for new M matrix */
  SparseSetMatToZero(arksls_mem->s_M);
  retval = arksls_mem->s_Meval(ark_mem->ark_tn, arksls_mem->s_M, 
			       arksls_mem->s_Mdata, vtemp1, 
			       vtemp2, vtemp3);
  arksls_mem->s_nme++;
  if (retval < 0) {
    arkProcessError(ark_mem, ARKSLS_MASSFUNC_UNRECVR, "ARKSLS", 
		    "arkMassKLUSetup", MSGSP_MASSFUNC_FAILED);
    arksls_mem->s_last_flag = ARKSLS_MASSFUNC_UNRECVR;
    return(-1);
  }
  if (retval > 0) {
    arksls_mem->s_last_flag = ARKSLS_MASSFUNC_RECVR;
    return(1);
  }

  /* Copy M into M_lu for LU decomposition */
  SparseCopyMat(arksls_mem->s_M, arksls_mem->s_M_lu);

  /* On first decomposition, get the symbolic factorization */ 
  if (arksls_mem->s_first_factorize) {

    /* Update the ordering option with user-updated values */
    klu_data->s_Common.ordering = klu_data->s_ordering;

    /* Perform symbolic analysis of sparsity structure */
    if (klu_data->s_Symbolic != NULL) {
       klu_free_symbolic(&(klu_data->s_Symbolic), &(klu_data->s_Common));
    }
    klu_data->s_Symbolic = klu_analyze(arksls_mem->s_M_lu->N, 
                                       arksls_mem->s_M_lu->indexptrs, 
				       arksls_mem->s_M_lu->indexvals, 
				       &(klu_data->s_Common));
    if (klu_data->s_Symbolic == NULL) {
      arkProcessError(ark_mem, ARKSLS_PACKAGE_FAIL, "ARKSLS", 
		      "ARKMassKLUSetup", MSGSP_PACKAGE_FAIL);
      return(ARKSLS_PACKAGE_FAIL);
    }

    /* ------------------------------------------------------------
       Compute the LU factorization of  the Jacobian.
       ------------------------------------------------------------*/
    if( klu_data->s_Numeric != NULL) {
       klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
    }
    klu_data->s_Numeric = klu_factor(arksls_mem->s_M_lu->indexptrs, 
				     arksls_mem->s_M_lu->indexvals, 
				     arksls_mem->s_M_lu->data, 
				     klu_data->s_Symbolic, 
				     &(klu_data->s_Common));
    if (klu_data->s_Numeric == NULL) {
      arkProcessError(ark_mem, ARKSLS_PACKAGE_FAIL, "ARKSLS", 
		      "ARKMassKLUSetup", MSGSP_PACKAGE_FAIL);
      return(ARKSLS_PACKAGE_FAIL);
    }
    
    arksls_mem->s_first_factorize = 0;
  }
  else {

    retval = klu_refactor(arksls_mem->s_M_lu->indexptrs, 
			  arksls_mem->s_M_lu->indexvals, 
			  arksls_mem->s_M_lu->data,
			  klu_data->s_Symbolic, klu_data->s_Numeric,
			  &(klu_data->s_Common));
    if (retval == 0) {
      arkProcessError(ark_mem, ARKSLS_PACKAGE_FAIL, "ARKSLS", 
		      "ARKMassKLUSetup", MSGSP_PACKAGE_FAIL);
      return(ARKSLS_PACKAGE_FAIL);
    }
    
    /*-----------------------------------------------------------
      Check if a cheap estimate of the reciprocal of the condition 
      number is getting too small.  If so, delete
      the prior numeric factorization and recompute it.
      -----------------------------------------------------------*/
    
    retval = klu_rcond(klu_data->s_Symbolic, klu_data->s_Numeric,
		       &(klu_data->s_Common));
    if (retval == 0) {
      arkProcessError(ark_mem, ARKSLS_PACKAGE_FAIL, "ARKSLS", 
		      "ARKMassKLUSetup", MSGSP_PACKAGE_FAIL);
      return(ARKSLS_PACKAGE_FAIL);
    }

    if ( (klu_data->s_Common.rcond)  < uround_twothirds ) {
      
      /* Condition number may be getting large.  
	 Compute more accurate estimate */
      retval = klu_condest(arksls_mem->s_M_lu->indexptrs, 
			   arksls_mem->s_M_lu->data,
			   klu_data->s_Symbolic, klu_data->s_Numeric,
			   &(klu_data->s_Common));
      if (retval == 0) {
	arkProcessError(ark_mem, ARKSLS_PACKAGE_FAIL, "ARKSLS", 
			"ARKMassKLUSetup", MSGSP_PACKAGE_FAIL);
	return(ARKSLS_PACKAGE_FAIL);
      }
      
      if ( (klu_data->s_Common.condest) > 
	   (1.0/uround_twothirds) ) {

	/* More accurate estimate also says condition number is 
	   large, so recompute the numeric factorization */

	klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
	
	klu_data->s_Numeric = klu_factor(arksls_mem->s_M_lu->indexptrs, 
					 arksls_mem->s_M_lu->indexvals, 
					 arksls_mem->s_M_lu->data, 
					 klu_data->s_Symbolic, 
					 &(klu_data->s_Common));

	if (klu_data->s_Numeric == NULL) {
	  arkProcessError(ark_mem, ARKSLS_PACKAGE_FAIL, "ARKSLS", 
			  "ARKMassKLUSetup", MSGSP_PACKAGE_FAIL);
	  return(ARKSLS_PACKAGE_FAIL);
	}
      }
    }
  }

  arksls_mem->s_last_flag = ARKSLS_SUCCESS;
  return(0);
}
コード例 #4
0
ファイル: arkode_klu.c プロジェクト: luca-heltai/sundials
/*---------------------------------------------------------------
 arkKLUSetup:

  This routine does the setup operations for the ARKKLU linear 
  solver module.  It calls the Jacobian evaluation routine,
  updates counters, and calls the LU factorization routine.
  The return value is either
     ARKSLS_SUCCESS = 0  if successful,
     +1  if the jac routine failed recoverably or the
         LU factorization failed, or
     -1  if the jac routine failed unrecoverably.
---------------------------------------------------------------*/
static int arkKLUSetup(ARKodeMem ark_mem, int convfail, 
		       N_Vector ypred, N_Vector fpred, 
		       booleantype *jcurPtr, N_Vector vtemp1, 
		       N_Vector vtemp2, N_Vector vtemp3)
{
  booleantype jbad, jok;
  realtype dgamma;
  ARKSlsMem arksls_mem;
  ARKSlsMassMem arksls_mass_mem;
  KLUData klu_data;
  int retval;

  realtype uround_twothirds;
  
  uround_twothirds = SUNRpowerR(ark_mem->ark_uround,TWOTHIRDS);

  arksls_mem = (ARKSlsMem) ark_mem->ark_lmem;
  klu_data = (KLUData) arksls_mem->s_solver_data;
  
  /* Check that Jacobian eval routine is set */
  if (arksls_mem->s_Jeval == NULL) {
    arkProcessError(ark_mem, ARKSLS_JAC_NOSET, "ARKSLS", 
		    "arkKLUSetup", MSGSP_JAC_NOSET);
    free(arksls_mem); arksls_mem = NULL;
    return(ARKSLS_JAC_NOSET);
  }

  /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */
  dgamma = SUNRabs((ark_mem->ark_gamma/ark_mem->ark_gammap) - ONE);
  jbad = (ark_mem->ark_nst == 0) || 
    (ark_mem->ark_nst > arksls_mem->s_nstlj + ARKS_MSBJ) ||
    ((convfail == ARK_FAIL_BAD_J) && (dgamma < ARKS_DGMAX)) ||
    (convfail == ARK_FAIL_OTHER);
  jok = !jbad;
  
  /* If jok = TRUE, use saved copy of J */
  if (jok) {
    *jcurPtr = FALSE;
    SparseCopyMat(arksls_mem->s_savedJ, arksls_mem->s_A);

  /* If jok = FALSE, call jac routine for new J value */
  } else {
    arksls_mem->s_nje++;
    arksls_mem->s_nstlj = ark_mem->ark_nst;
    *jcurPtr = TRUE;
    SparseSetMatToZero(arksls_mem->s_A);

    retval = arksls_mem->s_Jeval(ark_mem->ark_tn, ypred, fpred, 
				 arksls_mem->s_A, arksls_mem->s_Jdata, 
				 vtemp1, vtemp2, vtemp3);
    if (retval < 0) {
      arkProcessError(ark_mem, ARKSLS_JACFUNC_UNRECVR, "ARKSLS", 
		      "arkKLUSetup", MSGSP_JACFUNC_FAILED);
      arksls_mem->s_last_flag = ARKSLS_JACFUNC_UNRECVR;
      return(-1);
    }
    if (retval > 0) {
      arksls_mem->s_last_flag = ARKSLS_JACFUNC_RECVR;
      return(1);
    }

    SparseCopyMat(arksls_mem->s_A, arksls_mem->s_savedJ);
  }

  /* Scale J by -gamma */
  SparseScaleMat(-ark_mem->ark_gamma, arksls_mem->s_A);

  /* Add mass matrix to get A = M-gamma*J */
  if (ark_mem->ark_mass_matrix) {

    /* Compute mass matrix */
    arksls_mass_mem = (ARKSlsMassMem) ark_mem->ark_mass_mem;
    SparseSetMatToZero(arksls_mass_mem->s_M);
    retval = arksls_mass_mem->s_Meval(ark_mem->ark_tn, 
				      arksls_mass_mem->s_M, 
				      arksls_mass_mem->s_Mdata, 
				      vtemp1, vtemp2, vtemp3);
    arksls_mass_mem->s_nme++;
    if (retval < 0) {
      arkProcessError(ark_mem, ARKSLS_MASSFUNC_UNRECVR, "ARKSLS", 
		      "arkKLUSetup",  MSGSP_MASSFUNC_FAILED);
      arksls_mem->s_last_flag = ARKSLS_MASSFUNC_UNRECVR;
      return(-1);
    }
    if (retval > 0) {
      arksls_mem->s_last_flag = ARKSLS_MASSFUNC_RECVR;
      return(1);
    }
    
    /* add to A */
    retval = SparseAddMat(arksls_mem->s_A, arksls_mass_mem->s_M);
    if (retval < 0) {
      arkProcessError(ark_mem, ARKSLS_PACKAGE_FAIL, "ARKSLS", 
		      "arkKLUSetup",  "Error in adding mass matrix to Jacobian");
      arksls_mem->s_last_flag = ARKSLS_PACKAGE_FAIL;
      return(retval);
    }
    if (retval > 0)  return(retval);
    
  } else {
    SparseAddIdentityMat(arksls_mem->s_A);
  }


  /* On first decomposition, get the symbolic factorization */ 
  if (arksls_mem->s_first_factorize) {

    /* Update the ordering option with user-updated values */
    klu_data->s_Common.ordering = klu_data->s_ordering;

    /* Perform symbolic analysis of sparsity structure */
    if (klu_data->s_Symbolic != NULL) {
       klu_free_symbolic(&(klu_data->s_Symbolic), &(klu_data->s_Common));
    }
    klu_data->s_Symbolic = klu_analyze(arksls_mem->s_A->NP, 
				       arksls_mem->s_A->indexptrs, 
				       arksls_mem->s_A->indexvals, 
				       &(klu_data->s_Common));
    if (klu_data->s_Symbolic == NULL) {
      arkProcessError(ark_mem, ARKSLS_PACKAGE_FAIL, "ARKSLS", 
		      "ARKKLUSetup", MSGSP_PACKAGE_FAIL);
      return(ARKSLS_PACKAGE_FAIL);
    }

    /* ------------------------------------------------------------
       Compute the LU factorization of  the Jacobian.
       ------------------------------------------------------------*/
    if( klu_data->s_Numeric != NULL) {
       klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
    }
    klu_data->s_Numeric = klu_factor(arksls_mem->s_A->indexptrs, 
				     arksls_mem->s_A->indexvals, 
				     arksls_mem->s_A->data, 
				     klu_data->s_Symbolic, 
				     &(klu_data->s_Common));
    if (klu_data->s_Numeric == NULL) {
      arkProcessError(ark_mem, ARKSLS_PACKAGE_FAIL, "ARKSLS", 
		      "ARKKLUSetup", MSGSP_PACKAGE_FAIL);
      return(ARKSLS_PACKAGE_FAIL);
    }

    arksls_mem->s_first_factorize = 0;
  }
  else {

    retval = klu_refactor(arksls_mem->s_A->indexptrs, 
			  arksls_mem->s_A->indexvals, 
			  arksls_mem->s_A->data, 
			  klu_data->s_Symbolic, klu_data->s_Numeric,
			  &(klu_data->s_Common));
    if (retval == 0) {
      arkProcessError(ark_mem, ARKSLS_PACKAGE_FAIL, "ARKSLS", 
		      "ARKKLUSetup", MSGSP_PACKAGE_FAIL);
      return(ARKSLS_PACKAGE_FAIL);
    }
    
    /*-----------------------------------------------------------
      Check if a cheap estimate of the reciprocal of the condition 
      number is getting too small.  If so, delete
      the prior numeric factorization and recompute it.
      -----------------------------------------------------------*/
    
    retval = klu_rcond(klu_data->s_Symbolic, klu_data->s_Numeric,
		       &(klu_data->s_Common));
    if (retval == 0) {
      arkProcessError(ark_mem, ARKSLS_PACKAGE_FAIL, "ARKSLS", 
		      "ARKKLUSetup", MSGSP_PACKAGE_FAIL);
      return(ARKSLS_PACKAGE_FAIL);
    }

    if ( (klu_data->s_Common.rcond)  < uround_twothirds ) {
      
      /* Condition number may be getting large.  
	 Compute more accurate estimate */
      retval = klu_condest(arksls_mem->s_A->indexptrs, 
			   arksls_mem->s_A->data, 
			   klu_data->s_Symbolic, klu_data->s_Numeric,
			   &(klu_data->s_Common));
      if (retval == 0) {
	arkProcessError(ark_mem, ARKSLS_PACKAGE_FAIL, "ARKSLS", 
			"ARKKLUSetup", MSGSP_PACKAGE_FAIL);
	return(ARKSLS_PACKAGE_FAIL);
      }
      
      if ( (klu_data->s_Common.condest) > 
	   (1.0/uround_twothirds) ) {

	/* More accurate estimate also says condition number is 
	   large, so recompute the numeric factorization */

	klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
	
	klu_data->s_Numeric = klu_factor(arksls_mem->s_A->indexptrs, 
					 arksls_mem->s_A->indexvals, 
					 arksls_mem->s_A->data,
					 klu_data->s_Symbolic, 
					 &(klu_data->s_Common));

	if (klu_data->s_Numeric == NULL) {
	  arkProcessError(ark_mem, ARKSLS_PACKAGE_FAIL, "ARKSLS", 
			  "ARKKLUSetup", MSGSP_PACKAGE_FAIL);
	  return(ARKSLS_PACKAGE_FAIL);
	}
      }
    }
  }

  arksls_mem->s_last_flag = ARKSLS_SUCCESS;
  return(0);
}
コード例 #5
0
ファイル: cvode_klu.c プロジェクト: luca-heltai/sundials
static int cvKLUSetup(CVodeMem cv_mem, int convfail, N_Vector ypred, 
		      N_Vector fpred, booleantype *jcurPtr,
		      N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3)
{
  booleantype jbad, jok;
  int retval;
  long int nst, nstlj;
  realtype tn, gamma, gammap, dgamma;
  CVSlsMem cvsls_mem;
  CVSlsSparseJacFn jaceval;
  KLUData klu_data;
  SlsMat JacMat, savedJ;
  void *jacdata;
  
  realtype uround_twothirds;

  uround_twothirds = SUNRpowerR(cv_mem->cv_uround,TWOTHIRDS);

  cvsls_mem = (CVSlsMem) (cv_mem->cv_lmem);
  tn = cv_mem->cv_tn; 
  gamma = cv_mem->cv_gamma;
  gammap = cv_mem->cv_gammap;
  nst = cv_mem->cv_nst;

  klu_data = (KLUData) cvsls_mem->s_solver_data;

  jaceval = cvsls_mem->s_jaceval;
  jacdata = cvsls_mem->s_jacdata;
  JacMat = cvsls_mem->s_JacMat;
  savedJ = cvsls_mem->s_savedJ;
  nstlj = cvsls_mem->s_nstlj;

  /* Check that Jacobian eval routine is set */
  if (jaceval == NULL) {
    cvProcessError(cv_mem, CVSLS_JAC_NOSET, "CVSLS", "cvKLUSetup", 
		    MSGSP_JAC_NOSET);
    free(cvsls_mem); cvsls_mem = NULL;
    return(CVSLS_JAC_NOSET);
  }

  /* Determine whether Jacobian needs to be recalculated */
  dgamma = SUNRabs((gamma/gammap) - ONE);
  jbad = (nst == 0) || (nst > nstlj + CVS_MSBJ) ||
         ((convfail == CV_FAIL_BAD_J) && (dgamma < CVS_DGMAX)) ||
         (convfail == CV_FAIL_OTHER);
  jok = !jbad;
  
  if (jok) {
    /* If jok = TRUE, use saved copy of J */
    *jcurPtr = FALSE;
    SparseCopyMat(savedJ, JacMat);
  } else {
    /* If jok = FALSE, call jac routine for new J value */
    cvsls_mem->s_nje++;
    cvsls_mem->s_nstlj = nst;
    *jcurPtr = TRUE;
    SparseSetMatToZero(JacMat);
    retval = jaceval(tn, ypred, fpred, JacMat, jacdata, vtemp1, vtemp2, vtemp3);
    if (retval < 0) {
      cvProcessError(cv_mem, CVSLS_JACFUNC_UNRECVR, "CVSLS", "cvKLUSetup", MSGSP_JACFUNC_FAILED);
      cvsls_mem->s_last_flag = CVSLS_JACFUNC_UNRECVR;
      return(-1);
    }
    if (retval > 0) {
      cvsls_mem->s_last_flag = CVSLS_JACFUNC_RECVR;
      return(1);
    }

    SparseCopyMat(JacMat, savedJ);
  }

  /* Scale and add I to get M = I - gamma*J */
  SparseScaleMat(-gamma, JacMat);
  SparseAddIdentityMat(JacMat);

  if (cvsls_mem->s_first_factorize) {
    /* ------------------------------------------------------------
       Get the symbolic factorization
       ------------------------------------------------------------*/ 
    /* Update the ordering option with any user-updated values from 
       calls to CVKLUSetOrdering */
    klu_data->s_Common.ordering = klu_data->s_ordering;

    if (klu_data->s_Symbolic != NULL) {
       klu_free_symbolic(&(klu_data->s_Symbolic), &(klu_data->s_Common));
    }
    klu_data->s_Symbolic = klu_analyze(JacMat->NP, JacMat->indexptrs, 
				       JacMat->indexvals, &(klu_data->s_Common));
    if (klu_data->s_Symbolic == NULL) {
      cvProcessError(cv_mem, CVSLS_PACKAGE_FAIL, "CVSLS", "CVKLUSetup", 
		      MSGSP_PACKAGE_FAIL);
      return(CVSLS_PACKAGE_FAIL);
    }

    /* ------------------------------------------------------------
       Compute the LU factorization of  the Jacobian.
       ------------------------------------------------------------*/
    /* If klu_factor previously called, free data */
    if( klu_data->s_Numeric != NULL) {
       klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
    }
    klu_data->s_Numeric = klu_factor(JacMat->indexptrs, JacMat->indexvals, 
				     JacMat->data, 
				     klu_data->s_Symbolic, &(klu_data->s_Common));

    if (klu_data->s_Numeric == NULL) {
      cvProcessError(cv_mem, CVSLS_PACKAGE_FAIL, "CVSLS", "CVKLUSetup", 
		      MSGSP_PACKAGE_FAIL);
      return(CVSLS_PACKAGE_FAIL);
    }

    cvsls_mem->s_first_factorize = 0;
  }
  else {

    retval = klu_refactor(JacMat->indexptrs, JacMat->indexvals, JacMat->data, 
			  klu_data->s_Symbolic, klu_data->s_Numeric,
			  &(klu_data->s_Common));
    if (retval == 0) {
      cvProcessError(cv_mem, CVSLS_PACKAGE_FAIL, "CVSLS", "cvKLUSetup", 
		      MSGSP_PACKAGE_FAIL);
      return(CVSLS_PACKAGE_FAIL);
    }
    
    /*-----------------------------------------------------------
      Check if a cheap estimate of the reciprocal of the condition 
      number is getting too small.  If so, delete
      the prior numeric factorization and recompute it.
      -----------------------------------------------------------*/
    
    retval = klu_rcond(klu_data->s_Symbolic, klu_data->s_Numeric,
		       &(klu_data->s_Common));
    if (retval == 0) {
      cvProcessError(cv_mem, CVSLS_PACKAGE_FAIL, "CVSLS", "CVKLUSetup", 
		      MSGSP_PACKAGE_FAIL);
      return(CVSLS_PACKAGE_FAIL);
    }

    if ( (klu_data->s_Common.rcond)  < uround_twothirds ) {
      
      /* Condition number may be getting large.  
	 Compute more accurate estimate */
      retval = klu_condest(JacMat->indexptrs, JacMat->data, 
			   klu_data->s_Symbolic, klu_data->s_Numeric,
			   &(klu_data->s_Common));
      if (retval == 0) {
	cvProcessError(cv_mem, CVSLS_PACKAGE_FAIL, "CVSLS", "CVKLUSetup", 
		       MSGSP_PACKAGE_FAIL);
	return(CVSLS_PACKAGE_FAIL);
      }
      
      if ( (klu_data->s_Common.condest) > 
	   (1.0/uround_twothirds) ) {

	/* More accurate estimate also says condition number is 
	   large, so recompute the numeric factorization */

	klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
	
	klu_data->s_Numeric = klu_factor(JacMat->indexptrs, JacMat->indexvals, 
					 JacMat->data, klu_data->s_Symbolic, 
					 &(klu_data->s_Common));

	if (klu_data->s_Numeric == NULL) {
	  cvProcessError(cv_mem, CVSLS_PACKAGE_FAIL, "CVSLS", "CVKLUSetup", 
			 MSGSP_PACKAGE_FAIL);
	  return(CVSLS_PACKAGE_FAIL);
	}
      }
    }
  }

  cvsls_mem->s_last_flag = CVSLS_SUCCESS;
  
  return(0);
}