Actual source code: ex7.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 except the user provided functions take input values as a single vector instead of two vectors
10: */
12: /*
13: f(U,V) = U + V
15: */
16: PetscErrorCode f(PetscReal t, Vec UV, Vec F)
17: {
18: const PetscScalar *u, *v;
19: PetscScalar *f;
20: PetscInt n, i;
22: PetscFunctionBeginUser;
23: PetscCall(VecGetLocalSize(UV, &n));
24: n = n / 2;
25: PetscCall(VecGetArrayRead(UV, &u));
26: v = u + n;
27: PetscCall(VecGetArrayWrite(F, &f));
28: for (i = 0; i < n; i++) f[i] = u[i] + v[i];
29: PetscCall(VecRestoreArrayRead(UV, &u));
30: PetscCall(VecRestoreArrayWrite(F, &f));
31: PetscFunctionReturn(PETSC_SUCCESS);
32: }
34: /*
35: F(U,V) = U - V
36: */
37: PetscErrorCode F(PetscReal t, Vec UV, Vec F)
38: {
39: const PetscScalar *u, *v;
40: PetscScalar *f;
41: PetscInt n, i;
43: PetscFunctionBeginUser;
44: PetscCall(VecGetLocalSize(UV, &n));
45: n = n / 2;
46: PetscCall(VecGetArrayRead(UV, &u));
47: v = u + n;
48: PetscCall(VecGetArrayWrite(F, &f));
49: for (i = 0; i < n; i++) f[i] = u[i] - v[i];
50: PetscCall(VecRestoreArrayRead(UV, &u));
51: PetscCall(VecRestoreArrayWrite(F, &f));
52: PetscFunctionReturn(PETSC_SUCCESS);
53: }
55: typedef struct {
56: PetscReal t;
57: SNES snes;
58: Vec UV, V;
59: VecScatter scatterU, scatterV;
60: PetscErrorCode (*f)(PetscReal, Vec, Vec);
61: PetscErrorCode (*F)(PetscReal, Vec, Vec);
62: } AppCtx;
64: extern PetscErrorCode TSFunction(TS, PetscReal, Vec, Vec, void *);
65: extern PetscErrorCode SNESFunction(SNES, Vec, Vec, void *);
67: int main(int argc, char **argv)
68: {
69: AppCtx ctx;
70: TS ts;
71: Vec tsrhs, U;
72: IS is;
73: PetscInt i;
74: PetscMPIInt rank;
76: PetscFunctionBeginUser;
77: PetscCall(PetscInitialize(&argc, &argv, NULL, help));
78: PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
79: PetscCall(TSCreate(PETSC_COMM_WORLD, &ts));
80: PetscCall(TSSetProblemType(ts, TS_NONLINEAR));
81: PetscCall(TSSetType(ts, TSEULER));
82: PetscCall(TSSetFromOptions(ts));
83: PetscCall(VecCreateMPI(PETSC_COMM_WORLD, 1, PETSC_DETERMINE, &tsrhs));
84: PetscCall(VecDuplicate(tsrhs, &U));
85: PetscCall(TSSetRHSFunction(ts, tsrhs, TSFunction, &ctx));
86: PetscCall(TSSetMaxTime(ts, 1.0));
87: ctx.f = f;
89: PetscCall(SNESCreate(PETSC_COMM_WORLD, &ctx.snes));
90: PetscCall(SNESSetFromOptions(ctx.snes));
91: PetscCall(SNESSetFunction(ctx.snes, NULL, SNESFunction, &ctx));
92: PetscCall(SNESSetJacobian(ctx.snes, NULL, NULL, SNESComputeJacobianDefault, &ctx));
93: ctx.F = F;
94: PetscCall(VecCreateMPI(PETSC_COMM_WORLD, 1, PETSC_DETERMINE, &ctx.V));
96: /* Create scatters to move between separate U and V representation and UV representation of solution */
97: PetscCall(VecCreateMPI(PETSC_COMM_WORLD, 2, PETSC_DETERMINE, &ctx.UV));
98: i = 2 * rank;
99: PetscCall(ISCreateGeneral(PETSC_COMM_WORLD, 1, &i, PETSC_COPY_VALUES, &is));
100: PetscCall(VecScatterCreate(U, NULL, ctx.UV, is, &ctx.scatterU));
101: PetscCall(ISDestroy(&is));
102: i = 2 * rank + 1;
103: PetscCall(ISCreateGeneral(PETSC_COMM_WORLD, 1, &i, PETSC_COPY_VALUES, &is));
104: PetscCall(VecScatterCreate(ctx.V, NULL, ctx.UV, is, &ctx.scatterV));
105: PetscCall(ISDestroy(&is));
107: PetscCall(VecSet(U, 1.0));
108: PetscCall(TSSolve(ts, U));
110: PetscCall(VecDestroy(&ctx.V));
111: PetscCall(VecDestroy(&ctx.UV));
112: PetscCall(VecScatterDestroy(&ctx.scatterU));
113: PetscCall(VecScatterDestroy(&ctx.scatterV));
114: PetscCall(VecDestroy(&tsrhs));
115: PetscCall(VecDestroy(&U));
116: PetscCall(SNESDestroy(&ctx.snes));
117: PetscCall(TSDestroy(&ts));
118: PetscCall(PetscFinalize());
119: return 0;
120: }
122: /*
123: Defines the RHS function that is passed to the time-integrator.
125: Solves F(U,V) for V and then computes f(U,V)
126: */
127: PetscErrorCode TSFunction(TS ts, PetscReal t, Vec U, Vec F, void *actx)
128: {
129: AppCtx *ctx = (AppCtx *)actx;
131: PetscFunctionBeginUser;
132: ctx->t = t;
133: PetscCall(VecScatterBegin(ctx->scatterU, U, ctx->UV, INSERT_VALUES, SCATTER_FORWARD));
134: PetscCall(VecScatterEnd(ctx->scatterU, U, ctx->UV, INSERT_VALUES, SCATTER_FORWARD));
135: PetscCall(SNESSolve(ctx->snes, NULL, ctx->V));
136: PetscCall(VecScatterBegin(ctx->scatterV, ctx->V, ctx->UV, INSERT_VALUES, SCATTER_FORWARD));
137: PetscCall(VecScatterEnd(ctx->scatterV, ctx->V, ctx->UV, INSERT_VALUES, SCATTER_FORWARD));
138: PetscCall((*ctx->f)(t, ctx->UV, F));
139: PetscFunctionReturn(PETSC_SUCCESS);
140: }
142: /*
143: Defines the nonlinear function that is passed to the nonlinear solver
145: */
146: PetscErrorCode SNESFunction(SNES snes, Vec V, Vec F, void *actx)
147: {
148: AppCtx *ctx = (AppCtx *)actx;
150: PetscFunctionBeginUser;
151: PetscCall(VecScatterBegin(ctx->scatterV, V, ctx->UV, INSERT_VALUES, SCATTER_FORWARD));
152: PetscCall(VecScatterEnd(ctx->scatterV, V, ctx->UV, INSERT_VALUES, SCATTER_FORWARD));
153: PetscCall((*ctx->F)(ctx->t, ctx->UV, F));
154: PetscFunctionReturn(PETSC_SUCCESS);
155: }
157: /*TEST
159: test:
160: args: -ts_monitor -ts_view
162: TEST*/