xref: /petsc/src/ts/impls/implicit/radau5/radau5.c (revision 4dfa11a44d5adf2389f1d3acbc8f3c1116dc6c3a)
1d249a78fSBarry Smith /*
2d249a78fSBarry Smith     Provides a PETSc interface to RADAU5 solver.
3d249a78fSBarry Smith 
4d249a78fSBarry Smith */
5d249a78fSBarry Smith #include <petsc/private/tsimpl.h> /*I   "petscts.h"   I*/
6d249a78fSBarry Smith 
7d249a78fSBarry Smith typedef struct {
86ffeb343SBarry Smith   Vec work, workf;
9d249a78fSBarry Smith } TS_Radau5;
10d249a78fSBarry Smith 
119371c9d4SSatish Balay void FVPOL(int *N, double *X, double *Y, double *F, double *RPAR, void *IPAR) {
126ffeb343SBarry Smith   TS          ts    = (TS)IPAR;
136ffeb343SBarry Smith   TS_Radau5  *cvode = (TS_Radau5 *)ts->data;
146ffeb343SBarry Smith   DM          dm;
156ffeb343SBarry Smith   DMTS        tsdm;
166ffeb343SBarry Smith   TSIFunction ifunction;
176ffeb343SBarry Smith 
189566063dSJacob Faibussowitsch   PetscCallAbort(PETSC_COMM_SELF, VecPlaceArray(cvode->work, Y));
199566063dSJacob Faibussowitsch   PetscCallAbort(PETSC_COMM_SELF, VecPlaceArray(cvode->workf, F));
206ffeb343SBarry Smith 
216ffeb343SBarry Smith   /* Now compute the right hand side function, via IFunction unless only the more efficient RHSFunction is set */
229566063dSJacob Faibussowitsch   PetscCallAbort(PETSC_COMM_SELF, TSGetDM(ts, &dm));
239566063dSJacob Faibussowitsch   PetscCallAbort(PETSC_COMM_SELF, DMGetDMTS(dm, &tsdm));
249566063dSJacob Faibussowitsch   PetscCallAbort(PETSC_COMM_SELF, DMTSGetIFunction(dm, &ifunction, NULL));
256ffeb343SBarry Smith   if (!ifunction) {
269566063dSJacob Faibussowitsch     PetscCallAbort(PETSC_COMM_SELF, TSComputeRHSFunction(ts, *X, cvode->work, cvode->workf));
27e68ccae8SBarry Smith   } else { /* If rhsfunction is also set, this computes both parts and scale them to the right hand side */
286ffeb343SBarry Smith     Vec yydot;
296ffeb343SBarry Smith 
309566063dSJacob Faibussowitsch     PetscCallAbort(PETSC_COMM_SELF, VecDuplicate(cvode->work, &yydot));
319566063dSJacob Faibussowitsch     PetscCallAbort(PETSC_COMM_SELF, VecZeroEntries(yydot));
329566063dSJacob Faibussowitsch     PetscCallAbort(PETSC_COMM_SELF, TSComputeIFunction(ts, *X, cvode->work, yydot, cvode->workf, PETSC_FALSE));
339566063dSJacob Faibussowitsch     PetscCallAbort(PETSC_COMM_SELF, VecScale(cvode->workf, -1.));
349566063dSJacob Faibussowitsch     PetscCallAbort(PETSC_COMM_SELF, VecDestroy(&yydot));
356ffeb343SBarry Smith   }
366ffeb343SBarry Smith 
379566063dSJacob Faibussowitsch   PetscCallAbort(PETSC_COMM_SELF, VecResetArray(cvode->work));
389566063dSJacob Faibussowitsch   PetscCallAbort(PETSC_COMM_SELF, VecResetArray(cvode->workf));
396ffeb343SBarry Smith }
406ffeb343SBarry Smith 
419371c9d4SSatish Balay void JVPOL(PetscInt *N, PetscScalar *X, PetscScalar *Y, PetscScalar *DFY, int *LDFY, PetscScalar *RPAR, void *IPAR) {
428acf3572SBarry Smith   TS         ts    = (TS)IPAR;
438acf3572SBarry Smith   TS_Radau5 *cvode = (TS_Radau5 *)ts->data;
448acf3572SBarry Smith   Vec        yydot;
458acf3572SBarry Smith   Mat        mat;
468acf3572SBarry Smith   PetscInt   n;
47d249a78fSBarry Smith 
489566063dSJacob Faibussowitsch   PetscCallAbort(PETSC_COMM_SELF, VecPlaceArray(cvode->work, Y));
499566063dSJacob Faibussowitsch   PetscCallAbort(PETSC_COMM_SELF, VecDuplicate(cvode->work, &yydot));
509566063dSJacob Faibussowitsch   PetscCallAbort(PETSC_COMM_SELF, VecGetSize(yydot, &n));
519566063dSJacob Faibussowitsch   PetscCallAbort(PETSC_COMM_SELF, MatCreateSeqDense(PETSC_COMM_SELF, n, n, DFY, &mat));
529566063dSJacob Faibussowitsch   PetscCallAbort(PETSC_COMM_SELF, VecZeroEntries(yydot));
539566063dSJacob Faibussowitsch   PetscCallAbort(PETSC_COMM_SELF, TSComputeIJacobian(ts, *X, cvode->work, yydot, 0, mat, mat, PETSC_FALSE));
549566063dSJacob Faibussowitsch   PetscCallAbort(PETSC_COMM_SELF, MatScale(mat, -1.0));
559566063dSJacob Faibussowitsch   PetscCallAbort(PETSC_COMM_SELF, MatDestroy(&mat));
569566063dSJacob Faibussowitsch   PetscCallAbort(PETSC_COMM_SELF, VecDestroy(&yydot));
579566063dSJacob Faibussowitsch   PetscCallAbort(PETSC_COMM_SELF, VecResetArray(cvode->work));
588acf3572SBarry Smith }
598acf3572SBarry Smith 
609371c9d4SSatish Balay void SOLOUT(int *NR, double *XOLD, double *X, double *Y, double *CONT, double *LRC, int *N, double *RPAR, void *IPAR, int *IRTRN) {
61d249a78fSBarry Smith   TS         ts    = (TS)IPAR;
62d249a78fSBarry Smith   TS_Radau5 *cvode = (TS_Radau5 *)ts->data;
63d249a78fSBarry Smith 
649566063dSJacob Faibussowitsch   PetscCallAbort(PETSC_COMM_SELF, VecPlaceArray(cvode->work, Y));
65d249a78fSBarry Smith   ts->time_step = *X - *XOLD;
669566063dSJacob Faibussowitsch   PetscCallAbort(PETSC_COMM_SELF, TSMonitor(ts, *NR - 1, *X, cvode->work));
679566063dSJacob Faibussowitsch   PetscCallAbort(PETSC_COMM_SELF, VecResetArray(cvode->work));
68d249a78fSBarry Smith }
69d249a78fSBarry Smith 
70d249a78fSBarry Smith 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 *);
71d249a78fSBarry Smith 
729371c9d4SSatish Balay PetscErrorCode TSSolve_Radau5(TS ts) {
73d249a78fSBarry Smith   TS_Radau5   *cvode = (TS_Radau5 *)ts->data;
74d249a78fSBarry Smith   PetscScalar *Y, *WORK, X, XEND, RTOL, ATOL, H, RPAR;
75d249a78fSBarry Smith   PetscInt     ND, *IWORK, LWORK, LIWORK, MUJAC, MLMAS, MUMAS, IDID, ITOL;
76d249a78fSBarry Smith   int          IJAC, MLJAC, IMAS, IOUT;
77d249a78fSBarry Smith 
78d249a78fSBarry Smith   PetscFunctionBegin;
799566063dSJacob Faibussowitsch   PetscCall(VecGetArray(ts->vec_sol, &Y));
809566063dSJacob Faibussowitsch   PetscCall(VecGetSize(ts->vec_sol, &ND));
819566063dSJacob Faibussowitsch   PetscCall(VecCreateSeqWithArray(PETSC_COMM_SELF, 1, ND, NULL, &cvode->work));
829566063dSJacob Faibussowitsch   PetscCall(VecCreateSeqWithArray(PETSC_COMM_SELF, 1, ND, NULL, &cvode->workf));
83d249a78fSBarry Smith 
84d249a78fSBarry Smith   LWORK  = 4 * ND * ND + 12 * ND + 20;
85d249a78fSBarry Smith   LIWORK = 3 * ND + 20;
86d249a78fSBarry Smith 
879566063dSJacob Faibussowitsch   PetscCall(PetscCalloc2(LWORK, &WORK, LIWORK, &IWORK));
88d249a78fSBarry Smith 
89d249a78fSBarry Smith   /* C --- PARAMETER IN THE DIFFERENTIAL EQUATION */
90d249a78fSBarry Smith   RPAR  = 1.0e-6;
91d249a78fSBarry Smith   /* C --- COMPUTE THE JACOBIAN ANALYTICALLY */
92d249a78fSBarry Smith   IJAC  = 1;
93d249a78fSBarry Smith   /* C --- JACOBIAN IS A FULL MATRIX */
94d249a78fSBarry Smith   MLJAC = ND;
95d249a78fSBarry Smith   /* C --- DIFFERENTIAL EQUATION IS IN EXPLICIT FORM*/
96d249a78fSBarry Smith   IMAS  = 0;
97d249a78fSBarry Smith   /* C --- OUTPUT ROUTINE IS USED DURING INTEGRATION*/
98d249a78fSBarry Smith   IOUT  = 1;
99d249a78fSBarry Smith   /* C --- INITIAL VALUES*/
100d249a78fSBarry Smith   X     = ts->ptime;
101d249a78fSBarry Smith   /* C --- ENDPOINT OF INTEGRATION */
102d249a78fSBarry Smith   XEND  = ts->max_time;
103d249a78fSBarry Smith   /* C --- REQUIRED TOLERANCE */
1046ffeb343SBarry Smith   RTOL  = ts->rtol;
1056ffeb343SBarry Smith   ATOL  = ts->atol;
106d249a78fSBarry Smith   ITOL  = 0;
107d249a78fSBarry Smith   /* C --- INITIAL STEP SIZE */
10869a506b1SBarry Smith   H     = ts->time_step;
109d249a78fSBarry Smith 
110e68ccae8SBarry Smith   /* output MUJAC MLMAS IDID; currently all ignored */
111d249a78fSBarry Smith 
112d249a78fSBarry Smith   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);
113d249a78fSBarry Smith 
1149566063dSJacob Faibussowitsch   PetscCall(PetscFree2(WORK, IWORK));
115d249a78fSBarry Smith   PetscFunctionReturn(0);
116d249a78fSBarry Smith }
117d249a78fSBarry Smith 
1189371c9d4SSatish Balay PetscErrorCode TSDestroy_Radau5(TS ts) {
119d249a78fSBarry Smith   TS_Radau5 *cvode = (TS_Radau5 *)ts->data;
120d249a78fSBarry Smith 
121d249a78fSBarry Smith   PetscFunctionBegin;
1229566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&cvode->work));
1239566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&cvode->workf));
1249566063dSJacob Faibussowitsch   PetscCall(PetscFree(ts->data));
125d249a78fSBarry Smith   PetscFunctionReturn(0);
126d249a78fSBarry Smith }
127d249a78fSBarry Smith 
128d249a78fSBarry Smith /*MC
129d249a78fSBarry Smith       TSRADAU5 - ODE solver using the RADAU5 package
130d249a78fSBarry Smith 
13195452b02SPatrick Sanan     Notes:
13295452b02SPatrick Sanan     This uses its own nonlinear solver and dense matrix direct solver so PETSc SNES and KSP options do not apply.
133e68ccae8SBarry Smith            Uses its own time-step adaptivity (but uses the TS rtol and atol, and initial timestep)
134e68ccae8SBarry Smith            Uses its own memory for the dense matrix storage and factorization
135e68ccae8SBarry Smith            Can only handle ODEs of the form \cdot{u} = -F(t,u) + G(t,u)
136d249a78fSBarry Smith 
137d249a78fSBarry Smith     Level: beginner
138d249a78fSBarry Smith 
139db781477SPatrick Sanan .seealso: `TSCreate()`, `TS`, `TSSetType()`
140d249a78fSBarry Smith 
141d249a78fSBarry Smith M*/
1429371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode TSCreate_Radau5(TS ts) {
143d249a78fSBarry Smith   TS_Radau5 *cvode;
144d249a78fSBarry Smith 
145d249a78fSBarry Smith   PetscFunctionBegin;
146d249a78fSBarry Smith   ts->ops->destroy       = TSDestroy_Radau5;
147d249a78fSBarry Smith   ts->ops->solve         = TSSolve_Radau5;
148d249a78fSBarry Smith   ts->default_adapt_type = TSADAPTNONE;
149d249a78fSBarry Smith 
150*4dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&cvode));
151d249a78fSBarry Smith   ts->data = (void *)cvode;
152d249a78fSBarry Smith   PetscFunctionReturn(0);
153d249a78fSBarry Smith }
154