xref: /petsc/src/ts/interface/tsrhssplit.c (revision 3a2a065f407e7da3bb6fc7eaf619dbab56034fde)
1545aaa6fSHong Zhang #include <petsc/private/tsimpl.h> /*I "petscts.h"  I*/
2424fc49dSJoe Pusztay #include <petscdm.h>
3d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSRHSSplitGetRHSSplit(TS ts, const char splitname[], TS_RHSSplitLink *isplit)
4d71ae5a4SJacob Faibussowitsch {
51d06f6b3SHong Zhang   PetscBool found = PETSC_FALSE;
61d06f6b3SHong Zhang 
71d06f6b3SHong Zhang   PetscFunctionBegin;
81d06f6b3SHong Zhang   *isplit = ts->tsrhssplit;
91d06f6b3SHong Zhang   /* look up the split */
101d06f6b3SHong Zhang   while (*isplit) {
119566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp((*isplit)->splitname, splitname, &found));
121d06f6b3SHong Zhang     if (found) break;
131d06f6b3SHong Zhang     *isplit = (*isplit)->next;
141d06f6b3SHong Zhang   }
153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
161d06f6b3SHong Zhang }
171d06f6b3SHong Zhang 
18cc4c1da9SBarry Smith /*@
19545aaa6fSHong Zhang   TSRHSSplitSetIS - Set the index set for the specified split
20545aaa6fSHong Zhang 
21c3339decSBarry Smith   Logically Collective
22545aaa6fSHong Zhang 
23545aaa6fSHong Zhang   Input Parameters:
24bcf0153eSBarry Smith + ts        - the `TS` context obtained from `TSCreate()`
2520f4b53cSBarry Smith . splitname - name of this split, if `NULL` the number of the split is used
26545aaa6fSHong Zhang - is        - the index set for part of the solution vector
27545aaa6fSHong Zhang 
28545aaa6fSHong Zhang   Level: intermediate
29545aaa6fSHong Zhang 
301cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `IS`, `TSRHSSplitGetIS()`
31545aaa6fSHong Zhang @*/
32d71ae5a4SJacob Faibussowitsch PetscErrorCode TSRHSSplitSetIS(TS ts, const char splitname[], IS is)
33d71ae5a4SJacob Faibussowitsch {
341d06f6b3SHong Zhang   TS_RHSSplitLink newsplit, next = ts->tsrhssplit;
35545aaa6fSHong Zhang   char            prefix[128];
36545aaa6fSHong Zhang 
37545aaa6fSHong Zhang   PetscFunctionBegin;
38545aaa6fSHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
39545aaa6fSHong Zhang   PetscValidHeaderSpecific(is, IS_CLASSID, 3);
401d06f6b3SHong Zhang 
419566063dSJacob Faibussowitsch   PetscCall(PetscNew(&newsplit));
42545aaa6fSHong Zhang   if (splitname) {
439566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(splitname, &newsplit->splitname));
44545aaa6fSHong Zhang   } else {
459566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(8, &newsplit->splitname));
4663a3b9bcSJacob Faibussowitsch     PetscCall(PetscSNPrintf(newsplit->splitname, 7, "%" PetscInt_FMT, ts->num_rhs_splits));
47545aaa6fSHong Zhang   }
489566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)is));
49545aaa6fSHong Zhang   newsplit->is = is;
509566063dSJacob Faibussowitsch   PetscCall(TSCreate(PetscObjectComm((PetscObject)ts), &newsplit->ts));
51109dc152SHong Zhang 
529566063dSJacob Faibussowitsch   PetscCall(PetscObjectIncrementTabLevel((PetscObject)newsplit->ts, (PetscObject)ts, 1));
539566063dSJacob Faibussowitsch   PetscCall(PetscSNPrintf(prefix, sizeof(prefix), "%srhsplit_%s_", ((PetscObject)ts)->prefix ? ((PetscObject)ts)->prefix : "", newsplit->splitname));
549566063dSJacob Faibussowitsch   PetscCall(TSSetOptionsPrefix(newsplit->ts, prefix));
551d06f6b3SHong Zhang   if (!next) ts->tsrhssplit = newsplit;
561d06f6b3SHong Zhang   else {
571d06f6b3SHong Zhang     while (next->next) next = next->next;
581d06f6b3SHong Zhang     next->next = newsplit;
591d06f6b3SHong Zhang   }
601d06f6b3SHong Zhang   ts->num_rhs_splits++;
613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
62545aaa6fSHong Zhang }
63545aaa6fSHong Zhang 
64cc4c1da9SBarry Smith /*@
65bcf0153eSBarry Smith   TSRHSSplitGetIS - Retrieves the elements for a split as an `IS`
66545aaa6fSHong Zhang 
67c3339decSBarry Smith   Logically Collective
68545aaa6fSHong Zhang 
69545aaa6fSHong Zhang   Input Parameters:
70bcf0153eSBarry Smith + ts        - the `TS` context obtained from `TSCreate()`
71545aaa6fSHong Zhang - splitname - name of this split
72545aaa6fSHong Zhang 
732fe279fdSBarry Smith   Output Parameter:
742fe279fdSBarry Smith . is - the index set for part of the solution vector
75545aaa6fSHong Zhang 
76545aaa6fSHong Zhang   Level: intermediate
77545aaa6fSHong Zhang 
781cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `IS`, `TSRHSSplitSetIS()`
79545aaa6fSHong Zhang @*/
80d71ae5a4SJacob Faibussowitsch PetscErrorCode TSRHSSplitGetIS(TS ts, const char splitname[], IS *is)
81d71ae5a4SJacob Faibussowitsch {
821d06f6b3SHong Zhang   TS_RHSSplitLink isplit;
83545aaa6fSHong Zhang 
84545aaa6fSHong Zhang   PetscFunctionBegin;
85545aaa6fSHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
861d06f6b3SHong Zhang   *is = NULL;
87545aaa6fSHong Zhang   /* look up the split */
889566063dSJacob Faibussowitsch   PetscCall(TSRHSSplitGetRHSSplit(ts, splitname, &isplit));
891d06f6b3SHong Zhang   if (isplit) *is = isplit->is;
903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
91545aaa6fSHong Zhang }
92545aaa6fSHong Zhang 
93545aaa6fSHong Zhang /*@C
94545aaa6fSHong Zhang   TSRHSSplitSetRHSFunction - Set the split right-hand-side functions.
95545aaa6fSHong Zhang 
96c3339decSBarry Smith   Logically Collective
97545aaa6fSHong Zhang 
98545aaa6fSHong Zhang   Input Parameters:
99bcf0153eSBarry Smith + ts        - the `TS` context obtained from `TSCreate()`
100545aaa6fSHong Zhang . splitname - name of this split
10120f4b53cSBarry Smith . r         - vector to hold the residual (or `NULL` to have it created internally)
102545aaa6fSHong Zhang . rhsfunc   - the RHS function evaluation routine
10320f4b53cSBarry Smith - ctx       - user-defined context for private data for the split function evaluation routine (may be `NULL`)
104545aaa6fSHong Zhang 
10520f4b53cSBarry Smith   Level: intermediate
106545aaa6fSHong Zhang 
1078434afd1SBarry Smith .seealso: [](ch_ts), `TS`, `TSRHSFunctionFn`, `IS`, `TSRHSSplitSetIS()`
108545aaa6fSHong Zhang @*/
1098434afd1SBarry Smith PetscErrorCode TSRHSSplitSetRHSFunction(TS ts, const char splitname[], Vec r, TSRHSFunctionFn *rhsfunc, void *ctx)
110d71ae5a4SJacob Faibussowitsch {
1111d06f6b3SHong Zhang   TS_RHSSplitLink isplit;
112424fc49dSJoe Pusztay   DM              dmc;
113545aaa6fSHong Zhang   Vec             subvec, ralloc = NULL;
114545aaa6fSHong Zhang 
115545aaa6fSHong Zhang   PetscFunctionBegin;
116545aaa6fSHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
117064a246eSJacob Faibussowitsch   if (r) PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
118545aaa6fSHong Zhang 
119545aaa6fSHong Zhang   /* look up the split */
1209566063dSJacob Faibussowitsch   PetscCall(TSRHSSplitGetRHSSplit(ts, splitname, &isplit));
1213c633725SBarry Smith   PetscCheck(isplit, PETSC_COMM_SELF, PETSC_ERR_USER, "The split %s is not created, check the split name or call TSRHSSplitSetIS() to create one", splitname);
122545aaa6fSHong Zhang 
1231d06f6b3SHong Zhang   if (!r && ts->vec_sol) {
1249566063dSJacob Faibussowitsch     PetscCall(VecGetSubVector(ts->vec_sol, isplit->is, &subvec));
1259566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(subvec, &ralloc));
126545aaa6fSHong Zhang     r = ralloc;
1279566063dSJacob Faibussowitsch     PetscCall(VecRestoreSubVector(ts->vec_sol, isplit->is, &subvec));
128545aaa6fSHong Zhang   }
129424fc49dSJoe Pusztay 
130424fc49dSJoe Pusztay   if (ts->dm) {
131424fc49dSJoe Pusztay     PetscInt dim;
132424fc49dSJoe Pusztay 
1339566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(ts->dm, &dim));
134424fc49dSJoe Pusztay     if (dim != -1) {
1359566063dSJacob Faibussowitsch       PetscCall(DMClone(ts->dm, &dmc));
1369566063dSJacob Faibussowitsch       PetscCall(TSSetDM(isplit->ts, dmc));
1379566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&dmc));
138424fc49dSJoe Pusztay     }
139424fc49dSJoe Pusztay   }
140424fc49dSJoe Pusztay 
1419566063dSJacob Faibussowitsch   PetscCall(TSSetRHSFunction(isplit->ts, r, rhsfunc, ctx));
1429566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&ralloc));
1433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
144545aaa6fSHong Zhang }
145545aaa6fSHong Zhang 
146*3a2a065fSHong Zhang /*@C
147*3a2a065fSHong Zhang   TSRHSSplitSetIFunction - Set the split implicit function for `TSARKIMEX`
148*3a2a065fSHong Zhang 
149*3a2a065fSHong Zhang   Logically Collective
150*3a2a065fSHong Zhang 
151*3a2a065fSHong Zhang   Input Parameters:
152*3a2a065fSHong Zhang + ts        - the `TS` context obtained from `TSCreate()`
153*3a2a065fSHong Zhang . splitname - name of this split
154*3a2a065fSHong Zhang . r         - vector to hold the residual (or `NULL` to have it created internally)
155*3a2a065fSHong Zhang . ifunc     - the implicit function evaluation routine
156*3a2a065fSHong Zhang - ctx       - user-defined context for private data for the split function evaluation routine (may be `NULL`)
157*3a2a065fSHong Zhang 
158*3a2a065fSHong Zhang   Level: intermediate
159*3a2a065fSHong Zhang 
160*3a2a065fSHong Zhang .seealso: [](ch_ts), `TS`, `TSIFunctionFn`, `IS`, `TSRHSSplitSetIS()`, `TSARKIMEX`
161*3a2a065fSHong Zhang @*/
162*3a2a065fSHong Zhang PetscErrorCode TSRHSSplitSetIFunction(TS ts, const char splitname[], Vec r, TSIFunctionFn *ifunc, void *ctx)
163*3a2a065fSHong Zhang {
164*3a2a065fSHong Zhang   TS_RHSSplitLink isplit;
165*3a2a065fSHong Zhang   DM              dmc;
166*3a2a065fSHong Zhang   Vec             subvec, ralloc = NULL;
167*3a2a065fSHong Zhang 
168*3a2a065fSHong Zhang   PetscFunctionBegin;
169*3a2a065fSHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
170*3a2a065fSHong Zhang   if (r) PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
171*3a2a065fSHong Zhang 
172*3a2a065fSHong Zhang   /* look up the split */
173*3a2a065fSHong Zhang   PetscCall(TSRHSSplitGetRHSSplit(ts, splitname, &isplit));
174*3a2a065fSHong Zhang   PetscCheck(isplit, PETSC_COMM_SELF, PETSC_ERR_USER, "The split %s is not created, check the split name or call TSRHSSplitSetIS() to create one", splitname);
175*3a2a065fSHong Zhang 
176*3a2a065fSHong Zhang   if (!r && ts->vec_sol) {
177*3a2a065fSHong Zhang     PetscCall(VecGetSubVector(ts->vec_sol, isplit->is, &subvec));
178*3a2a065fSHong Zhang     PetscCall(VecDuplicate(subvec, &ralloc));
179*3a2a065fSHong Zhang     r = ralloc;
180*3a2a065fSHong Zhang     PetscCall(VecRestoreSubVector(ts->vec_sol, isplit->is, &subvec));
181*3a2a065fSHong Zhang   }
182*3a2a065fSHong Zhang 
183*3a2a065fSHong Zhang   if (ts->dm) {
184*3a2a065fSHong Zhang     PetscInt dim;
185*3a2a065fSHong Zhang 
186*3a2a065fSHong Zhang     PetscCall(DMGetDimension(ts->dm, &dim));
187*3a2a065fSHong Zhang     if (dim != -1) {
188*3a2a065fSHong Zhang       PetscCall(DMClone(ts->dm, &dmc));
189*3a2a065fSHong Zhang       PetscCall(TSSetDM(isplit->ts, dmc));
190*3a2a065fSHong Zhang       PetscCall(DMDestroy(&dmc));
191*3a2a065fSHong Zhang     }
192*3a2a065fSHong Zhang   }
193*3a2a065fSHong Zhang 
194*3a2a065fSHong Zhang   PetscCall(TSSetIFunction(isplit->ts, r, ifunc, ctx));
195*3a2a065fSHong Zhang   PetscCall(VecDestroy(&ralloc));
196*3a2a065fSHong Zhang   PetscFunctionReturn(PETSC_SUCCESS);
197*3a2a065fSHong Zhang }
198*3a2a065fSHong Zhang 
199*3a2a065fSHong Zhang /*@C
200*3a2a065fSHong Zhang   TSRHSSplitSetIJacobian - Set the Jacobian for the split implicit function with `TSARKIMEX`
201*3a2a065fSHong Zhang 
202*3a2a065fSHong Zhang   Logically Collective
203*3a2a065fSHong Zhang 
204*3a2a065fSHong Zhang   Input Parameters:
205*3a2a065fSHong Zhang + ts        - the `TS` context obtained from `TSCreate()`
206*3a2a065fSHong Zhang . splitname - name of this split
207*3a2a065fSHong Zhang . Amat      - (approximate) matrix to store Jacobian entries computed by `f`
208*3a2a065fSHong Zhang . Pmat      - matrix used to compute preconditioner (usually the same as `Amat`)
209*3a2a065fSHong Zhang . ijac      - the Jacobian evaluation routine
210*3a2a065fSHong Zhang - ctx       - user-defined context for private data for the split function evaluation routine (may be `NULL`)
211*3a2a065fSHong Zhang 
212*3a2a065fSHong Zhang   Level: intermediate
213*3a2a065fSHong Zhang 
214*3a2a065fSHong Zhang .seealso: [](ch_ts), `TS`, `TSRHSSplitSetIFunction`, `TSIJacobianFn`, `IS`, `TSRHSSplitSetIS()`
215*3a2a065fSHong Zhang @*/
216*3a2a065fSHong Zhang PetscErrorCode TSRHSSplitSetIJacobian(TS ts, const char splitname[], Mat Amat, Mat Pmat, TSIJacobianFn *ijac, void *ctx)
217*3a2a065fSHong Zhang {
218*3a2a065fSHong Zhang   TS_RHSSplitLink isplit;
219*3a2a065fSHong Zhang   DM              dmc;
220*3a2a065fSHong Zhang 
221*3a2a065fSHong Zhang   PetscFunctionBegin;
222*3a2a065fSHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
223*3a2a065fSHong Zhang   if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 3);
224*3a2a065fSHong Zhang   if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 4);
225*3a2a065fSHong Zhang   if (Amat) PetscCheckSameComm(ts, 1, Amat, 3);
226*3a2a065fSHong Zhang   if (Pmat) PetscCheckSameComm(ts, 1, Pmat, 4);
227*3a2a065fSHong Zhang 
228*3a2a065fSHong Zhang   /* look up the split */
229*3a2a065fSHong Zhang   PetscCall(TSRHSSplitGetRHSSplit(ts, splitname, &isplit));
230*3a2a065fSHong Zhang   PetscCheck(isplit, PETSC_COMM_SELF, PETSC_ERR_USER, "The split %s is not created, check the split name or call TSRHSSplitSetIS() to create one", splitname);
231*3a2a065fSHong Zhang 
232*3a2a065fSHong Zhang   if (ts->dm) {
233*3a2a065fSHong Zhang     PetscInt dim;
234*3a2a065fSHong Zhang 
235*3a2a065fSHong Zhang     PetscCall(DMGetDimension(ts->dm, &dim));
236*3a2a065fSHong Zhang     if (dim != -1) {
237*3a2a065fSHong Zhang       PetscCall(DMClone(ts->dm, &dmc));
238*3a2a065fSHong Zhang       PetscCall(TSSetDM(isplit->ts, dmc));
239*3a2a065fSHong Zhang       PetscCall(DMDestroy(&dmc));
240*3a2a065fSHong Zhang     }
241*3a2a065fSHong Zhang   }
242*3a2a065fSHong Zhang 
243*3a2a065fSHong Zhang   PetscCall(TSSetIJacobian(isplit->ts, Amat, Pmat, ijac, ctx));
244*3a2a065fSHong Zhang   PetscFunctionReturn(PETSC_SUCCESS);
245*3a2a065fSHong Zhang }
246*3a2a065fSHong Zhang 
247*3a2a065fSHong Zhang /*@C
248bcf0153eSBarry Smith   TSRHSSplitGetSubTS - Get the sub-`TS` by split name.
2491d06f6b3SHong Zhang 
250c3339decSBarry Smith   Logically Collective
2511d06f6b3SHong Zhang 
2526b867d5aSJose E. Roman   Input Parameter:
253bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()`
2546b867d5aSJose E. Roman 
2551d06f6b3SHong Zhang   Output Parameters:
2561d06f6b3SHong Zhang + splitname - the number of the split
25720f4b53cSBarry Smith - subts     - the sub-`TS`
2581d06f6b3SHong Zhang 
2591d06f6b3SHong Zhang   Level: advanced
2601d06f6b3SHong Zhang 
2611cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `IS`, `TSGetRHSSplitFunction()`
2621d06f6b3SHong Zhang @*/
263d71ae5a4SJacob Faibussowitsch PetscErrorCode TSRHSSplitGetSubTS(TS ts, const char splitname[], TS *subts)
264d71ae5a4SJacob Faibussowitsch {
2651d06f6b3SHong Zhang   TS_RHSSplitLink isplit;
2661d06f6b3SHong Zhang 
2671d06f6b3SHong Zhang   PetscFunctionBegin;
2681d06f6b3SHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2694f572ea9SToby Isaac   PetscAssertPointer(subts, 3);
2701d06f6b3SHong Zhang   *subts = NULL;
2711d06f6b3SHong Zhang   /* look up the split */
2729566063dSJacob Faibussowitsch   PetscCall(TSRHSSplitGetRHSSplit(ts, splitname, &isplit));
2731d06f6b3SHong Zhang   if (isplit) *subts = isplit->ts;
2743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2751d06f6b3SHong Zhang }
2761d06f6b3SHong Zhang 
2771d06f6b3SHong Zhang /*@C
278bcf0153eSBarry Smith   TSRHSSplitGetSubTSs - Get an array of all sub-`TS` contexts.
279545aaa6fSHong Zhang 
280c3339decSBarry Smith   Logically Collective
281545aaa6fSHong Zhang 
2826b867d5aSJose E. Roman   Input Parameter:
283bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()`
2846b867d5aSJose E. Roman 
285545aaa6fSHong Zhang   Output Parameters:
286545aaa6fSHong Zhang + n     - the number of splits
287b43aa488SJacob Faibussowitsch - subts - the array of `TS` contexts
288545aaa6fSHong Zhang 
289545aaa6fSHong Zhang   Level: advanced
290545aaa6fSHong Zhang 
291bcf0153eSBarry Smith   Note:
292bcf0153eSBarry Smith   After `TSRHSSplitGetSubTS()` the array of `TS`s is to be freed by the user with `PetscFree()`
29320f4b53cSBarry Smith   (not the `TS` in the array just the array that contains them).
294bcf0153eSBarry Smith 
2951cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `IS`, `TSGetRHSSplitFunction()`
296545aaa6fSHong Zhang @*/
297d71ae5a4SJacob Faibussowitsch PetscErrorCode TSRHSSplitGetSubTSs(TS ts, PetscInt *n, TS *subts[])
298d71ae5a4SJacob Faibussowitsch {
2991d06f6b3SHong Zhang   TS_RHSSplitLink ilink = ts->tsrhssplit;
300545aaa6fSHong Zhang   PetscInt        i     = 0;
301545aaa6fSHong Zhang 
302545aaa6fSHong Zhang   PetscFunctionBegin;
303545aaa6fSHong Zhang   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
304545aaa6fSHong Zhang   if (subts) {
3059566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(ts->num_rhs_splits, subts));
3061d06f6b3SHong Zhang     while (ilink) {
3071d06f6b3SHong Zhang       (*subts)[i++] = ilink->ts;
3081d06f6b3SHong Zhang       ilink         = ilink->next;
309545aaa6fSHong Zhang     }
310545aaa6fSHong Zhang   }
311545aaa6fSHong Zhang   if (n) *n = ts->num_rhs_splits;
3123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
313545aaa6fSHong Zhang }
314