コード例 #1
0
ファイル: cvode_ls.c プロジェクト: NumCosmo/NumCosmo
/*-----------------------------------------------------------------
  cvLsSetup

  This conditionally calls the LS 'setup' routine.

  When using a SUNMatrix object, this determines whether
  to update a Jacobian matrix (or use a stored version), based
  on heuristics regarding previous convergence issues, the number
  of time steps since it was last updated, etc.; it then creates
  the system matrix from this, the 'gamma' factor and the
  identity matrix, A = I-gamma*J.

  This routine then calls the LS 'setup' routine with A.
  -----------------------------------------------------------------*/
int cvLsSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
              N_Vector fpred, booleantype *jcurPtr,
              N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3)
{
  CVLsMem  cvls_mem;
  realtype dgamma;
  int      retval;

  /* access CVLsMem structure */
  if (cv_mem->cv_lmem==NULL) {
    cvProcessError(cv_mem, CVLS_LMEM_NULL, "CVLS",
                   "cvLsSetup", MSG_LS_LMEM_NULL);
    return(CVLS_LMEM_NULL);
  }
  cvls_mem = (CVLsMem) cv_mem->cv_lmem;

  /* Set CVLs N_Vector pointers to current solution and rhs */
  cvls_mem->ycur = ypred;
  cvls_mem->fcur = fpred;

  /* Use nst, gamma/gammap, and convfail to set J/P eval. flag jok */
  dgamma = SUNRabs((cv_mem->cv_gamma/cv_mem->cv_gammap) - ONE);
  cvls_mem->jbad = (cv_mem->cv_nst == 0) ||
    (cv_mem->cv_nst > cvls_mem->nstlj + cvls_mem->msbj) ||
    ((convfail == CV_FAIL_BAD_J) && (dgamma < CVLS_DGMAX)) ||
    (convfail == CV_FAIL_OTHER);

  /* If using a NULL SUNMatrix, set jcur to jbad; otherwise update J as appropriate */
  if (cvls_mem->A == NULL) {

    *jcurPtr = cvls_mem->jbad;

  } else {

    /* If jbad = SUNFALSE, use saved copy of J */
    if (!cvls_mem->jbad) {

      *jcurPtr = SUNFALSE;
      retval = SUNMatCopy(cvls_mem->savedJ, cvls_mem->A);
      if (retval) {
        cvProcessError(cv_mem, CVLS_SUNMAT_FAIL, "CVLS",
                       "cvLsSetup",  MSG_LS_SUNMAT_FAILED);
        cvls_mem->last_flag = CVLS_SUNMAT_FAIL;
        return(cvls_mem->last_flag);
      }

    /* If jbad = SUNTRUE, call jac routine for new J value */
    } else {

      cvls_mem->nje++;
      cvls_mem->nstlj = cv_mem->cv_nst;
      *jcurPtr = SUNTRUE;
      retval = SUNMatZero(cvls_mem->A);
      if (retval) {
        cvProcessError(cv_mem, CVLS_SUNMAT_FAIL, "CVLS",
                       "cvLsSetup",  MSG_LS_SUNMAT_FAILED);
        cvls_mem->last_flag = CVLS_SUNMAT_FAIL;
        return(cvls_mem->last_flag);
      }

      retval = cvls_mem->jac(cv_mem->cv_tn, ypred, fpred, cvls_mem->A,
                             cvls_mem->J_data, vtemp1, vtemp2, vtemp3);
      if (retval < 0) {
        cvProcessError(cv_mem, CVLS_JACFUNC_UNRECVR, "CVLS",
                       "cvLsSetup",  MSG_LS_JACFUNC_FAILED);
        cvls_mem->last_flag = CVLS_JACFUNC_UNRECVR;
        return(-1);
      }
      if (retval > 0) {
        cvls_mem->last_flag = CVLS_JACFUNC_RECVR;
        return(1);
      }

      retval = SUNMatCopy(cvls_mem->A, cvls_mem->savedJ);
      if (retval) {
        cvProcessError(cv_mem, CVLS_SUNMAT_FAIL, "CVLS",
                       "cvLsSetup",  MSG_LS_SUNMAT_FAILED);
        cvls_mem->last_flag = CVLS_SUNMAT_FAIL;
        return(cvls_mem->last_flag);
      }

    }

    /* Scale and add I to get A = I - gamma*J */
    retval = SUNMatScaleAddI(-cv_mem->cv_gamma, cvls_mem->A);
    if (retval) {
      cvProcessError(cv_mem, CVLS_SUNMAT_FAIL, "CVLS",
                     "cvLsSetup",  MSG_LS_SUNMAT_FAILED);
      cvls_mem->last_flag = CVLS_SUNMAT_FAIL;
      return(cvls_mem->last_flag);
    }

  }

  /* Call LS setup routine -- the LS may call cvLsPSetup, who will
     pass the heuristic suggestions above to the user code(s) */
  cvls_mem->last_flag = SUNLinSolSetup(cvls_mem->LS, cvls_mem->A);

  /* If the SUNMatrix was NULL, update heuristics flags */
  if (cvls_mem->A == NULL) {

    /* If user set jcur to SUNTRUE, increment npe and save nst value */
    if (*jcurPtr) {
      cvls_mem->npe++;
      cvls_mem->nstlj = cv_mem->cv_nst;
    }

    /* Update jcur flag if we suggested an update */
    if (cvls_mem->jbad) *jcurPtr = SUNTRUE;
  }

  return(cvls_mem->last_flag);
}
コード例 #2
0
ファイル: cvode_direct.c プロジェクト: sn248/Rcppsbmod
/*-----------------------------------------------------------------
  cvDlsSetup
  -----------------------------------------------------------------
  This routine determines whether to update a Jacobian matrix (or
  use a stored version), based on heuristics regarding previous 
  convergence issues, the number of time steps since it was last
  updated, etc.; it then creates the system matrix from this, the
  'gamma' factor and the identity matrix, 
    A = I-gamma*J.
  This routine then calls the LS 'setup' routine with A.
  -----------------------------------------------------------------*/
int cvDlsSetup(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;
  realtype dgamma;
  CVDlsMem cvdls_mem;
  int retval;

  /* Return immediately if cv_mem or cv_mem->cv_lmem are NULL */
  if (cv_mem == NULL) {
    cvProcessError(NULL, CVDLS_MEM_NULL, "CVDLS", 
                    "cvDlsSetup", MSGD_CVMEM_NULL);
    return(CVDLS_MEM_NULL);
  }
  if (cv_mem->cv_lmem == NULL) {
    cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVDLS", 
                    "cvDlsSetup", MSGD_LMEM_NULL);
    return(CVDLS_LMEM_NULL);
  }
  cvdls_mem = (CVDlsMem) cv_mem->cv_lmem;

  /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */
  dgamma = SUNRabs((cv_mem->cv_gamma/cv_mem->cv_gammap) - ONE);
  jbad = (cv_mem->cv_nst == 0) || 
    (cv_mem->cv_nst > cvdls_mem->nstlj + CVD_MSBJ) ||
    ((convfail == CV_FAIL_BAD_J) && (dgamma < CVD_DGMAX)) ||
    (convfail == CV_FAIL_OTHER);
  jok = !jbad;
 
  /* If jok = SUNTRUE, use saved copy of J */
  if (jok) {
    *jcurPtr = SUNFALSE;
    retval = SUNMatCopy(cvdls_mem->savedJ, cvdls_mem->A);
    if (retval) {
      cvProcessError(cv_mem, CVDLS_SUNMAT_FAIL, "CVDLS", 
                      "cvDlsSetup",  MSGD_MATCOPY_FAILED);
      cvdls_mem->last_flag = CVDLS_SUNMAT_FAIL;
      return(-1);
    }

  /* If jok = SUNFALSE, call jac routine for new J value */
  } else {
    cvdls_mem->nje++;
    cvdls_mem->nstlj = cv_mem->cv_nst;
    *jcurPtr = SUNTRUE;
    retval = SUNMatZero(cvdls_mem->A);
    if (retval) {
      cvProcessError(cv_mem, CVDLS_SUNMAT_FAIL, "CVDLS", 
                      "cvDlsSetup",  MSGD_MATZERO_FAILED);
      cvdls_mem->last_flag = CVDLS_SUNMAT_FAIL;
      return(-1);
    }

    retval = cvdls_mem->jac(cv_mem->cv_tn, ypred, 
                            fpred, cvdls_mem->A, 
                            cvdls_mem->J_data, vtemp1, vtemp2, vtemp3);
    if (retval < 0) {
      cvProcessError(cv_mem, CVDLS_JACFUNC_UNRECVR, "CVDLS", 
                      "cvDlsSetup",  MSGD_JACFUNC_FAILED);
      cvdls_mem->last_flag = CVDLS_JACFUNC_UNRECVR;
      return(-1);
    }
    if (retval > 0) {
      cvdls_mem->last_flag = CVDLS_JACFUNC_RECVR;
      return(1);
    }

    retval = SUNMatCopy(cvdls_mem->A, cvdls_mem->savedJ);
    if (retval) {
      cvProcessError(cv_mem, CVDLS_SUNMAT_FAIL, "CVDLS", 
                      "cvDlsSetup",  MSGD_MATCOPY_FAILED);
      cvdls_mem->last_flag = CVDLS_SUNMAT_FAIL;
      return(-1);
    }

  }
  
  /* Scale and add I to get A = I - gamma*J */
  retval = SUNMatScaleAddI(-cv_mem->cv_gamma, cvdls_mem->A);
  if (retval) {
    cvProcessError(cv_mem, CVDLS_SUNMAT_FAIL, "CVDLS", 
                   "cvDlsSetup",  MSGD_MATSCALEADDI_FAILED);
    cvdls_mem->last_flag = CVDLS_SUNMAT_FAIL;
    return(-1);
  }

  /* Call generic linear solver 'setup' with this system matrix, and
     return success/failure flag */
  cvdls_mem->last_flag = SUNLinSolSetup(cvdls_mem->LS, cvdls_mem->A);
  return(cvdls_mem->last_flag);
}