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