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 34e49d4f37SHong Zhang Level: intermediate 35e49d4f37SHong Zhang .seealso: TSBASICSYMPLECTIC 36e49d4f37SHong Zhang M*/ 37e49d4f37SHong Zhang 38e49d4f37SHong Zhang /*MC 39e49d4f37SHong Zhang TSBASICSYMPLECTICVELVERLET - second order Velocity Verlet method (leapfrog method with starting process and determing velocity and position at the same time) 40e49d4f37SHong Zhang Level: intermediate 41e49d4f37SHong Zhang .seealso: TSBASICSYMPLECTIC 42e49d4f37SHong Zhang M*/ 43e49d4f37SHong Zhang 44e49d4f37SHong Zhang /*@C 45e49d4f37SHong Zhang TSBasicSymplecticRegisterAll - Registers all of the basic symplectic integration methods in TSBasicSymplectic 46e49d4f37SHong Zhang 47e49d4f37SHong Zhang Not Collective, but should be called by all processes which will need the schemes to be registered 48e49d4f37SHong Zhang 49e49d4f37SHong Zhang Level: advanced 50e49d4f37SHong Zhang 51e49d4f37SHong Zhang .keywords: TS, TSBASICSYMPLECTIC, register, all 52e49d4f37SHong Zhang 53e49d4f37SHong Zhang .seealso: TSBasicSymplecticRegisterDestroy() 54e49d4f37SHong Zhang @*/ 55e49d4f37SHong Zhang PetscErrorCode TSBasicSymplecticRegisterAll(void) 56e49d4f37SHong Zhang { 57e49d4f37SHong Zhang PetscErrorCode ierr; 58e49d4f37SHong Zhang 59e49d4f37SHong Zhang PetscFunctionBegin; 60e49d4f37SHong Zhang if (TSBasicSymplecticRegisterAllCalled) PetscFunctionReturn(0); 61e49d4f37SHong Zhang TSBasicSymplecticRegisterAllCalled = PETSC_TRUE; 62e49d4f37SHong Zhang { 63e49d4f37SHong Zhang PetscReal c[1] = {1.0},d[1] = {1.0}; 64e49d4f37SHong Zhang ierr = TSBasicSymplecticRegister(TSBASICSYMPLECTICSIEULER,1,1,c,d);CHKERRQ(ierr); 65e49d4f37SHong Zhang } 66e49d4f37SHong Zhang { 67e49d4f37SHong Zhang PetscReal c[2] = {0,1.0},d[2] = {0.5,0.5}; 68e49d4f37SHong Zhang ierr = TSBasicSymplecticRegister(TSBASICSYMPLECTICVELVERLET,2,2,c,d);CHKERRQ(ierr); 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}; 72e49d4f37SHong Zhang ierr = TSBasicSymplecticRegister(TSBASICSYMPLECTIC3,3,3,c,d);CHKERRQ(ierr); 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}; 77e49d4f37SHong Zhang ierr = TSBasicSymplecticRegister(TSBASICSYMPLECTIC4,4,4,c,d);CHKERRQ(ierr); 78e49d4f37SHong Zhang } 79e49d4f37SHong Zhang PetscFunctionReturn(0); 80e49d4f37SHong Zhang } 81e49d4f37SHong Zhang 82e49d4f37SHong Zhang /*@C 83e49d4f37SHong Zhang 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 89e49d4f37SHong Zhang .keywords: TSBasicSymplectic, register, destroy 90e49d4f37SHong Zhang .seealso: TSBasicSymplecticRegister(), TSBasicSymplecticRegisterAll() 91e49d4f37SHong Zhang @*/ 92e49d4f37SHong Zhang PetscErrorCode TSBasicSymplecticRegisterDestroy(void) 93e49d4f37SHong Zhang { 94e49d4f37SHong Zhang PetscErrorCode ierr; 95e49d4f37SHong Zhang BasicSymplecticSchemeLink link; 96e49d4f37SHong Zhang 97e49d4f37SHong Zhang PetscFunctionBegin; 98e49d4f37SHong Zhang while ((link = BasicSymplecticSchemeList)) { 99e49d4f37SHong Zhang BasicSymplecticScheme scheme = &link->sch; 100e49d4f37SHong Zhang BasicSymplecticSchemeList = link->next; 101e49d4f37SHong Zhang ierr = PetscFree2(scheme->c,scheme->d);CHKERRQ(ierr); 102e49d4f37SHong Zhang ierr = PetscFree(scheme->name);CHKERRQ(ierr); 103e49d4f37SHong Zhang ierr = PetscFree(link);CHKERRQ(ierr); 104e49d4f37SHong Zhang } 105e49d4f37SHong Zhang TSBasicSymplecticRegisterAllCalled = PETSC_FALSE; 106e49d4f37SHong Zhang PetscFunctionReturn(0); 107e49d4f37SHong Zhang } 108e49d4f37SHong Zhang 109e49d4f37SHong Zhang /*@C 110e49d4f37SHong Zhang TSBasicSymplecticInitializePackage - This function initializes everything in the TSBasicSymplectic package. It is called 111*8a690491SBarry Smith from TSInitializePackage(). 112e49d4f37SHong Zhang 113e49d4f37SHong Zhang Level: developer 114e49d4f37SHong Zhang 115e49d4f37SHong Zhang .keywords: TS, TSBasicSymplectic, initialize, package 116e49d4f37SHong Zhang .seealso: PetscInitialize() 117e49d4f37SHong Zhang @*/ 118e49d4f37SHong Zhang PetscErrorCode TSBasicSymplecticInitializePackage(void) 119e49d4f37SHong Zhang { 120e49d4f37SHong Zhang PetscErrorCode ierr; 121e49d4f37SHong Zhang 122e49d4f37SHong Zhang PetscFunctionBegin; 123e49d4f37SHong Zhang if (TSBasicSymplecticPackageInitialized) PetscFunctionReturn(0); 124e49d4f37SHong Zhang TSBasicSymplecticPackageInitialized = PETSC_TRUE; 125e49d4f37SHong Zhang ierr = TSBasicSymplecticRegisterAll();CHKERRQ(ierr); 126e49d4f37SHong Zhang ierr = PetscRegisterFinalize(TSBasicSymplecticFinalizePackage);CHKERRQ(ierr); 127e49d4f37SHong Zhang PetscFunctionReturn(0); 128e49d4f37SHong Zhang } 129e49d4f37SHong Zhang 130e49d4f37SHong Zhang /*@C 131e49d4f37SHong Zhang TSBasicSymplecticFinalizePackage - This function destroys everything in the TSBasicSymplectic package. It is 132e49d4f37SHong Zhang called from PetscFinalize(). 133e49d4f37SHong Zhang 134e49d4f37SHong Zhang Level: developer 135e49d4f37SHong Zhang 136e49d4f37SHong Zhang .keywords: Petsc, destroy, package 137e49d4f37SHong Zhang .seealso: PetscFinalize() 138e49d4f37SHong Zhang @*/ 139e49d4f37SHong Zhang PetscErrorCode TSBasicSymplecticFinalizePackage(void) 140e49d4f37SHong Zhang { 141e49d4f37SHong Zhang PetscErrorCode ierr; 142e49d4f37SHong Zhang 143e49d4f37SHong Zhang PetscFunctionBegin; 144e49d4f37SHong Zhang TSBasicSymplecticPackageInitialized = PETSC_FALSE; 145e49d4f37SHong Zhang ierr = TSBasicSymplecticRegisterDestroy();CHKERRQ(ierr); 146e49d4f37SHong Zhang PetscFunctionReturn(0); 147e49d4f37SHong Zhang } 148e49d4f37SHong Zhang 149e49d4f37SHong Zhang /*@C 150e49d4f37SHong Zhang TSBasicSymplecticRegister - register a basic symplectic integration scheme by providing the coefficients. 151e49d4f37SHong Zhang 152e49d4f37SHong Zhang Not Collective, but the same schemes should be registered on all processes on which they will be used 153e49d4f37SHong Zhang 154e49d4f37SHong Zhang Input Parameters: 155e49d4f37SHong Zhang + name - identifier for method 156e49d4f37SHong Zhang . order - approximation order of method 157e49d4f37SHong Zhang . s - number of stages, this is the dimension of the matrices below 158e49d4f37SHong Zhang . c - coefficients for updating generalized position (dimension s) 159e49d4f37SHong Zhang - d - coefficients for updating generalized momentum (dimension s) 160e49d4f37SHong Zhang 161e49d4f37SHong Zhang Notes: 162e49d4f37SHong Zhang Several symplectic methods are provided, this function is only needed to create new methods. 163e49d4f37SHong Zhang 164e49d4f37SHong Zhang Level: advanced 165e49d4f37SHong Zhang 166e49d4f37SHong Zhang .keywords: TS, register 167e49d4f37SHong Zhang 168e49d4f37SHong Zhang .seealso: TSBasicSymplectic 169e49d4f37SHong Zhang @*/ 170e49d4f37SHong Zhang PetscErrorCode TSBasicSymplecticRegister(TSRosWType name,PetscInt order,PetscInt s,PetscReal c[],PetscReal d[]) 171e49d4f37SHong Zhang { 172e49d4f37SHong Zhang BasicSymplecticSchemeLink link; 173e49d4f37SHong Zhang BasicSymplecticScheme scheme; 174e49d4f37SHong Zhang PetscErrorCode ierr; 175e49d4f37SHong Zhang 176e49d4f37SHong Zhang PetscFunctionBegin; 177e49d4f37SHong Zhang PetscValidCharPointer(name,1); 178e49d4f37SHong Zhang PetscValidPointer(c,4); 179e49d4f37SHong Zhang PetscValidPointer(d,4); 180e49d4f37SHong Zhang 1811d36bdfdSBarry Smith ierr = TSBasicSymplecticInitializePackage();CHKERRQ(ierr); 182e49d4f37SHong Zhang ierr = PetscCalloc1(1,&link);CHKERRQ(ierr); 183e49d4f37SHong Zhang scheme = &link->sch; 184e49d4f37SHong Zhang ierr = PetscStrallocpy(name,&scheme->name);CHKERRQ(ierr); 185e49d4f37SHong Zhang scheme->order = order; 186e49d4f37SHong Zhang scheme->s = s; 187e49d4f37SHong Zhang ierr = PetscMalloc2(s,&scheme->c,s,&scheme->d);CHKERRQ(ierr); 188e49d4f37SHong Zhang ierr = PetscMemcpy(scheme->c,c,s*sizeof(c[0]));CHKERRQ(ierr); 189e49d4f37SHong Zhang ierr = PetscMemcpy(scheme->d,d,s*sizeof(d[0]));CHKERRQ(ierr); 190e49d4f37SHong Zhang link->next = BasicSymplecticSchemeList; 191e49d4f37SHong Zhang BasicSymplecticSchemeList = link; 192e49d4f37SHong Zhang PetscFunctionReturn(0); 193e49d4f37SHong Zhang } 194e49d4f37SHong Zhang 195e49d4f37SHong Zhang /* 196e49d4f37SHong Zhang The simplified form of the equations are: 197e49d4f37SHong Zhang 198e49d4f37SHong Zhang $ p_{i+1} = p_i + c_i*g(q_i)*h 199e49d4f37SHong Zhang $ q_{i+1} = q_i + d_i*f(p_{i+1},t_{i+1})*h 200e49d4f37SHong Zhang 201e49d4f37SHong Zhang Several symplectic integrators are given below. An illustrative way to use them is to consider a particle with position q and velocity p. 202e49d4f37SHong Zhang 203e49d4f37SHong Zhang To apply a timestep with values c_{1,2},d_{1,2} to the particle, carry out the following steps: 204e49d4f37SHong Zhang 205e49d4f37SHong Zhang - Update the velocity of the particle by adding to it its acceleration multiplied by c_1 206e49d4f37SHong Zhang - Update the position of the particle by adding to it its (updated) velocity multiplied by d_1 207e49d4f37SHong Zhang - Update the velocity of the particle by adding to it its acceleration (at the updated position) multiplied by c_2 208e49d4f37SHong Zhang - Update the position of the particle by adding to it its (double-updated) velocity multiplied by d_2 209e49d4f37SHong Zhang 210e49d4f37SHong Zhang */ 211e49d4f37SHong Zhang static PetscErrorCode TSStep_BasicSymplectic(TS ts) 212e49d4f37SHong Zhang { 213e49d4f37SHong Zhang TS_BasicSymplectic *bsymp = (TS_BasicSymplectic*)ts->data; 214e49d4f37SHong Zhang BasicSymplecticScheme scheme = bsymp->scheme; 215e49d4f37SHong Zhang Vec solution = ts->vec_sol,update = bsymp->update,q,p,q_update,p_update; 216e49d4f37SHong Zhang IS is_q = bsymp->is_q,is_p = bsymp->is_p; 217e49d4f37SHong Zhang TS subts_q = bsymp->subts_q,subts_p = bsymp->subts_p; 218e49d4f37SHong Zhang PetscBool stageok; 219e49d4f37SHong Zhang PetscReal next_time_step = ts->time_step; 220e49d4f37SHong Zhang PetscInt iter; 221e49d4f37SHong Zhang PetscErrorCode ierr; 222e49d4f37SHong Zhang 223e49d4f37SHong Zhang PetscFunctionBegin; 224e49d4f37SHong Zhang ierr = VecGetSubVector(solution,is_q,&q);CHKERRQ(ierr); 225e49d4f37SHong Zhang ierr = VecGetSubVector(solution,is_p,&p);CHKERRQ(ierr); 226e49d4f37SHong Zhang ierr = VecGetSubVector(update,is_q,&q_update);CHKERRQ(ierr); 227e49d4f37SHong Zhang ierr = VecGetSubVector(update,is_p,&p_update);CHKERRQ(ierr); 228e49d4f37SHong Zhang 229e49d4f37SHong Zhang for (iter = 0;iter<scheme->s;iter++) { 230e49d4f37SHong Zhang ierr = TSPreStage(ts,ts->ptime);CHKERRQ(ierr); 231e49d4f37SHong Zhang /* update velocity p */ 232e49d4f37SHong Zhang if (scheme->c[iter]) { 233e49d4f37SHong Zhang ierr = TSComputeRHSFunction(subts_p,ts->ptime,q,p_update);CHKERRQ(ierr); 234e49d4f37SHong Zhang ierr = VecAXPY(p,scheme->c[iter]*ts->time_step,p_update);CHKERRQ(ierr); 235e49d4f37SHong Zhang } 236e49d4f37SHong Zhang /* update position q */ 237e49d4f37SHong Zhang if (scheme->d[iter]) { 238e49d4f37SHong Zhang ierr = TSComputeRHSFunction(subts_q,ts->ptime,p,q_update);CHKERRQ(ierr); 239e49d4f37SHong Zhang ierr = VecAXPY(q,scheme->d[iter]*ts->time_step,q_update);CHKERRQ(ierr); 240e49d4f37SHong Zhang ts->ptime = ts->ptime+scheme->d[iter]*ts->time_step; 241e49d4f37SHong Zhang } 242e49d4f37SHong Zhang ierr = TSPostStage(ts,ts->ptime,0,&solution);CHKERRQ(ierr); 243e49d4f37SHong Zhang ierr = TSAdaptCheckStage(ts->adapt,ts,ts->ptime,solution,&stageok);CHKERRQ(ierr); 244e49d4f37SHong Zhang if(!stageok) {ts->reason = TS_DIVERGED_STEP_REJECTED; PetscFunctionReturn(0);} 245e49d4f37SHong Zhang ierr = TSFunctionDomainError(ts,ts->ptime+ts->time_step,update,&stageok);CHKERRQ(ierr); 246e49d4f37SHong Zhang if(!stageok) {ts->reason = TS_DIVERGED_STEP_REJECTED; PetscFunctionReturn(0);} 247e49d4f37SHong Zhang } 248e49d4f37SHong Zhang 249e49d4f37SHong Zhang ts->time_step = next_time_step; 250e49d4f37SHong Zhang ierr = VecRestoreSubVector(solution,is_q,&q);CHKERRQ(ierr); 251e49d4f37SHong Zhang ierr = VecRestoreSubVector(solution,is_p,&p);CHKERRQ(ierr); 252e49d4f37SHong Zhang ierr = VecRestoreSubVector(update,is_q,&q_update);CHKERRQ(ierr); 253e49d4f37SHong Zhang ierr = VecRestoreSubVector(update,is_p,&p_update);CHKERRQ(ierr); 254e49d4f37SHong Zhang PetscFunctionReturn(0); 255e49d4f37SHong Zhang } 256e49d4f37SHong Zhang 257e49d4f37SHong Zhang static PetscErrorCode DMCoarsenHook_BasicSymplectic(DM fine,DM coarse,void *ctx) 258e49d4f37SHong Zhang { 259e49d4f37SHong Zhang PetscFunctionBegin; 260e49d4f37SHong Zhang PetscFunctionReturn(0); 261e49d4f37SHong Zhang } 262e49d4f37SHong Zhang 263e49d4f37SHong Zhang static PetscErrorCode DMRestrictHook_BasicSymplectic(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse,void *ctx) 264e49d4f37SHong Zhang { 265e49d4f37SHong Zhang PetscFunctionBegin; 266e49d4f37SHong Zhang PetscFunctionReturn(0); 267e49d4f37SHong Zhang } 268e49d4f37SHong Zhang 269e49d4f37SHong Zhang static PetscErrorCode DMSubDomainHook_BasicSymplectic(DM dm,DM subdm,void *ctx) 270e49d4f37SHong Zhang { 271e49d4f37SHong Zhang PetscFunctionBegin; 272e49d4f37SHong Zhang PetscFunctionReturn(0); 273e49d4f37SHong Zhang } 274e49d4f37SHong Zhang 275e49d4f37SHong Zhang static PetscErrorCode DMSubDomainRestrictHook_BasicSymplectic(DM dm,VecScatter gscat,VecScatter lscat,DM subdm,void *ctx) 276e49d4f37SHong Zhang { 277e49d4f37SHong Zhang 278e49d4f37SHong Zhang PetscFunctionBegin; 279e49d4f37SHong Zhang PetscFunctionReturn(0); 280e49d4f37SHong Zhang } 281e49d4f37SHong Zhang 282e49d4f37SHong Zhang static PetscErrorCode TSSetUp_BasicSymplectic(TS ts) 283e49d4f37SHong Zhang { 284e49d4f37SHong Zhang TS_BasicSymplectic *bsymp = (TS_BasicSymplectic*)ts->data; 285e49d4f37SHong Zhang DM dm; 286e49d4f37SHong Zhang PetscErrorCode ierr; 287e49d4f37SHong Zhang 288e49d4f37SHong Zhang PetscFunctionBegin; 289e49d4f37SHong Zhang ierr = TSRHSSplitGetIS(ts,"position",&bsymp->is_q);CHKERRQ(ierr); 290e49d4f37SHong Zhang ierr = TSRHSSplitGetIS(ts,"momentum",&bsymp->is_p);CHKERRQ(ierr); 291e49d4f37SHong Zhang if (!bsymp->is_q || !bsymp->is_p) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must set up RHSSplits with TSRHSSplitSetIS() using split names positon and momentum respectively in order to use -ts_type basicsymplectic"); 292e49d4f37SHong Zhang ierr = TSRHSSplitGetSubTS(ts,"position",&bsymp->subts_q);CHKERRQ(ierr); 293e49d4f37SHong Zhang ierr = TSRHSSplitGetSubTS(ts,"momentum",&bsymp->subts_p);CHKERRQ(ierr); 294e49d4f37SHong Zhang if (!bsymp->subts_q || !bsymp->subts_p) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must set up the RHSFunctions for position and momentum using TSRHSSplitSetRHSFunction() or calling TSSetRHSFunction() for each sub-TS"); 295e49d4f37SHong Zhang 296e49d4f37SHong Zhang ierr = VecDuplicate(ts->vec_sol,&bsymp->update);CHKERRQ(ierr); 297e49d4f37SHong Zhang 298e49d4f37SHong Zhang ierr = TSGetAdapt(ts,&ts->adapt);CHKERRQ(ierr); 299e49d4f37SHong Zhang ierr = TSAdaptCandidatesClear(ts->adapt);CHKERRQ(ierr); /* make sure to use fixed time stepping */ 300e49d4f37SHong Zhang ierr = TSGetDM(ts,&dm);CHKERRQ(ierr); 301e49d4f37SHong Zhang if (dm) { 302e49d4f37SHong Zhang ierr = DMCoarsenHookAdd(dm,DMCoarsenHook_BasicSymplectic,DMRestrictHook_BasicSymplectic,ts);CHKERRQ(ierr); 303e49d4f37SHong Zhang ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_BasicSymplectic,DMSubDomainRestrictHook_BasicSymplectic,ts);CHKERRQ(ierr); 304e49d4f37SHong Zhang } 305e49d4f37SHong Zhang PetscFunctionReturn(0); 306e49d4f37SHong Zhang } 307e49d4f37SHong Zhang 308e49d4f37SHong Zhang static PetscErrorCode TSReset_BasicSymplectic(TS ts) 309e49d4f37SHong Zhang { 310e49d4f37SHong Zhang TS_BasicSymplectic *bsymp = (TS_BasicSymplectic*)ts->data; 311e49d4f37SHong Zhang PetscErrorCode ierr; 312e49d4f37SHong Zhang 313e49d4f37SHong Zhang PetscFunctionBegin; 314e49d4f37SHong Zhang ierr = VecDestroy(&bsymp->update);CHKERRQ(ierr); 315e49d4f37SHong Zhang PetscFunctionReturn(0); 316e49d4f37SHong Zhang } 317e49d4f37SHong Zhang 318e49d4f37SHong Zhang static PetscErrorCode TSDestroy_BasicSymplectic(TS ts) 319e49d4f37SHong Zhang { 320e49d4f37SHong Zhang PetscErrorCode ierr; 321e49d4f37SHong Zhang 322e49d4f37SHong Zhang PetscFunctionBegin; 323e49d4f37SHong Zhang ierr = TSReset_BasicSymplectic(ts);CHKERRQ(ierr); 324e49d4f37SHong Zhang ierr = PetscFree(ts->data);CHKERRQ(ierr); 325e49d4f37SHong Zhang PetscFunctionReturn(0); 326e49d4f37SHong Zhang } 327e49d4f37SHong Zhang 328e49d4f37SHong Zhang static PetscErrorCode TSSetFromOptions_BasicSymplectic(PetscOptionItems *PetscOptionsObject,TS ts) 329e49d4f37SHong Zhang { 330e49d4f37SHong Zhang TS_BasicSymplectic *bsymp = (TS_BasicSymplectic*)ts->data; 331e49d4f37SHong Zhang PetscErrorCode ierr; 332e49d4f37SHong Zhang 333e49d4f37SHong Zhang PetscFunctionBegin; 334e49d4f37SHong Zhang ierr = PetscOptionsHead(PetscOptionsObject,"Basic symplectic integrator options");CHKERRQ(ierr); 335e49d4f37SHong Zhang { 336e49d4f37SHong Zhang BasicSymplecticSchemeLink link; 337e49d4f37SHong Zhang PetscInt count,choice; 338e49d4f37SHong Zhang PetscBool flg; 339e49d4f37SHong Zhang const char **namelist; 340e49d4f37SHong Zhang 341e49d4f37SHong Zhang for (link=BasicSymplecticSchemeList,count=0; link; link=link->next,count++) ; 342e49d4f37SHong Zhang ierr = PetscMalloc1(count,(char***)&namelist);CHKERRQ(ierr); 343e49d4f37SHong Zhang for (link=BasicSymplecticSchemeList,count=0; link; link=link->next,count++) namelist[count] = link->sch.name; 344e49d4f37SHong Zhang ierr = PetscOptionsEList("-ts_basicsymplectic_type","Family of basic symplectic integration method","TSBasicSymplecticSetType",(const char*const*)namelist,count,bsymp->scheme->name,&choice,&flg);CHKERRQ(ierr); 345e49d4f37SHong Zhang if (flg) {ierr = TSBasicSymplecticSetType(ts,namelist[choice]);CHKERRQ(ierr);} 346e49d4f37SHong Zhang ierr = PetscFree(namelist);CHKERRQ(ierr); 347e49d4f37SHong Zhang } 348e49d4f37SHong Zhang ierr = PetscOptionsTail();CHKERRQ(ierr); 349e49d4f37SHong Zhang PetscFunctionReturn(0); 350e49d4f37SHong Zhang } 351e49d4f37SHong Zhang 352e49d4f37SHong Zhang static PetscErrorCode TSView_BasicSymplectic(TS ts,PetscViewer viewer) 353e49d4f37SHong Zhang { 354e49d4f37SHong Zhang PetscFunctionBegin; 355e49d4f37SHong Zhang PetscFunctionReturn(0); 356e49d4f37SHong Zhang } 357e49d4f37SHong Zhang 358e49d4f37SHong Zhang static PetscErrorCode TSInterpolate_BasicSymplectic(TS ts,PetscReal t,Vec X) 359e49d4f37SHong Zhang { 360e49d4f37SHong Zhang TS_BasicSymplectic *bsymp = (TS_BasicSymplectic*)ts->data; 361e49d4f37SHong Zhang Vec update = bsymp->update; 362e49d4f37SHong Zhang PetscReal alpha = (ts->ptime - t)/ts->time_step; 363e49d4f37SHong Zhang PetscErrorCode ierr; 364e49d4f37SHong Zhang 365e49d4f37SHong Zhang PetscFunctionBegin; 366e49d4f37SHong Zhang ierr = VecWAXPY(X,-ts->time_step,update,ts->vec_sol);CHKERRQ(ierr); 367e49d4f37SHong Zhang ierr = VecAXPBY(X,1.0-alpha,alpha,ts->vec_sol);CHKERRQ(ierr); 368e49d4f37SHong Zhang PetscFunctionReturn(0); 369e49d4f37SHong Zhang } 370e49d4f37SHong Zhang 371e49d4f37SHong Zhang static PetscErrorCode TSComputeLinearStability_BasicSymplectic(TS ts,PetscReal xr,PetscReal xi,PetscReal *yr,PetscReal *yi) 372e49d4f37SHong Zhang { 373e49d4f37SHong Zhang PetscFunctionBegin; 374e49d4f37SHong Zhang *yr = 1.0 + xr; 375e49d4f37SHong Zhang *yi = xi; 376e49d4f37SHong Zhang PetscFunctionReturn(0); 377e49d4f37SHong Zhang } 378e49d4f37SHong Zhang 379e49d4f37SHong Zhang /*@C 380e49d4f37SHong Zhang TSBasicSymplecticSetType - Set the type of the basic symplectic method 381e49d4f37SHong Zhang 382e49d4f37SHong Zhang Logically Collective on TS 383e49d4f37SHong Zhang 384e49d4f37SHong Zhang Input Parameter: 385e49d4f37SHong Zhang + ts - timestepping context 386e49d4f37SHong Zhang - bsymptype - type of the symplectic scheme 387e49d4f37SHong Zhang 388e49d4f37SHong Zhang Options Database: 389e49d4f37SHong Zhang . -ts_basicsymplectic_type <scheme> 390e49d4f37SHong Zhang 391e49d4f37SHong Zhang Notes: 392e49d4f37SHong Zhang The symplectic solver always expects a two-way splitting with the split names being "position" and "momentum". Each split is associated with an IS object and a sub-TS that is intended to store the user-provided RHS function. 393e49d4f37SHong Zhang 394e49d4f37SHong Zhang Level: intermediate 395e49d4f37SHong Zhang @*/ 396e49d4f37SHong Zhang PetscErrorCode TSBasicSymplecticSetType(TS ts,TSBasicSymplecticType bsymptype) 397e49d4f37SHong Zhang { 398e49d4f37SHong Zhang PetscErrorCode ierr; 399e49d4f37SHong Zhang 400e49d4f37SHong Zhang PetscFunctionBegin; 401e49d4f37SHong Zhang PetscValidHeaderSpecific(ts,TS_CLASSID,1); 402e49d4f37SHong Zhang ierr = PetscTryMethod(ts,"TSBasicSymplecticSetType_C",(TS,TSBasicSymplecticType),(ts,bsymptype));CHKERRQ(ierr); 403e49d4f37SHong Zhang PetscFunctionReturn(0); 404e49d4f37SHong Zhang } 405e49d4f37SHong Zhang 406e49d4f37SHong Zhang /*@C 407e49d4f37SHong Zhang TSBasicSymplecticGetType - Get the type of the basic symplectic method 408e49d4f37SHong Zhang 409e49d4f37SHong Zhang Logically Collective on TS 410e49d4f37SHong Zhang 411e49d4f37SHong Zhang Input Parameter: 412e49d4f37SHong Zhang + ts - timestepping context 413e49d4f37SHong Zhang - bsymptype - type of the basic symplectic scheme 414e49d4f37SHong Zhang 415e49d4f37SHong Zhang Level: intermediate 416e49d4f37SHong Zhang @*/ 417e49d4f37SHong Zhang PetscErrorCode TSBasicSymplecticGetType(TS ts,TSBasicSymplecticType *bsymptype) 418e49d4f37SHong Zhang { 419e49d4f37SHong Zhang PetscErrorCode ierr; 420e49d4f37SHong Zhang 421e49d4f37SHong Zhang PetscFunctionBegin; 422e49d4f37SHong Zhang PetscValidHeaderSpecific(ts,TS_CLASSID,1); 423e49d4f37SHong Zhang ierr = PetscUseMethod(ts,"TSBasicSymplecticGetType_C",(TS,TSBasicSymplecticType*),(ts,bsymptype));CHKERRQ(ierr); 424e49d4f37SHong Zhang PetscFunctionReturn(0); 425e49d4f37SHong Zhang } 426e49d4f37SHong Zhang 427e49d4f37SHong Zhang static PetscErrorCode TSBasicSymplecticSetType_BasicSymplectic(TS ts,TSBasicSymplecticType bsymptype) 428e49d4f37SHong Zhang { 429e49d4f37SHong Zhang TS_BasicSymplectic *bsymp = (TS_BasicSymplectic*)ts->data; 430e49d4f37SHong Zhang BasicSymplecticSchemeLink link; 431e49d4f37SHong Zhang PetscBool match; 432e49d4f37SHong Zhang PetscErrorCode ierr; 433e49d4f37SHong Zhang 434e49d4f37SHong Zhang PetscFunctionBegin; 435e49d4f37SHong Zhang if (bsymp->scheme) { 436e49d4f37SHong Zhang ierr = PetscStrcmp(bsymp->scheme->name,bsymptype,&match);CHKERRQ(ierr); 437e49d4f37SHong Zhang if (match) PetscFunctionReturn(0); 438e49d4f37SHong Zhang } 439e49d4f37SHong Zhang for (link = BasicSymplecticSchemeList; link; link=link->next) { 440e49d4f37SHong Zhang ierr = PetscStrcmp(link->sch.name,bsymptype,&match);CHKERRQ(ierr); 441e49d4f37SHong Zhang if (match) { 442e49d4f37SHong Zhang bsymp->scheme = &link->sch; 443e49d4f37SHong Zhang PetscFunctionReturn(0); 444e49d4f37SHong Zhang } 445e49d4f37SHong Zhang } 446e49d4f37SHong Zhang SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_UNKNOWN_TYPE,"Could not find '%s'",bsymptype); 447e49d4f37SHong Zhang PetscFunctionReturn(0); 448e49d4f37SHong Zhang } 449e49d4f37SHong Zhang 450e49d4f37SHong Zhang static PetscErrorCode TSBasicSymplecticGetType_BasicSymplectic(TS ts,TSBasicSymplecticType *bsymptype) 451e49d4f37SHong Zhang { 452e49d4f37SHong Zhang TS_BasicSymplectic *bsymp = (TS_BasicSymplectic*)ts->data; 453e49d4f37SHong Zhang 454e49d4f37SHong Zhang PetscFunctionBegin; 455e49d4f37SHong Zhang *bsymptype = bsymp->scheme->name; 456e49d4f37SHong Zhang PetscFunctionReturn(0); 457e49d4f37SHong Zhang } 458e49d4f37SHong Zhang 459e49d4f37SHong Zhang /*MC 460e49d4f37SHong Zhang TSBasicSymplectic - ODE solver using basic symplectic integration schemes 461e49d4f37SHong Zhang 462e49d4f37SHong Zhang These methods are intened for separable Hamiltonian systems 463e49d4f37SHong Zhang 464e49d4f37SHong Zhang $ qdot = dH(q,p,t)/dp 465e49d4f37SHong Zhang $ pdot = -dH(q,p,t)/dq 466e49d4f37SHong Zhang 467e49d4f37SHong Zhang where the Hamiltonian can be split into the sum of kinetic energy and potential energy 468e49d4f37SHong Zhang 469e49d4f37SHong Zhang $ H(q,p,t) = T(p,t) + V(q,t). 470e49d4f37SHong Zhang 471e49d4f37SHong Zhang As a result, the system can be genearlly represented by 472e49d4f37SHong Zhang 473e49d4f37SHong Zhang $ qdot = f(p,t) = dT(p,t)/dp 474e49d4f37SHong Zhang $ pdot = g(q,t) = -dV(q,t)/dq 475e49d4f37SHong Zhang 476e49d4f37SHong Zhang and solved iteratively with 477e49d4f37SHong Zhang 478e49d4f37SHong Zhang $ q_new = q_old + d_i*h*f(p_old,t_old) 479e49d4f37SHong Zhang $ t_new = t_old + d_i*h 480e49d4f37SHong Zhang $ p_new = p_old + c_i*h*g(p_new,t_new) 481e49d4f37SHong Zhang $ i=0,1,...,n. 482e49d4f37SHong Zhang 483e49d4f37SHong Zhang The solution vector should contain both q and p, which correspond to (generalized) position and momentum respectively. Note that the momentum component could simply be velocity in some representations. 484e49d4f37SHong Zhang The symplectic solver always expects a two-way splitting with the split names being "position" and "momentum". Each split is associated with an IS object and a sub-TS that is intended to store the user-provided RHS function. 485e49d4f37SHong Zhang 486e49d4f37SHong Zhang Reference: wikipedia (https://en.wikipedia.org/wiki/Symplectic_integrator) 487e49d4f37SHong Zhang 488e49d4f37SHong Zhang Level: beginner 489e49d4f37SHong Zhang 490e49d4f37SHong Zhang .seealso: TSCreate(), TSSetType(), TSRHSSplitSetIS(), TSRHSSplitSetRHSFunction() 491e49d4f37SHong Zhang 492e49d4f37SHong Zhang M*/ 493e49d4f37SHong Zhang PETSC_EXTERN PetscErrorCode TSCreate_BasicSymplectic(TS ts) 494e49d4f37SHong Zhang { 495e49d4f37SHong Zhang TS_BasicSymplectic *bsymp; 496e49d4f37SHong Zhang PetscErrorCode ierr; 497e49d4f37SHong Zhang 498e49d4f37SHong Zhang PetscFunctionBegin; 499e49d4f37SHong Zhang ierr = TSBasicSymplecticInitializePackage();CHKERRQ(ierr); 500e49d4f37SHong Zhang ierr = PetscNewLog(ts,&bsymp);CHKERRQ(ierr); 501e49d4f37SHong Zhang ts->data = (void*)bsymp; 502e49d4f37SHong Zhang 503e49d4f37SHong Zhang ts->ops->setup = TSSetUp_BasicSymplectic; 504e49d4f37SHong Zhang ts->ops->step = TSStep_BasicSymplectic; 505e49d4f37SHong Zhang ts->ops->reset = TSReset_BasicSymplectic; 506e49d4f37SHong Zhang ts->ops->destroy = TSDestroy_BasicSymplectic; 507e49d4f37SHong Zhang ts->ops->setfromoptions = TSSetFromOptions_BasicSymplectic; 508e49d4f37SHong Zhang ts->ops->view = TSView_BasicSymplectic; 509e49d4f37SHong Zhang ts->ops->interpolate = TSInterpolate_BasicSymplectic; 510e49d4f37SHong Zhang ts->ops->linearstability = TSComputeLinearStability_BasicSymplectic; 511e49d4f37SHong Zhang 512e49d4f37SHong Zhang ierr = PetscObjectComposeFunction((PetscObject)ts,"TSBasicSymplecticSetType_C",TSBasicSymplecticSetType_BasicSymplectic);CHKERRQ(ierr); 513e49d4f37SHong Zhang ierr = PetscObjectComposeFunction((PetscObject)ts,"TSBasicSymplecticGetType_C",TSBasicSymplecticGetType_BasicSymplectic);CHKERRQ(ierr); 514e49d4f37SHong Zhang 515e49d4f37SHong Zhang ierr = TSBasicSymplecticSetType(ts,TSBasicSymplecticDefault);CHKERRQ(ierr); 516e49d4f37SHong Zhang PetscFunctionReturn(0); 517e49d4f37SHong Zhang } 518