Actual source code: ex9.c
1: static char help[] = "Solves DAE with integrator only on non-algebraic terms \n";
3: #include <petscts.h>
5: /*
6: \dot{U} = f(U,V)
7: F(U,V) = 0
9: Same as ex6.c and ex7.c except calls the ARKIMEX integrator on the entire DAE
10: */
12: /*
13: f(U,V) = U + V
15: */
16: PetscErrorCode f(PetscReal t, Vec U, Vec V, Vec F)
17: {
18: PetscFunctionBeginUser;
19: PetscCall(VecWAXPY(F, 1.0, U, V));
20: PetscFunctionReturn(PETSC_SUCCESS);
21: }
23: /*
24: F(U,V) = U - V
26: */
27: PetscErrorCode F(PetscReal t, Vec U, Vec V, Vec F)
28: {
29: PetscFunctionBeginUser;
30: PetscCall(VecWAXPY(F, -1.0, V, U));
31: PetscFunctionReturn(PETSC_SUCCESS);
32: }
34: typedef struct {
35: Vec U, V;
36: Vec UF, VF;
37: VecScatter scatterU, scatterV;
38: PetscErrorCode (*f)(PetscReal, Vec, Vec, Vec);
39: PetscErrorCode (*F)(PetscReal, Vec, Vec, Vec);
40: } AppCtx;
42: extern PetscErrorCode TSFunctionRHS(TS, PetscReal, Vec, Vec, void *);
43: extern PetscErrorCode TSFunctionI(TS, PetscReal, Vec, Vec, Vec, void *);
45: int main(int argc, char **argv)
46: {
47: AppCtx ctx;
48: TS ts;
49: Vec tsrhs, UV;
50: IS is;
51: PetscInt I;
52: PetscMPIInt rank;
54: PetscFunctionBeginUser;
55: PetscCall(PetscInitialize(&argc, &argv, NULL, help));
56: PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
57: PetscCall(TSCreate(PETSC_COMM_WORLD, &ts));
58: PetscCall(TSSetProblemType(ts, TS_NONLINEAR));
59: PetscCall(TSSetType(ts, TSROSW));
60: PetscCall(TSSetFromOptions(ts));
61: PetscCall(VecCreateMPI(PETSC_COMM_WORLD, 2, PETSC_DETERMINE, &tsrhs));
62: PetscCall(VecCreateMPI(PETSC_COMM_WORLD, 2, PETSC_DETERMINE, &UV));
63: PetscCall(TSSetRHSFunction(ts, tsrhs, TSFunctionRHS, &ctx));
64: PetscCall(TSSetIFunction(ts, NULL, TSFunctionI, &ctx));
65: ctx.f = f;
66: ctx.F = F;
68: PetscCall(VecCreateMPI(PETSC_COMM_WORLD, 1, PETSC_DETERMINE, &ctx.U));
69: PetscCall(VecCreateMPI(PETSC_COMM_WORLD, 1, PETSC_DETERMINE, &ctx.V));
70: PetscCall(VecCreateMPI(PETSC_COMM_WORLD, 1, PETSC_DETERMINE, &ctx.UF));
71: PetscCall(VecCreateMPI(PETSC_COMM_WORLD, 1, PETSC_DETERMINE, &ctx.VF));
72: I = 2 * rank;
73: PetscCall(ISCreateGeneral(PETSC_COMM_WORLD, 1, &I, PETSC_COPY_VALUES, &is));
74: PetscCall(VecScatterCreate(ctx.U, NULL, UV, is, &ctx.scatterU));
75: PetscCall(ISDestroy(&is));
76: I = 2 * rank + 1;
77: PetscCall(ISCreateGeneral(PETSC_COMM_WORLD, 1, &I, PETSC_COPY_VALUES, &is));
78: PetscCall(VecScatterCreate(ctx.V, NULL, UV, is, &ctx.scatterV));
79: PetscCall(ISDestroy(&is));
81: PetscCall(VecSet(UV, 1.0));
82: PetscCall(TSSolve(ts, UV));
83: PetscCall(VecDestroy(&tsrhs));
84: PetscCall(VecDestroy(&UV));
85: PetscCall(VecDestroy(&ctx.U));
86: PetscCall(VecDestroy(&ctx.V));
87: PetscCall(VecDestroy(&ctx.UF));
88: PetscCall(VecDestroy(&ctx.VF));
89: PetscCall(VecScatterDestroy(&ctx.scatterU));
90: PetscCall(VecScatterDestroy(&ctx.scatterV));
91: PetscCall(TSDestroy(&ts));
92: PetscCall(PetscFinalize());
93: return 0;
94: }
96: /*
97: Defines the RHS function that is passed to the time-integrator.
99: */
100: PetscErrorCode TSFunctionRHS(TS ts, PetscReal t, Vec UV, Vec F, void *actx)
101: {
102: AppCtx *ctx = (AppCtx *)actx;
104: PetscFunctionBeginUser;
105: PetscCall(VecSet(F, 0.0));
106: PetscCall(VecScatterBegin(ctx->scatterU, UV, ctx->U, INSERT_VALUES, SCATTER_REVERSE));
107: PetscCall(VecScatterEnd(ctx->scatterU, UV, ctx->U, INSERT_VALUES, SCATTER_REVERSE));
108: PetscCall(VecScatterBegin(ctx->scatterV, UV, ctx->V, INSERT_VALUES, SCATTER_REVERSE));
109: PetscCall(VecScatterEnd(ctx->scatterV, UV, ctx->V, INSERT_VALUES, SCATTER_REVERSE));
110: PetscCall((*ctx->f)(t, ctx->U, ctx->V, ctx->UF));
111: PetscCall(VecScatterBegin(ctx->scatterU, ctx->UF, F, INSERT_VALUES, SCATTER_FORWARD));
112: PetscCall(VecScatterEnd(ctx->scatterU, ctx->UF, F, INSERT_VALUES, SCATTER_FORWARD));
113: PetscFunctionReturn(PETSC_SUCCESS);
114: }
116: /*
117: Defines the nonlinear function that is passed to the time-integrator
119: */
120: PetscErrorCode TSFunctionI(TS ts, PetscReal t, Vec UV, Vec UVdot, Vec F, void *actx)
121: {
122: AppCtx *ctx = (AppCtx *)actx;
124: PetscFunctionBeginUser;
125: PetscCall(VecCopy(UVdot, F));
126: PetscCall(VecScatterBegin(ctx->scatterU, UV, ctx->U, INSERT_VALUES, SCATTER_REVERSE));
127: PetscCall(VecScatterEnd(ctx->scatterU, UV, ctx->U, INSERT_VALUES, SCATTER_REVERSE));
128: PetscCall(VecScatterBegin(ctx->scatterV, UV, ctx->V, INSERT_VALUES, SCATTER_REVERSE));
129: PetscCall(VecScatterEnd(ctx->scatterV, UV, ctx->V, INSERT_VALUES, SCATTER_REVERSE));
130: PetscCall((*ctx->F)(t, ctx->U, ctx->V, ctx->VF));
131: PetscCall(VecScatterBegin(ctx->scatterV, ctx->VF, F, INSERT_VALUES, SCATTER_FORWARD));
132: PetscCall(VecScatterEnd(ctx->scatterV, ctx->VF, F, INSERT_VALUES, SCATTER_FORWARD));
133: PetscFunctionReturn(PETSC_SUCCESS);
134: }