1e49d4f37SHong Zhang /* 2e49d4f37SHong Zhang Code for Timestepping with basic symplectic integrators for separable Hamiltonian systems 3e49d4f37SHong Zhang */ 4e49d4f37SHong Zhang #include <petsc/private/tsimpl.h> /*I "petscts.h" I*/ 5e49d4f37SHong Zhang #include <petscdm.h> 6e49d4f37SHong Zhang 7e49d4f37SHong Zhang static TSBasicSymplecticType TSBasicSymplecticDefault = TSBASICSYMPLECTICSIEULER; 8e49d4f37SHong Zhang static PetscBool TSBasicSymplecticRegisterAllCalled; 9e49d4f37SHong Zhang static PetscBool TSBasicSymplecticPackageInitialized; 10e49d4f37SHong Zhang 11e49d4f37SHong Zhang typedef struct _BasicSymplecticScheme *BasicSymplecticScheme; 12e49d4f37SHong Zhang typedef struct _BasicSymplecticSchemeLink *BasicSymplecticSchemeLink; 13e49d4f37SHong Zhang 14e49d4f37SHong Zhang struct _BasicSymplecticScheme { 15e49d4f37SHong Zhang char *name; 16e49d4f37SHong Zhang PetscInt order; 17e49d4f37SHong Zhang PetscInt s; /* number of stages */ 18e49d4f37SHong Zhang PetscReal *c, *d; 19e49d4f37SHong Zhang }; 20e49d4f37SHong Zhang struct _BasicSymplecticSchemeLink { 21e49d4f37SHong Zhang struct _BasicSymplecticScheme sch; 22e49d4f37SHong Zhang BasicSymplecticSchemeLink next; 23e49d4f37SHong Zhang }; 24e49d4f37SHong Zhang static BasicSymplecticSchemeLink BasicSymplecticSchemeList; 25e49d4f37SHong Zhang typedef struct { 26e49d4f37SHong Zhang TS subts_p, subts_q; /* sub TS contexts that holds the RHSFunction pointers */ 27e49d4f37SHong Zhang IS is_p, is_q; /* IS sets for position and momentum respectively */ 28e49d4f37SHong Zhang Vec update; /* a nest work vector for generalized coordinates */ 29e49d4f37SHong Zhang BasicSymplecticScheme scheme; 30e49d4f37SHong Zhang } TS_BasicSymplectic; 31e49d4f37SHong Zhang 32e49d4f37SHong Zhang /*MC 33e49d4f37SHong Zhang TSBASICSYMPLECTICSIEULER - first order semi-implicit Euler method 34bcf0153eSBarry Smith 35e49d4f37SHong Zhang Level: intermediate 36bcf0153eSBarry Smith 371cc06b55SBarry Smith .seealso: [](ch_ts), `TSBASICSYMPLECTIC` 38e49d4f37SHong Zhang M*/ 39e49d4f37SHong Zhang 40e49d4f37SHong Zhang /*MC 41aaa8cc7dSPierre Jolivet TSBASICSYMPLECTICVELVERLET - second order Velocity Verlet method (leapfrog method with starting process and determining velocity and position at the same time) 42bcf0153eSBarry Smith 43e49d4f37SHong Zhang Level: intermediate 44bcf0153eSBarry Smith 451cc06b55SBarry Smith .seealso: [](ch_ts), `TSBASICSYMPLECTIC` 46e49d4f37SHong Zhang M*/ 47e49d4f37SHong Zhang 48e49d4f37SHong Zhang /*@C 49bcf0153eSBarry Smith TSBasicSymplecticRegisterAll - Registers all of the basic symplectic integration methods in `TSBASICSYMPLECTIC` 50e49d4f37SHong Zhang 51e49d4f37SHong Zhang Not Collective, but should be called by all processes which will need the schemes to be registered 52e49d4f37SHong Zhang 53e49d4f37SHong Zhang Level: advanced 54e49d4f37SHong Zhang 551cc06b55SBarry Smith .seealso: [](ch_ts), `TSBASICSYMPLECTIC`, `TSBasicSymplecticRegisterDestroy()` 56e49d4f37SHong Zhang @*/ 57d71ae5a4SJacob Faibussowitsch PetscErrorCode TSBasicSymplecticRegisterAll(void) 58d71ae5a4SJacob Faibussowitsch { 59e49d4f37SHong Zhang PetscFunctionBegin; 603ba16761SJacob Faibussowitsch if (TSBasicSymplecticRegisterAllCalled) PetscFunctionReturn(PETSC_SUCCESS); 61e49d4f37SHong Zhang TSBasicSymplecticRegisterAllCalled = PETSC_TRUE; 62e49d4f37SHong Zhang { 63e49d4f37SHong Zhang PetscReal c[1] = {1.0}, d[1] = {1.0}; 649566063dSJacob Faibussowitsch PetscCall(TSBasicSymplecticRegister(TSBASICSYMPLECTICSIEULER, 1, 1, c, d)); 65e49d4f37SHong Zhang } 66e49d4f37SHong Zhang { 67e49d4f37SHong Zhang PetscReal c[2] = {0, 1.0}, d[2] = {0.5, 0.5}; 689566063dSJacob Faibussowitsch PetscCall(TSBasicSymplecticRegister(TSBASICSYMPLECTICVELVERLET, 2, 2, c, d)); 69e49d4f37SHong Zhang } 70e49d4f37SHong Zhang { 71e49d4f37SHong Zhang PetscReal c[3] = {1, -2.0 / 3.0, 2.0 / 3.0}, d[3] = {-1.0 / 24.0, 3.0 / 4.0, 7.0 / 24.0}; 729566063dSJacob Faibussowitsch PetscCall(TSBasicSymplecticRegister(TSBASICSYMPLECTIC3, 3, 3, c, d)); 73e49d4f37SHong Zhang } 74e49d4f37SHong Zhang { 75e49d4f37SHong Zhang #define CUBEROOTOFTWO 1.2599210498948731647672106 76e49d4f37SHong Zhang PetscReal c[4] = {1.0 / 2.0 / (2.0 - CUBEROOTOFTWO), (1.0 - CUBEROOTOFTWO) / 2.0 / (2.0 - CUBEROOTOFTWO), (1.0 - CUBEROOTOFTWO) / 2.0 / (2.0 - CUBEROOTOFTWO), 1.0 / 2.0 / (2.0 - CUBEROOTOFTWO)}, d[4] = {1.0 / (2.0 - CUBEROOTOFTWO), -CUBEROOTOFTWO / (2.0 - CUBEROOTOFTWO), 1.0 / (2.0 - CUBEROOTOFTWO), 0}; 779566063dSJacob Faibussowitsch PetscCall(TSBasicSymplecticRegister(TSBASICSYMPLECTIC4, 4, 4, c, d)); 78e49d4f37SHong Zhang } 793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 80e49d4f37SHong Zhang } 81e49d4f37SHong Zhang 82e49d4f37SHong Zhang /*@C 83bcf0153eSBarry Smith TSBasicSymplecticRegisterDestroy - Frees the list of schemes that were registered by `TSBasicSymplecticRegister()`. 84e49d4f37SHong Zhang 85e49d4f37SHong Zhang Not Collective 86e49d4f37SHong Zhang 87e49d4f37SHong Zhang Level: advanced 88e49d4f37SHong Zhang 891cc06b55SBarry Smith .seealso: [](ch_ts), `TSBasicSymplecticRegister()`, `TSBasicSymplecticRegisterAll()`, `TSBASICSYMPLECTIC` 90e49d4f37SHong Zhang @*/ 91d71ae5a4SJacob Faibussowitsch PetscErrorCode TSBasicSymplecticRegisterDestroy(void) 92d71ae5a4SJacob Faibussowitsch { 93e49d4f37SHong Zhang BasicSymplecticSchemeLink link; 94e49d4f37SHong Zhang 95e49d4f37SHong Zhang PetscFunctionBegin; 96e49d4f37SHong Zhang while ((link = BasicSymplecticSchemeList)) { 97e49d4f37SHong Zhang BasicSymplecticScheme scheme = &link->sch; 98e49d4f37SHong Zhang BasicSymplecticSchemeList = link->next; 999566063dSJacob Faibussowitsch PetscCall(PetscFree2(scheme->c, scheme->d)); 1009566063dSJacob Faibussowitsch PetscCall(PetscFree(scheme->name)); 1019566063dSJacob Faibussowitsch PetscCall(PetscFree(link)); 102e49d4f37SHong Zhang } 103e49d4f37SHong Zhang TSBasicSymplecticRegisterAllCalled = PETSC_FALSE; 1043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 105e49d4f37SHong Zhang } 106e49d4f37SHong Zhang 107e49d4f37SHong Zhang /*@C 108bcf0153eSBarry Smith TSBasicSymplecticInitializePackage - This function initializes everything in the `TSBASICSYMPLECTIC` package. It is called 109bcf0153eSBarry Smith from `TSInitializePackage()`. 110e49d4f37SHong Zhang 111e49d4f37SHong Zhang Level: developer 112e49d4f37SHong Zhang 1131cc06b55SBarry Smith .seealso: [](ch_ts), `PetscInitialize()`, `TSBASICSYMPLECTIC` 114e49d4f37SHong Zhang @*/ 115d71ae5a4SJacob Faibussowitsch PetscErrorCode TSBasicSymplecticInitializePackage(void) 116d71ae5a4SJacob Faibussowitsch { 117e49d4f37SHong Zhang PetscFunctionBegin; 1183ba16761SJacob Faibussowitsch if (TSBasicSymplecticPackageInitialized) PetscFunctionReturn(PETSC_SUCCESS); 119e49d4f37SHong Zhang TSBasicSymplecticPackageInitialized = PETSC_TRUE; 1209566063dSJacob Faibussowitsch PetscCall(TSBasicSymplecticRegisterAll()); 1219566063dSJacob Faibussowitsch PetscCall(PetscRegisterFinalize(TSBasicSymplecticFinalizePackage)); 1223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 123e49d4f37SHong Zhang } 124e49d4f37SHong Zhang 125e49d4f37SHong Zhang /*@C 126bcf0153eSBarry Smith TSBasicSymplecticFinalizePackage - This function destroys everything in the `TSBASICSYMPLECTIC` package. It is 127bcf0153eSBarry Smith called from `PetscFinalize()`. 128e49d4f37SHong Zhang 129e49d4f37SHong Zhang Level: developer 130e49d4f37SHong Zhang 1311cc06b55SBarry Smith .seealso: [](ch_ts), `PetscFinalize()`, `TSBASICSYMPLECTIC` 132e49d4f37SHong Zhang @*/ 133d71ae5a4SJacob Faibussowitsch PetscErrorCode TSBasicSymplecticFinalizePackage(void) 134d71ae5a4SJacob Faibussowitsch { 135e49d4f37SHong Zhang PetscFunctionBegin; 136e49d4f37SHong Zhang TSBasicSymplecticPackageInitialized = PETSC_FALSE; 1379566063dSJacob Faibussowitsch PetscCall(TSBasicSymplecticRegisterDestroy()); 1383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 139e49d4f37SHong Zhang } 140e49d4f37SHong Zhang 141e49d4f37SHong Zhang /*@C 142e49d4f37SHong Zhang TSBasicSymplecticRegister - register a basic symplectic integration scheme by providing the coefficients. 143e49d4f37SHong Zhang 144e49d4f37SHong Zhang Not Collective, but the same schemes should be registered on all processes on which they will be used 145e49d4f37SHong Zhang 146e49d4f37SHong Zhang Input Parameters: 147e49d4f37SHong Zhang + name - identifier for method 148e49d4f37SHong Zhang . order - approximation order of method 149e49d4f37SHong Zhang . s - number of stages, this is the dimension of the matrices below 150e49d4f37SHong Zhang . c - coefficients for updating generalized position (dimension s) 151e49d4f37SHong Zhang - d - coefficients for updating generalized momentum (dimension s) 152e49d4f37SHong Zhang 153bcf0153eSBarry Smith Level: advanced 154bcf0153eSBarry Smith 155*1d27aa22SBarry Smith Note: 156e49d4f37SHong Zhang Several symplectic methods are provided, this function is only needed to create new methods. 157e49d4f37SHong Zhang 1581cc06b55SBarry Smith .seealso: [](ch_ts), `TSBASICSYMPLECTIC` 159e49d4f37SHong Zhang @*/ 160d71ae5a4SJacob Faibussowitsch PetscErrorCode TSBasicSymplecticRegister(TSRosWType name, PetscInt order, PetscInt s, PetscReal c[], PetscReal d[]) 161d71ae5a4SJacob Faibussowitsch { 162e49d4f37SHong Zhang BasicSymplecticSchemeLink link; 163e49d4f37SHong Zhang BasicSymplecticScheme scheme; 164e49d4f37SHong Zhang 165e49d4f37SHong Zhang PetscFunctionBegin; 1664f572ea9SToby Isaac PetscAssertPointer(name, 1); 1674f572ea9SToby Isaac PetscAssertPointer(c, 4); 1684f572ea9SToby Isaac PetscAssertPointer(d, 5); 169e49d4f37SHong Zhang 1709566063dSJacob Faibussowitsch PetscCall(TSBasicSymplecticInitializePackage()); 1719566063dSJacob Faibussowitsch PetscCall(PetscNew(&link)); 172e49d4f37SHong Zhang scheme = &link->sch; 1739566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(name, &scheme->name)); 174e49d4f37SHong Zhang scheme->order = order; 175e49d4f37SHong Zhang scheme->s = s; 1769566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(s, &scheme->c, s, &scheme->d)); 1779566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(scheme->c, c, s)); 1789566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(scheme->d, d, s)); 179e49d4f37SHong Zhang link->next = BasicSymplecticSchemeList; 180e49d4f37SHong Zhang BasicSymplecticSchemeList = link; 1813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 182e49d4f37SHong Zhang } 183e49d4f37SHong Zhang 184e49d4f37SHong Zhang /* 185e49d4f37SHong Zhang The simplified form of the equations are: 186e49d4f37SHong Zhang 18737fdd005SBarry Smith .vb 18825de42d4SHong Zhang q_{i+1} = q_i + c_i*g(p_i)*h 18925de42d4SHong Zhang p_{i+1} = p_i + d_i*f(q_{i+1})*h 19037fdd005SBarry Smith .ve 191e49d4f37SHong Zhang 192e49d4f37SHong Zhang Several symplectic integrators are given below. An illustrative way to use them is to consider a particle with position q and velocity p. 193e49d4f37SHong Zhang 194e49d4f37SHong Zhang To apply a timestep with values c_{1,2},d_{1,2} to the particle, carry out the following steps: 19537fdd005SBarry Smith .vb 19625de42d4SHong Zhang - Update the position of the particle by adding to it its velocity multiplied by c_1 19725de42d4SHong Zhang - Update the velocity of the particle by adding to it its acceleration (at the updated position) multiplied by d_1 19825de42d4SHong Zhang - Update the position of the particle by adding to it its (updated) velocity multiplied by c_2 19925de42d4SHong Zhang - Update the velocity of the particle by adding to it its acceleration (at the updated position) multiplied by d_2 20037fdd005SBarry Smith .ve 201e49d4f37SHong Zhang 202e49d4f37SHong Zhang */ 203d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSStep_BasicSymplectic(TS ts) 204d71ae5a4SJacob Faibussowitsch { 205e49d4f37SHong Zhang TS_BasicSymplectic *bsymp = (TS_BasicSymplectic *)ts->data; 206e49d4f37SHong Zhang BasicSymplecticScheme scheme = bsymp->scheme; 207e49d4f37SHong Zhang Vec solution = ts->vec_sol, update = bsymp->update, q, p, q_update, p_update; 208e49d4f37SHong Zhang IS is_q = bsymp->is_q, is_p = bsymp->is_p; 209e49d4f37SHong Zhang TS subts_q = bsymp->subts_q, subts_p = bsymp->subts_p; 210f9813ea2SStefano Zampini PetscBool stageok = PETSC_TRUE; 211f9813ea2SStefano Zampini PetscReal ptime = ts->ptime, next_time_step = ts->time_step; 212e49d4f37SHong Zhang PetscInt iter; 213e49d4f37SHong Zhang 214e49d4f37SHong Zhang PetscFunctionBegin; 2159566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(update, is_q, &q_update)); 2169566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(update, is_p, &p_update)); 217e49d4f37SHong Zhang for (iter = 0; iter < scheme->s; iter++) { 218f9813ea2SStefano Zampini PetscCall(TSPreStage(ts, ptime)); 219f9813ea2SStefano Zampini PetscCall(VecGetSubVector(solution, is_q, &q)); 220f9813ea2SStefano Zampini PetscCall(VecGetSubVector(solution, is_p, &p)); 221e49d4f37SHong Zhang /* update position q */ 22225de42d4SHong Zhang if (scheme->c[iter]) { 223f9813ea2SStefano Zampini PetscCall(TSComputeRHSFunction(subts_q, ptime, p, q_update)); 22425de42d4SHong Zhang PetscCall(VecAXPY(q, scheme->c[iter] * ts->time_step, q_update)); 22525de42d4SHong Zhang } 22625de42d4SHong Zhang /* update velocity p */ 22725de42d4SHong Zhang if (scheme->d[iter]) { 228f9813ea2SStefano Zampini ptime = ptime + scheme->d[iter] * ts->time_step; 22925de42d4SHong Zhang PetscCall(TSComputeRHSFunction(subts_p, ptime, q, p_update)); 23025de42d4SHong Zhang PetscCall(VecAXPY(p, scheme->d[iter] * ts->time_step, p_update)); 231e49d4f37SHong Zhang } 2329566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(solution, is_q, &q)); 2339566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(solution, is_p, &p)); 234f9813ea2SStefano Zampini PetscCall(TSPostStage(ts, ptime, 0, &solution)); 235f9813ea2SStefano Zampini PetscCall(TSAdaptCheckStage(ts->adapt, ts, ptime, solution, &stageok)); 236f9813ea2SStefano Zampini if (!stageok) goto finally; 237f9813ea2SStefano Zampini PetscCall(TSFunctionDomainError(ts, ptime, solution, &stageok)); 238f9813ea2SStefano Zampini if (!stageok) goto finally; 239f9813ea2SStefano Zampini } 240f9813ea2SStefano Zampini 241f9813ea2SStefano Zampini finally: 242f9813ea2SStefano Zampini if (!stageok) ts->reason = TS_DIVERGED_STEP_REJECTED; 243f9813ea2SStefano Zampini else ts->ptime += next_time_step; 2449566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(update, is_q, &q_update)); 2459566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(update, is_p, &p_update)); 2463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 247e49d4f37SHong Zhang } 248e49d4f37SHong Zhang 249d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCoarsenHook_BasicSymplectic(DM fine, DM coarse, void *ctx) 250d71ae5a4SJacob Faibussowitsch { 251e49d4f37SHong Zhang PetscFunctionBegin; 2523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 253e49d4f37SHong Zhang } 254e49d4f37SHong Zhang 255d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMRestrictHook_BasicSymplectic(DM fine, Mat restrct, Vec rscale, Mat inject, DM coarse, void *ctx) 256d71ae5a4SJacob Faibussowitsch { 257e49d4f37SHong Zhang PetscFunctionBegin; 2583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 259e49d4f37SHong Zhang } 260e49d4f37SHong Zhang 261d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSubDomainHook_BasicSymplectic(DM dm, DM subdm, void *ctx) 262d71ae5a4SJacob Faibussowitsch { 263e49d4f37SHong Zhang PetscFunctionBegin; 2643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 265e49d4f37SHong Zhang } 266e49d4f37SHong Zhang 267d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSubDomainRestrictHook_BasicSymplectic(DM dm, VecScatter gscat, VecScatter lscat, DM subdm, void *ctx) 268d71ae5a4SJacob Faibussowitsch { 269e49d4f37SHong Zhang PetscFunctionBegin; 2703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 271e49d4f37SHong Zhang } 272e49d4f37SHong Zhang 273d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSSetUp_BasicSymplectic(TS ts) 274d71ae5a4SJacob Faibussowitsch { 275e49d4f37SHong Zhang TS_BasicSymplectic *bsymp = (TS_BasicSymplectic *)ts->data; 276e49d4f37SHong Zhang DM dm; 277e49d4f37SHong Zhang 278e49d4f37SHong Zhang PetscFunctionBegin; 2799566063dSJacob Faibussowitsch PetscCall(TSRHSSplitGetIS(ts, "position", &bsymp->is_q)); 2809566063dSJacob Faibussowitsch PetscCall(TSRHSSplitGetIS(ts, "momentum", &bsymp->is_p)); 281aaa8cc7dSPierre Jolivet PetscCheck(bsymp->is_q && bsymp->is_p, PetscObjectComm((PetscObject)ts), PETSC_ERR_USER, "Must set up RHSSplits with TSRHSSplitSetIS() using split names position and momentum respectively in order to use -ts_type basicsymplectic"); 2829566063dSJacob Faibussowitsch PetscCall(TSRHSSplitGetSubTS(ts, "position", &bsymp->subts_q)); 2839566063dSJacob Faibussowitsch PetscCall(TSRHSSplitGetSubTS(ts, "momentum", &bsymp->subts_p)); 2843c633725SBarry Smith PetscCheck(bsymp->subts_q && bsymp->subts_p, PetscObjectComm((PetscObject)ts), PETSC_ERR_USER, "Must set up the RHSFunctions for position and momentum using TSRHSSplitSetRHSFunction() or calling TSSetRHSFunction() for each sub-TS"); 285e49d4f37SHong Zhang 2869566063dSJacob Faibussowitsch PetscCall(VecDuplicate(ts->vec_sol, &bsymp->update)); 287e49d4f37SHong Zhang 2889566063dSJacob Faibussowitsch PetscCall(TSGetAdapt(ts, &ts->adapt)); 2899566063dSJacob Faibussowitsch PetscCall(TSAdaptCandidatesClear(ts->adapt)); /* make sure to use fixed time stepping */ 2909566063dSJacob Faibussowitsch PetscCall(TSGetDM(ts, &dm)); 291e49d4f37SHong Zhang if (dm) { 2929566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookAdd(dm, DMCoarsenHook_BasicSymplectic, DMRestrictHook_BasicSymplectic, ts)); 2939566063dSJacob Faibussowitsch PetscCall(DMSubDomainHookAdd(dm, DMSubDomainHook_BasicSymplectic, DMSubDomainRestrictHook_BasicSymplectic, ts)); 294e49d4f37SHong Zhang } 2953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 296e49d4f37SHong Zhang } 297e49d4f37SHong Zhang 298d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSReset_BasicSymplectic(TS ts) 299d71ae5a4SJacob Faibussowitsch { 300e49d4f37SHong Zhang TS_BasicSymplectic *bsymp = (TS_BasicSymplectic *)ts->data; 301e49d4f37SHong Zhang 302e49d4f37SHong Zhang PetscFunctionBegin; 3039566063dSJacob Faibussowitsch PetscCall(VecDestroy(&bsymp->update)); 3043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 305e49d4f37SHong Zhang } 306e49d4f37SHong Zhang 307d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSDestroy_BasicSymplectic(TS ts) 308d71ae5a4SJacob Faibussowitsch { 309e49d4f37SHong Zhang PetscFunctionBegin; 3109566063dSJacob Faibussowitsch PetscCall(TSReset_BasicSymplectic(ts)); 3112e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSBasicSymplecticSetType_C", NULL)); 3122e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSBasicSymplecticGetType_C", NULL)); 3139566063dSJacob Faibussowitsch PetscCall(PetscFree(ts->data)); 3143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 315e49d4f37SHong Zhang } 316e49d4f37SHong Zhang 317d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSSetFromOptions_BasicSymplectic(TS ts, PetscOptionItems *PetscOptionsObject) 318d71ae5a4SJacob Faibussowitsch { 319e49d4f37SHong Zhang TS_BasicSymplectic *bsymp = (TS_BasicSymplectic *)ts->data; 320e49d4f37SHong Zhang 321e49d4f37SHong Zhang PetscFunctionBegin; 322d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "Basic symplectic integrator options"); 323e49d4f37SHong Zhang { 324e49d4f37SHong Zhang BasicSymplecticSchemeLink link; 325e49d4f37SHong Zhang PetscInt count, choice; 326e49d4f37SHong Zhang PetscBool flg; 327e49d4f37SHong Zhang const char **namelist; 328e49d4f37SHong Zhang 3299371c9d4SSatish Balay for (link = BasicSymplecticSchemeList, count = 0; link; link = link->next, count++) 3309371c9d4SSatish Balay ; 3319566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(count, (char ***)&namelist)); 332e49d4f37SHong Zhang for (link = BasicSymplecticSchemeList, count = 0; link; link = link->next, count++) namelist[count] = link->sch.name; 3339566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-ts_basicsymplectic_type", "Family of basic symplectic integration method", "TSBasicSymplecticSetType", (const char *const *)namelist, count, bsymp->scheme->name, &choice, &flg)); 3349566063dSJacob Faibussowitsch if (flg) PetscCall(TSBasicSymplecticSetType(ts, namelist[choice])); 3359566063dSJacob Faibussowitsch PetscCall(PetscFree(namelist)); 336e49d4f37SHong Zhang } 337d0609cedSBarry Smith PetscOptionsHeadEnd(); 3383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 339e49d4f37SHong Zhang } 340e49d4f37SHong Zhang 341d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSView_BasicSymplectic(TS ts, PetscViewer viewer) 342d71ae5a4SJacob Faibussowitsch { 343e49d4f37SHong Zhang PetscFunctionBegin; 3443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 345e49d4f37SHong Zhang } 346e49d4f37SHong Zhang 347d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSInterpolate_BasicSymplectic(TS ts, PetscReal t, Vec X) 348d71ae5a4SJacob Faibussowitsch { 349e49d4f37SHong Zhang TS_BasicSymplectic *bsymp = (TS_BasicSymplectic *)ts->data; 350e49d4f37SHong Zhang Vec update = bsymp->update; 351e49d4f37SHong Zhang PetscReal alpha = (ts->ptime - t) / ts->time_step; 352e49d4f37SHong Zhang 353e49d4f37SHong Zhang PetscFunctionBegin; 3549566063dSJacob Faibussowitsch PetscCall(VecWAXPY(X, -ts->time_step, update, ts->vec_sol)); 3559566063dSJacob Faibussowitsch PetscCall(VecAXPBY(X, 1.0 - alpha, alpha, ts->vec_sol)); 3563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 357e49d4f37SHong Zhang } 358e49d4f37SHong Zhang 359d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSComputeLinearStability_BasicSymplectic(TS ts, PetscReal xr, PetscReal xi, PetscReal *yr, PetscReal *yi) 360d71ae5a4SJacob Faibussowitsch { 361e49d4f37SHong Zhang PetscFunctionBegin; 362e49d4f37SHong Zhang *yr = 1.0 + xr; 363e49d4f37SHong Zhang *yi = xi; 3643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 365e49d4f37SHong Zhang } 366e49d4f37SHong Zhang 367e49d4f37SHong Zhang /*@C 368e49d4f37SHong Zhang TSBasicSymplecticSetType - Set the type of the basic symplectic method 369e49d4f37SHong Zhang 370c3339decSBarry Smith Logically Collective 371e49d4f37SHong Zhang 372d8d19677SJose E. Roman Input Parameters: 373e49d4f37SHong Zhang + ts - timestepping context 374e49d4f37SHong Zhang - bsymptype - type of the symplectic scheme 375e49d4f37SHong Zhang 376bcf0153eSBarry Smith Options Database Key: 377147403d9SBarry Smith . -ts_basicsymplectic_type <scheme> - select the scheme 378e49d4f37SHong Zhang 379bcf0153eSBarry Smith Level: intermediate 380bcf0153eSBarry Smith 381bcf0153eSBarry Smith Note: 382*1d27aa22SBarry Smith The symplectic solver always expects a two-way splitting with the split names being "position" and "momentum". 383*1d27aa22SBarry Smith Each split is associated with an `IS` object and a sub-`TS` 384147403d9SBarry Smith that is intended to store the user-provided RHS function. 385e49d4f37SHong Zhang 38642747ad1SJacob Faibussowitsch .seealso: [](ch_ts), `TSBASICSYMPLECTIC`, `TSBasicSymplecticType` 387e49d4f37SHong Zhang @*/ 388d71ae5a4SJacob Faibussowitsch PetscErrorCode TSBasicSymplecticSetType(TS ts, TSBasicSymplecticType bsymptype) 389d71ae5a4SJacob Faibussowitsch { 390e49d4f37SHong Zhang PetscFunctionBegin; 391e49d4f37SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 392cac4c232SBarry Smith PetscTryMethod(ts, "TSBasicSymplecticSetType_C", (TS, TSBasicSymplecticType), (ts, bsymptype)); 3933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 394e49d4f37SHong Zhang } 395e49d4f37SHong Zhang 396e49d4f37SHong Zhang /*@C 397e49d4f37SHong Zhang TSBasicSymplecticGetType - Get the type of the basic symplectic method 398e49d4f37SHong Zhang 399c3339decSBarry Smith Logically Collective 400e49d4f37SHong Zhang 401d8d19677SJose E. Roman Input Parameters: 402e49d4f37SHong Zhang + ts - timestepping context 403e49d4f37SHong Zhang - bsymptype - type of the basic symplectic scheme 404e49d4f37SHong Zhang 405e49d4f37SHong Zhang Level: intermediate 406bcf0153eSBarry Smith 4071cc06b55SBarry Smith .seealso: [](ch_ts), `TSBASICSYMPLECTIC`, `TSBasicSymplecticType`, `TSBasicSymplecticSetType()` 408e49d4f37SHong Zhang @*/ 409d71ae5a4SJacob Faibussowitsch PetscErrorCode TSBasicSymplecticGetType(TS ts, TSBasicSymplecticType *bsymptype) 410d71ae5a4SJacob Faibussowitsch { 411e49d4f37SHong Zhang PetscFunctionBegin; 412e49d4f37SHong Zhang PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 413cac4c232SBarry Smith PetscUseMethod(ts, "TSBasicSymplecticGetType_C", (TS, TSBasicSymplecticType *), (ts, bsymptype)); 4143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 415e49d4f37SHong Zhang } 416e49d4f37SHong Zhang 417d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSBasicSymplecticSetType_BasicSymplectic(TS ts, TSBasicSymplecticType bsymptype) 418d71ae5a4SJacob Faibussowitsch { 419e49d4f37SHong Zhang TS_BasicSymplectic *bsymp = (TS_BasicSymplectic *)ts->data; 420e49d4f37SHong Zhang BasicSymplecticSchemeLink link; 421e49d4f37SHong Zhang PetscBool match; 422e49d4f37SHong Zhang 423e49d4f37SHong Zhang PetscFunctionBegin; 424e49d4f37SHong Zhang if (bsymp->scheme) { 4259566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(bsymp->scheme->name, bsymptype, &match)); 4263ba16761SJacob Faibussowitsch if (match) PetscFunctionReturn(PETSC_SUCCESS); 427e49d4f37SHong Zhang } 428e49d4f37SHong Zhang for (link = BasicSymplecticSchemeList; link; link = link->next) { 4299566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(link->sch.name, bsymptype, &match)); 430e49d4f37SHong Zhang if (match) { 431e49d4f37SHong Zhang bsymp->scheme = &link->sch; 4323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 433e49d4f37SHong Zhang } 434e49d4f37SHong Zhang } 43598921bdaSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_UNKNOWN_TYPE, "Could not find '%s'", bsymptype); 436e49d4f37SHong Zhang } 437e49d4f37SHong Zhang 438d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSBasicSymplecticGetType_BasicSymplectic(TS ts, TSBasicSymplecticType *bsymptype) 439d71ae5a4SJacob Faibussowitsch { 440e49d4f37SHong Zhang TS_BasicSymplectic *bsymp = (TS_BasicSymplectic *)ts->data; 441e49d4f37SHong Zhang 442e49d4f37SHong Zhang PetscFunctionBegin; 443e49d4f37SHong Zhang *bsymptype = bsymp->scheme->name; 4443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 445e49d4f37SHong Zhang } 446e49d4f37SHong Zhang 447e49d4f37SHong Zhang /*MC 448*1d27aa22SBarry Smith TSBASICSYMPLECTIC - ODE solver using basic symplectic integration schemes <https://en.wikipedia.org/wiki/Symplectic_integrator> 449e49d4f37SHong Zhang 450bcf0153eSBarry Smith These methods are intended for separable Hamiltonian systems 451*1d27aa22SBarry Smith 452*1d27aa22SBarry Smith $$ 453*1d27aa22SBarry Smith \begin{align*} 454*1d27aa22SBarry Smith qdot = dH(q,p,t)/dp \\ 455bcf0153eSBarry Smith pdot = -dH(q,p,t)/dq 456*1d27aa22SBarry Smith \end{align*} 457*1d27aa22SBarry Smith $$ 458e49d4f37SHong Zhang 459e49d4f37SHong Zhang where the Hamiltonian can be split into the sum of kinetic energy and potential energy 460*1d27aa22SBarry Smith 461*1d27aa22SBarry Smith $$ 462bcf0153eSBarry Smith H(q,p,t) = T(p,t) + V(q,t). 463*1d27aa22SBarry Smith $$ 464e49d4f37SHong Zhang 465145b44c9SPierre Jolivet As a result, the system can be generally represented by 466*1d27aa22SBarry Smith 467*1d27aa22SBarry Smith $$ 468*1d27aa22SBarry Smith \begin{align*} 469*1d27aa22SBarry Smith qdot = f(p,t) = dT(p,t)/dp \\ 470bcf0153eSBarry Smith pdot = g(q,t) = -dV(q,t)/dq 471*1d27aa22SBarry Smith \end{align*} 472*1d27aa22SBarry Smith $$ 473e49d4f37SHong Zhang 474e49d4f37SHong Zhang and solved iteratively with 475*1d27aa22SBarry Smith 476*1d27aa22SBarry Smith $$ 477*1d27aa22SBarry Smith \begin{align*} 478*1d27aa22SBarry Smith q_new = q_old + d_i*h*f(p_old,t_old) \\ 479*1d27aa22SBarry Smith t_new = t_old + d_i*h \\ 480*1d27aa22SBarry Smith p_new = p_old + c_i*h*g(p_new,t_new) \\ 481bcf0153eSBarry Smith i = 0,1,...,n. 482*1d27aa22SBarry Smith \end{align*} 483*1d27aa22SBarry Smith $$ 484e49d4f37SHong Zhang 485bcf0153eSBarry Smith The solution vector should contain both q and p, which correspond to (generalized) position and momentum respectively. Note that the momentum component 486bcf0153eSBarry Smith could simply be velocity in some representations. The symplectic solver always expects a two-way splitting with the split names being "position" and "momentum". 487bcf0153eSBarry Smith Each split is associated with an `IS` object and a sub-`TS` that is intended to store the user-provided RHS function. 488e49d4f37SHong Zhang 489e49d4f37SHong Zhang Level: beginner 490e49d4f37SHong Zhang 4911cc06b55SBarry Smith .seealso: [](ch_ts), `TSCreate()`, `TSSetType()`, `TSRHSSplitSetIS()`, `TSRHSSplitSetRHSFunction()`, `TSType` 492e49d4f37SHong Zhang M*/ 493d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode TSCreate_BasicSymplectic(TS ts) 494d71ae5a4SJacob Faibussowitsch { 495e49d4f37SHong Zhang TS_BasicSymplectic *bsymp; 496e49d4f37SHong Zhang 497e49d4f37SHong Zhang PetscFunctionBegin; 4989566063dSJacob Faibussowitsch PetscCall(TSBasicSymplecticInitializePackage()); 4994dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&bsymp)); 500e49d4f37SHong Zhang ts->data = (void *)bsymp; 501e49d4f37SHong Zhang 502e49d4f37SHong Zhang ts->ops->setup = TSSetUp_BasicSymplectic; 503e49d4f37SHong Zhang ts->ops->step = TSStep_BasicSymplectic; 504e49d4f37SHong Zhang ts->ops->reset = TSReset_BasicSymplectic; 505e49d4f37SHong Zhang ts->ops->destroy = TSDestroy_BasicSymplectic; 506e49d4f37SHong Zhang ts->ops->setfromoptions = TSSetFromOptions_BasicSymplectic; 507e49d4f37SHong Zhang ts->ops->view = TSView_BasicSymplectic; 508e49d4f37SHong Zhang ts->ops->interpolate = TSInterpolate_BasicSymplectic; 509e49d4f37SHong Zhang ts->ops->linearstability = TSComputeLinearStability_BasicSymplectic; 510e49d4f37SHong Zhang 5119566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSBasicSymplecticSetType_C", TSBasicSymplecticSetType_BasicSymplectic)); 5129566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ts, "TSBasicSymplecticGetType_C", TSBasicSymplecticGetType_BasicSymplectic)); 513e49d4f37SHong Zhang 5149566063dSJacob Faibussowitsch PetscCall(TSBasicSymplecticSetType(ts, TSBasicSymplecticDefault)); 5153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 516e49d4f37SHong Zhang } 517