Date: 2022-08-02T03:15:01+00:00

Actual source code: radau5.c

      1: /*
      2:     Provides a PETSc interface to RADAU5 solver.

      4: */
      5: #include <petsc/private/tsimpl.h>

      7: typedef struct {
      8:   Vec work,workf;
      9: } TS_Radau5;

     11: void FVPOL(int *N,double *X,double *Y,double *F,double *RPAR,void *IPAR)
     12: {
     13:   TS             ts = (TS) IPAR;
     14:   TS_Radau5      *cvode = (TS_Radau5*)ts->data;
     15:   DM             dm;
     16:   DMTS           tsdm;
     17:   TSIFunction    ifunction;

     19:   PETSC_COMM_SELF,VecPlaceArray(cvode->work,Y);
     20:   PETSC_COMM_SELF,VecPlaceArray(cvode->workf,F);

     22:   /* Now compute the right hand side function, via IFunction unless only the more efficient RHSFunction is set */
     23:   PETSC_COMM_SELF,TSGetDM(ts,&dm);
     24:   PETSC_COMM_SELF,DMGetDMTS(dm,&tsdm);
     25:   PETSC_COMM_SELF,DMTSGetIFunction(dm,&ifunction,NULL);
     26:   if (!ifunction) {
     27:     PETSC_COMM_SELF,TSComputeRHSFunction(ts,*X,cvode->work,cvode->workf);
     28:   } else {       /* If rhsfunction is also set, this computes both parts and scale them to the right hand side */
     29:     Vec yydot;

     31:     PETSC_COMM_SELF,VecDuplicate(cvode->work,&yydot);
     32:     PETSC_COMM_SELF,VecZeroEntries(yydot);
     33:     PETSC_COMM_SELF,TSComputeIFunction(ts,*X,cvode->work,yydot,cvode->workf,PETSC_FALSE);
     34:     PETSC_COMM_SELF,VecScale(cvode->workf,-1.);
     35:     PETSC_COMM_SELF,VecDestroy(&yydot);
     36:   }

     38:   PETSC_COMM_SELF,VecResetArray(cvode->work);
     39:   PETSC_COMM_SELF,VecResetArray(cvode->workf);
     40: }

     42: void JVPOL(PetscInt *N,PetscScalar *X,PetscScalar *Y,PetscScalar *DFY,int *LDFY,PetscScalar *RPAR,void *IPAR)
     43: {
     44:   TS             ts = (TS) IPAR;
     45:   TS_Radau5      *cvode = (TS_Radau5*)ts->data;
     46:   Vec            yydot;
     47:   Mat            mat;
     48:   PetscInt       n;

     50:   PETSC_COMM_SELF,VecPlaceArray(cvode->work,Y);
     51:   PETSC_COMM_SELF,VecDuplicate(cvode->work,&yydot);
     52:   PETSC_COMM_SELF,VecGetSize(yydot,&n);
     53:   PETSC_COMM_SELF,MatCreateSeqDense(PETSC_COMM_SELF,n,n,DFY,&mat);
     54:   PETSC_COMM_SELF,VecZeroEntries(yydot);
     55:   PETSC_COMM_SELF,TSComputeIJacobian(ts,*X,cvode->work,yydot,0,mat,mat,PETSC_FALSE);
     56:   PETSC_COMM_SELF,MatScale(mat,-1.0);
     57:   PETSC_COMM_SELF,MatDestroy(&mat);
     58:   PETSC_COMM_SELF,VecDestroy(&yydot);
     59:   PETSC_COMM_SELF,VecResetArray(cvode->work);
     60: }

     62: void SOLOUT(int *NR,double *XOLD,double *X, double *Y,double *CONT,double *LRC,int *N,double *RPAR,void *IPAR,int *IRTRN)
     63: {
     64:   TS             ts = (TS) IPAR;
     65:   TS_Radau5      *cvode = (TS_Radau5*)ts->data;

     67:   PETSC_COMM_SELF,VecPlaceArray(cvode->work,Y);
     68:   ts->time_step = *X - *XOLD;
     69:   PETSC_COMM_SELF,TSMonitor(ts,*NR-1,*X,cvode->work);
     70:   PETSC_COMM_SELF,VecResetArray(cvode->work);
     71: }

     73: void radau5_(int *,void*,double*,double*,double*,double*,double*,double*,int*,void*,int*,int*,int*,void*,int*,int*,int*,void*,int*,double*,int*,int*,int*,double*,void*,int*);

     75: PetscErrorCode TSSolve_Radau5(TS ts)
     76: {
     77:   TS_Radau5      *cvode = (TS_Radau5*)ts->data;
     78:   PetscScalar    *Y,*WORK,X,XEND,RTOL,ATOL,H,RPAR;
     79:   PetscInt       ND,*IWORK,LWORK,LIWORK,MUJAC,MLMAS,MUMAS,IDID,ITOL;
     80:   int            IJAC,MLJAC,IMAS,IOUT;

     82:   VecGetArray(ts->vec_sol,&Y);
     83:   VecGetSize(ts->vec_sol,&ND);
     84:   VecCreateSeqWithArray(PETSC_COMM_SELF,1,ND,NULL,&cvode->work);
     85:   VecCreateSeqWithArray(PETSC_COMM_SELF,1,ND,NULL,&cvode->workf);

     87:   LWORK  = 4*ND*ND+12*ND+20;
     88:   LIWORK = 3*ND+20;

     90:   PetscCalloc2(LWORK,&WORK,LIWORK,&IWORK);

     92:   /* C --- PARAMETER IN THE DIFFERENTIAL EQUATION */
     93:   RPAR=1.0e-6;
     94:   /* C --- COMPUTE THE JACOBIAN ANALYTICALLY */
     95:   IJAC=1;
     96:   /* C --- JACOBIAN IS A FULL MATRIX */
     97:   MLJAC=ND;
     98:   /* C --- DIFFERENTIAL EQUATION IS IN EXPLICIT FORM*/
     99:   IMAS=0;
    100:   /* C --- OUTPUT ROUTINE IS USED DURING INTEGRATION*/
    101:   IOUT=1;
    102:   /* C --- INITIAL VALUES*/
    103:   X = ts->ptime;
    104:   /* C --- ENDPOINT OF INTEGRATION */
    105:   XEND = ts->max_time;
    106:   /* C --- REQUIRED TOLERANCE */
    107:   RTOL = ts->rtol;
    108:   ATOL = ts->atol;
    109:   ITOL=0;
    110:   /* C --- INITIAL STEP SIZE */
    111:   H = ts->time_step;

    113:   /* output MUJAC MLMAS IDID; currently all ignored */

    115:   radau5_(&ND,FVPOL,&X,Y,&XEND,&H,&RTOL,&ATOL,&ITOL,JVPOL,&IJAC,&MLJAC,&MUJAC,FVPOL,&IMAS,&MLMAS,&MUMAS,SOLOUT,&IOUT,WORK,&LWORK,IWORK,&LIWORK,&RPAR,(void*)ts,&IDID);

    117:   PetscFree2(WORK,IWORK);
    118:   return 0;
    119: }

    121: PetscErrorCode TSDestroy_Radau5(TS ts)
    122: {
    123:   TS_Radau5      *cvode = (TS_Radau5*)ts->data;

    125:   VecDestroy(&cvode->work);
    126:   VecDestroy(&cvode->workf);
    127:   PetscFree(ts->data);
    128:   return 0;
    129: }

    131: /*MC
    132:       TSRADAU5 - ODE solver using the RADAU5 package

    134:     Notes:
    135:     This uses its own nonlinear solver and dense matrix direct solver so PETSc SNES and KSP options do not apply.
    136:            Uses its own time-step adaptivity (but uses the TS rtol and atol, and initial timestep)
    137:            Uses its own memory for the dense matrix storage and factorization
    138:            Can only handle ODEs of the form \cdot{u} = -F(t,u) + G(t,u)

    140:     Level: beginner

    142: .seealso:  TSCreate(), TS, TSSetType()

    144: M*/
    145: PETSC_EXTERN PetscErrorCode TSCreate_Radau5(TS ts)
    146: {
    147:   TS_Radau5      *cvode;

    149:   ts->ops->destroy        = TSDestroy_Radau5;
    150:   ts->ops->solve          = TSSolve_Radau5;
    151:   ts->default_adapt_type  = TSADAPTNONE;

    153:   PetscNewLog(ts,&cvode);
    154:   ts->data = (void*)cvode;
    155:   return 0;
    156: }