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 18545aaa6fSHong Zhang /*@C 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 30*1cc06b55SBarry 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 64545aaa6fSHong Zhang /*@C 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 78*1cc06b55SBarry 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 Calling sequence of `rhsfun`: 10620f4b53cSBarry Smith $ PetscErrorCode rhsfunc(TS ts, PetscReal t, Vec u, Vec f,ctx) 10720f4b53cSBarry Smith + ts - the `TS` context obtained from `TSCreate()` 10820f4b53cSBarry Smith . t - time at step/stage being solved 109545aaa6fSHong Zhang . u - state vector 110545aaa6fSHong Zhang . f - function vector 11120f4b53cSBarry Smith - ctx - [optional] user-defined context for matrix evaluation routine (may be `NULL`) 112545aaa6fSHong Zhang 11320f4b53cSBarry Smith Level: intermediate 114545aaa6fSHong Zhang 115*1cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `TSRHSFunction`, `IS`, `TSRHSSplitSetIS()` 116545aaa6fSHong Zhang @*/ 117d71ae5a4SJacob Faibussowitsch PetscErrorCode TSRHSSplitSetRHSFunction(TS ts, const char splitname[], Vec r, TSRHSFunction rhsfunc, void *ctx) 118d71ae5a4SJacob Faibussowitsch { 1191d06f6b3SHong Zhang TS_RHSSplitLink isplit; 120424fc49dSJoe Pusztay DM dmc; 121545aaa6fSHong Zhang Vec subvec, ralloc = NULL; 122545aaa6fSHong Zhang 123545aaa6fSHong Zhang PetscFunctionBegin; 124545aaa6fSHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 125064a246eSJacob Faibussowitsch if (r) PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 126545aaa6fSHong Zhang 127545aaa6fSHong Zhang /* look up the split */ 1289566063dSJacob Faibussowitsch PetscCall(TSRHSSplitGetRHSSplit(ts, splitname, &isplit)); 1293c633725SBarry 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); 130545aaa6fSHong Zhang 1311d06f6b3SHong Zhang if (!r && ts->vec_sol) { 1329566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(ts->vec_sol, isplit->is, &subvec)); 1339566063dSJacob Faibussowitsch PetscCall(VecDuplicate(subvec, &ralloc)); 134545aaa6fSHong Zhang r = ralloc; 1359566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(ts->vec_sol, isplit->is, &subvec)); 136545aaa6fSHong Zhang } 137424fc49dSJoe Pusztay 138424fc49dSJoe Pusztay if (ts->dm) { 139424fc49dSJoe Pusztay PetscInt dim; 140424fc49dSJoe Pusztay 1419566063dSJacob Faibussowitsch PetscCall(DMGetDimension(ts->dm, &dim)); 142424fc49dSJoe Pusztay if (dim != -1) { 1439566063dSJacob Faibussowitsch PetscCall(DMClone(ts->dm, &dmc)); 1449566063dSJacob Faibussowitsch PetscCall(TSSetDM(isplit->ts, dmc)); 1459566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 146424fc49dSJoe Pusztay } 147424fc49dSJoe Pusztay } 148424fc49dSJoe Pusztay 1499566063dSJacob Faibussowitsch PetscCall(TSSetRHSFunction(isplit->ts, r, rhsfunc, ctx)); 1509566063dSJacob Faibussowitsch PetscCall(VecDestroy(&ralloc)); 1513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 152545aaa6fSHong Zhang } 153545aaa6fSHong Zhang 154545aaa6fSHong Zhang /*@C 155bcf0153eSBarry Smith TSRHSSplitGetSubTS - Get the sub-`TS` by split name. 1561d06f6b3SHong Zhang 157c3339decSBarry Smith Logically Collective 1581d06f6b3SHong Zhang 1596b867d5aSJose E. Roman Input Parameter: 160bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()` 1616b867d5aSJose E. Roman 1621d06f6b3SHong Zhang Output Parameters: 1631d06f6b3SHong Zhang + splitname - the number of the split 16420f4b53cSBarry Smith - subts - the sub-`TS` 1651d06f6b3SHong Zhang 1661d06f6b3SHong Zhang Level: advanced 1671d06f6b3SHong Zhang 168*1cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `IS`, `TSGetRHSSplitFunction()` 1691d06f6b3SHong Zhang @*/ 170d71ae5a4SJacob Faibussowitsch PetscErrorCode TSRHSSplitGetSubTS(TS ts, const char splitname[], TS *subts) 171d71ae5a4SJacob Faibussowitsch { 1721d06f6b3SHong Zhang TS_RHSSplitLink isplit; 1731d06f6b3SHong Zhang 1741d06f6b3SHong Zhang PetscFunctionBegin; 1751d06f6b3SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1761d06f6b3SHong Zhang PetscValidPointer(subts, 3); 1771d06f6b3SHong Zhang *subts = NULL; 1781d06f6b3SHong Zhang /* look up the split */ 1799566063dSJacob Faibussowitsch PetscCall(TSRHSSplitGetRHSSplit(ts, splitname, &isplit)); 1801d06f6b3SHong Zhang if (isplit) *subts = isplit->ts; 1813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1821d06f6b3SHong Zhang } 1831d06f6b3SHong Zhang 1841d06f6b3SHong Zhang /*@C 185bcf0153eSBarry Smith TSRHSSplitGetSubTSs - Get an array of all sub-`TS` contexts. 186545aaa6fSHong Zhang 187c3339decSBarry Smith Logically Collective 188545aaa6fSHong Zhang 1896b867d5aSJose E. Roman Input Parameter: 190bcf0153eSBarry Smith . ts - the `TS` context obtained from `TSCreate()` 1916b867d5aSJose E. Roman 192545aaa6fSHong Zhang Output Parameters: 193545aaa6fSHong Zhang + n - the number of splits 194bcf0153eSBarry Smith - subksp - the array of `TS` contexts 195545aaa6fSHong Zhang 196545aaa6fSHong Zhang Level: advanced 197545aaa6fSHong Zhang 198bcf0153eSBarry Smith Note: 199bcf0153eSBarry Smith After `TSRHSSplitGetSubTS()` the array of `TS`s is to be freed by the user with `PetscFree()` 20020f4b53cSBarry Smith (not the `TS` in the array just the array that contains them). 201bcf0153eSBarry Smith 202*1cc06b55SBarry Smith .seealso: [](ch_ts), `TS`, `IS`, `TSGetRHSSplitFunction()` 203545aaa6fSHong Zhang @*/ 204d71ae5a4SJacob Faibussowitsch PetscErrorCode TSRHSSplitGetSubTSs(TS ts, PetscInt *n, TS *subts[]) 205d71ae5a4SJacob Faibussowitsch { 2061d06f6b3SHong Zhang TS_RHSSplitLink ilink = ts->tsrhssplit; 207545aaa6fSHong Zhang PetscInt i = 0; 208545aaa6fSHong Zhang 209545aaa6fSHong Zhang PetscFunctionBegin; 210545aaa6fSHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 211545aaa6fSHong Zhang if (subts) { 2129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ts->num_rhs_splits, subts)); 2131d06f6b3SHong Zhang while (ilink) { 2141d06f6b3SHong Zhang (*subts)[i++] = ilink->ts; 2151d06f6b3SHong Zhang ilink = ilink->next; 216545aaa6fSHong Zhang } 217545aaa6fSHong Zhang } 218545aaa6fSHong Zhang if (n) *n = ts->num_rhs_splits; 2193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 220545aaa6fSHong Zhang } 221