xref: /petsc/src/dm/impls/swarm/tests/ex5.c (revision 5f80ce2ab25dff0f4601e710601cbbcecf323266)
1c4762a1bSJed Brown static char help[] = "Vlasov example of particles orbiting around a central massive point.\n";
2c4762a1bSJed Brown 
3c4762a1bSJed Brown #include <petscdmplex.h>
4c4762a1bSJed Brown #include <petsc/private/dmpleximpl.h>  /* For norm */
5c4762a1bSJed Brown #include <petsc/private/petscfeimpl.h> /* For CoordinatesRefToReal() */
6c4762a1bSJed Brown #include <petscdmswarm.h>
7c4762a1bSJed Brown #include <petscts.h>
8c4762a1bSJed Brown 
9c4762a1bSJed Brown typedef struct {
1030602db0SMatthew G. Knepley   PetscInt  dim;
11c4762a1bSJed Brown   PetscInt  particlesPerCell; /* The number of partices per cell */
12c4762a1bSJed Brown   PetscReal momentTol;        /* Tolerance for checking moment conservation */
13c4762a1bSJed Brown   PetscBool monitor;          /* Flag for using the TS monitor */
14c4762a1bSJed Brown   PetscBool error;            /* Flag for printing the error */
15c4762a1bSJed Brown   PetscInt  ostep;            /* print the energy at each ostep time steps */
16c4762a1bSJed Brown } AppCtx;
17c4762a1bSJed Brown 
18c4762a1bSJed Brown static PetscErrorCode ProcessOptions(MPI_Comm comm, AppCtx *options)
19c4762a1bSJed Brown {
20c4762a1bSJed Brown   PetscErrorCode ierr;
21c4762a1bSJed Brown 
22c4762a1bSJed Brown   PetscFunctionBeginUser;
23c4762a1bSJed Brown   options->monitor          = PETSC_FALSE;
24c4762a1bSJed Brown   options->error            = PETSC_FALSE;
25c4762a1bSJed Brown   options->particlesPerCell = 1;
26c4762a1bSJed Brown   options->momentTol        = 100.0*PETSC_MACHINE_EPSILON;
27c4762a1bSJed Brown   options->ostep            = 100;
28c4762a1bSJed Brown 
29c4762a1bSJed Brown   ierr = PetscOptionsBegin(comm, "", "Vlasov Options", "DMPLEX");CHKERRQ(ierr);
30*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsInt("-output_step", "Number of time steps between output", "ex4.c", options->ostep, &options->ostep, PETSC_NULL));
31*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-monitor", "Flag to use the TS monitor", "ex4.c", options->monitor, &options->monitor, NULL));
32*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-error", "Flag to print the error", "ex4.c", options->error, &options->error, NULL));
33*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsInt("-particles_per_cell", "Number of particles per cell", "ex4.c", options->particlesPerCell, &options->particlesPerCell, NULL));
34c4762a1bSJed Brown   ierr = PetscOptionsEnd();CHKERRQ(ierr);
35c4762a1bSJed Brown 
36c4762a1bSJed Brown   PetscFunctionReturn(0);
37c4762a1bSJed Brown }
38c4762a1bSJed Brown 
39c4762a1bSJed Brown static PetscErrorCode CreateMesh(MPI_Comm comm, DM *dm, AppCtx *user)
40c4762a1bSJed Brown {
41c4762a1bSJed Brown   PetscFunctionBeginUser;
42*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreate(comm, dm));
43*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetType(*dm, DMPLEX));
44*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetFromOptions(*dm));
45*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMViewFromOptions(*dm, NULL, "-dm_view"));
46*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(*dm, &user->dim));
47c4762a1bSJed Brown   PetscFunctionReturn(0);
48c4762a1bSJed Brown }
49c4762a1bSJed Brown 
50c4762a1bSJed Brown static PetscErrorCode SetInitialCoordinates(DM dmSw)
51c4762a1bSJed Brown {
52c4762a1bSJed Brown   DM             dm;
53c4762a1bSJed Brown   AppCtx        *user;
54c4762a1bSJed Brown   PetscRandom    rnd;
55c4762a1bSJed Brown   PetscBool      simplex;
56c4762a1bSJed Brown   PetscReal     *centroid, *coords, *xi0, *v0, *J, *invJ, detJ;
57c4762a1bSJed Brown   PetscInt       dim, d, cStart, cEnd, c, Np, p;
58c4762a1bSJed Brown 
59c4762a1bSJed Brown   PetscFunctionBeginUser;
60*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscRandomCreate(PetscObjectComm((PetscObject) dmSw), &rnd));
61*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscRandomSetInterval(rnd, -1.0, 1.0));
62*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscRandomSetFromOptions(rnd));
63c4762a1bSJed Brown 
64*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetApplicationContext(dmSw, &user));
65c4762a1bSJed Brown   Np   = user->particlesPerCell;
66*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSwarmGetCellDM(dmSw, &dm));
67*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(dm, &dim));
68*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexIsSimplex(dm, &simplex));
69*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
70*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc5(dim, &centroid, dim, &xi0, dim, &v0, dim*dim, &J, dim*dim, &invJ));
71c4762a1bSJed Brown   for (d = 0; d < dim; ++d) xi0[d] = -1.0;
72*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSwarmGetField(dmSw, DMSwarmPICField_coor, NULL, NULL, (void **) &coords));
73c4762a1bSJed Brown   for (c = cStart; c < cEnd; ++c) {
74c4762a1bSJed Brown     if (Np == 1) {
75*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexComputeCellGeometryFVM(dm, c, NULL, centroid, NULL));
76c4762a1bSJed Brown       for (d = 0; d < dim; ++d) coords[c*dim+d] = centroid[d];
77c4762a1bSJed Brown     } else {
78*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ)); /* affine */
79c4762a1bSJed Brown       for (p = 0; p < Np; ++p) {
80c4762a1bSJed Brown         const PetscInt n   = c*Np + p;
81c4762a1bSJed Brown         PetscReal      sum = 0.0, refcoords[3];
82c4762a1bSJed Brown 
83c4762a1bSJed Brown         for (d = 0; d < dim; ++d) {
84*5f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscRandomGetValueReal(rnd, &refcoords[d]));
85c4762a1bSJed Brown           sum += refcoords[d];
86c4762a1bSJed Brown         }
87c4762a1bSJed Brown         if (simplex && sum > 0.0) for (d = 0; d < dim; ++d) refcoords[d] -= PetscSqrtReal(dim)*sum;
88c4762a1bSJed Brown         CoordinatesRefToReal(dim, dim, xi0, v0, J, refcoords, &coords[n*dim]);
89c4762a1bSJed Brown       }
90c4762a1bSJed Brown     }
91c4762a1bSJed Brown   }
92*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSwarmRestoreField(dmSw, DMSwarmPICField_coor, NULL, NULL, (void **) &coords));
93*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree5(centroid, xi0, v0, J, invJ));
94*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscRandomDestroy(&rnd));
95c4762a1bSJed Brown   PetscFunctionReturn(0);
96c4762a1bSJed Brown }
97c4762a1bSJed Brown 
98c4762a1bSJed Brown static PetscErrorCode SetInitialConditions(DM dmSw, Vec u)
99c4762a1bSJed Brown {
100c4762a1bSJed Brown   DM             dm;
101c4762a1bSJed Brown   AppCtx         *user;
102c4762a1bSJed Brown   PetscScalar    *initialConditions;
103c4762a1bSJed Brown   PetscInt       dim, cStart, cEnd, c, Np, p;
104c4762a1bSJed Brown 
105c4762a1bSJed Brown   PetscFunctionBeginUser;
106*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetApplicationContext(dmSw, &user));
107c4762a1bSJed Brown   Np   = user->particlesPerCell;
108*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSwarmGetCellDM(dmSw, &dm));
109*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(dm, &dim));
110*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
111*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(u, &initialConditions));
112c4762a1bSJed Brown   for (c = cStart; c < cEnd; ++c) {
113c4762a1bSJed Brown     for (p = 0; p < Np; ++p) {
114c4762a1bSJed Brown       const PetscInt n = c*Np + p;
115c4762a1bSJed Brown 
116c4762a1bSJed Brown       initialConditions[(n*2 + 0)*dim + 0] = n+1;
117c4762a1bSJed Brown       initialConditions[(n*2 + 0)*dim + 1] = 0;
118c4762a1bSJed Brown       initialConditions[(n*2 + 1)*dim + 0] = 0;
119c4762a1bSJed Brown       initialConditions[(n*2 + 1)*dim + 1] = PetscSqrtReal(1000./(n+1.));
120c4762a1bSJed Brown     }
121c4762a1bSJed Brown   }
122*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(u, &initialConditions));
123c4762a1bSJed Brown   PetscFunctionReturn(0);
124c4762a1bSJed Brown }
125c4762a1bSJed Brown 
126c4762a1bSJed Brown static PetscErrorCode CreateParticles(DM dm, DM *sw, AppCtx *user)
127c4762a1bSJed Brown {
128c4762a1bSJed Brown   PetscInt      *cellid;
129c4762a1bSJed Brown   PetscInt       dim, cStart, cEnd, c, Np = user->particlesPerCell, p;
130c4762a1bSJed Brown 
131c4762a1bSJed Brown   PetscFunctionBeginUser;
132*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(dm, &dim));
133*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreate(PetscObjectComm((PetscObject) dm), sw));
134*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetType(*sw, DMSWARM));
135*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetDimension(*sw, dim));
136c4762a1bSJed Brown 
137*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSwarmSetType(*sw, DMSWARM_PIC));
138*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSwarmSetCellDM(*sw, dm));
139*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSwarmRegisterPetscDatatypeField(*sw, "kinematics", 2*dim, PETSC_REAL));
140*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSwarmFinalizeFieldRegister(*sw));
141*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
142*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSwarmSetLocalSizes(*sw, (cEnd - cStart) * Np, 0));
143*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetFromOptions(*sw));
144*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSwarmGetField(*sw, DMSwarmPICField_cellid, NULL, NULL, (void **) &cellid));
145c4762a1bSJed Brown   for (c = cStart; c < cEnd; ++c) {
146c4762a1bSJed Brown     for (p = 0; p < Np; ++p) {
147c4762a1bSJed Brown       const PetscInt n = c*Np + p;
148c4762a1bSJed Brown 
149c4762a1bSJed Brown       cellid[n] = c;
150c4762a1bSJed Brown     }
151c4762a1bSJed Brown   }
152*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSwarmRestoreField(*sw, DMSwarmPICField_cellid, NULL, NULL, (void **) &cellid));
153*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) *sw, "Particles"));
154*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMViewFromOptions(*sw, NULL, "-sw_view"));
155c4762a1bSJed Brown   PetscFunctionReturn(0);
156c4762a1bSJed Brown }
157c4762a1bSJed Brown 
158c4762a1bSJed Brown /* Create particle RHS Functions for gravity with G = 1 for simplification */
159c4762a1bSJed Brown static PetscErrorCode RHSFunction1(TS ts, PetscReal t, Vec V, Vec Xres, void *ctx)
160c4762a1bSJed Brown {
161c4762a1bSJed Brown   const PetscScalar *v;
162c4762a1bSJed Brown   PetscScalar       *xres;
163c4762a1bSJed Brown   PetscInt          Np, p, dim, d;
164c4762a1bSJed Brown 
165c4762a1bSJed Brown   PetscFunctionBeginUser;
16630602db0SMatthew G. Knepley   /* The DM is not currently pushed down to the splits */
16730602db0SMatthew G. Knepley   dim  = ((AppCtx *) ctx)->dim;
168*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetLocalSize(Xres, &Np));
169c4762a1bSJed Brown   Np  /= dim;
170*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(Xres, &xres));
171*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayRead(V, &v));
172c4762a1bSJed Brown   for (p = 0; p < Np; ++p) {
173c4762a1bSJed Brown      for (d = 0; d < dim; ++d) {
174c4762a1bSJed Brown        xres[p*dim+d] = v[p*dim+d];
175c4762a1bSJed Brown      }
176c4762a1bSJed Brown   }
177*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayRead(V,& v));
178*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(Xres, &xres));
179c4762a1bSJed Brown   PetscFunctionReturn(0);
180c4762a1bSJed Brown }
181c4762a1bSJed Brown 
182c4762a1bSJed Brown static PetscErrorCode RHSFunction2(TS ts, PetscReal t, Vec X, Vec Vres, void *ctx)
183c4762a1bSJed Brown {
184c4762a1bSJed Brown   const PetscScalar *x;
185c4762a1bSJed Brown   PetscScalar       *vres;
186c4762a1bSJed Brown   PetscInt          Np, p, dim, d;
187c4762a1bSJed Brown 
188c4762a1bSJed Brown   PetscFunctionBeginUser;
18930602db0SMatthew G. Knepley   /* The DM is not currently pushed down to the splits */
19030602db0SMatthew G. Knepley   dim  = ((AppCtx *) ctx)->dim;
191*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetLocalSize(Vres, &Np));
192c4762a1bSJed Brown   Np  /= dim;
193*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(Vres, &vres));
194*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayRead(X, &x));
195c4762a1bSJed Brown   for (p = 0; p < Np; ++p) {
196c4762a1bSJed Brown     const PetscScalar rsqr = DMPlex_NormD_Internal(dim, &x[p*dim]);
197c4762a1bSJed Brown 
198c4762a1bSJed Brown     for (d = 0; d < dim; ++d) {
199c4762a1bSJed Brown       vres[p*dim+d] = -(1000./(p+1.)) * x[p*dim+d]/PetscSqr(rsqr);
200c4762a1bSJed Brown     }
201c4762a1bSJed Brown   }
202*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(Vres, &vres));
203*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayRead(X, &x));
204c4762a1bSJed Brown   PetscFunctionReturn(0);
205c4762a1bSJed Brown }
206c4762a1bSJed Brown 
207c4762a1bSJed Brown static PetscErrorCode RHSFunctionParticles(TS ts, PetscReal t , Vec U, Vec R, void *ctx)
208c4762a1bSJed Brown {
209c4762a1bSJed Brown   DM                dm;
210c4762a1bSJed Brown   const PetscScalar *u;
211c4762a1bSJed Brown   PetscScalar       *r;
212c4762a1bSJed Brown   PetscInt          Np, p, dim, d;
213c4762a1bSJed Brown 
214c4762a1bSJed Brown   PetscFunctionBeginUser;
215*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSGetDM(ts, &dm));
216*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(dm, &dim));
217*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetLocalSize(U, &Np));
218c4762a1bSJed Brown   Np  /= 2*dim;
219*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayRead(U, &u));
220*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(R, &r));
221c4762a1bSJed Brown   for (p = 0; p < Np; ++p) {
222c4762a1bSJed Brown     const PetscScalar rsqr = DMPlex_NormD_Internal(dim, &u[p*2*dim]);
223c4762a1bSJed Brown 
224c4762a1bSJed Brown     for (d = 0; d < dim; ++d) {
225c4762a1bSJed Brown         r[p*2*dim+d]   = u[p*2*dim+d+2];
226c4762a1bSJed Brown         r[p*2*dim+d+2] = -(1000./(1.+p)) * u[p*2*dim+d]/PetscSqr(rsqr);
227c4762a1bSJed Brown     }
228c4762a1bSJed Brown   }
229*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayRead(U, &u));
230*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(R, &r));
231c4762a1bSJed Brown   PetscFunctionReturn(0);
232c4762a1bSJed Brown }
233c4762a1bSJed Brown 
234c4762a1bSJed Brown static PetscErrorCode InitializeSolve(TS ts, Vec u)
235c4762a1bSJed Brown {
236c4762a1bSJed Brown   DM             dm;
237c4762a1bSJed Brown   AppCtx        *user;
238c4762a1bSJed Brown 
239c4762a1bSJed Brown   PetscFunctionBeginUser;
240*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSGetDM(ts, &dm));
241*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetApplicationContext(dm, &user));
242*5f80ce2aSJacob Faibussowitsch   CHKERRQ(SetInitialCoordinates(dm));
243*5f80ce2aSJacob Faibussowitsch   CHKERRQ(SetInitialConditions(dm, u));
244c4762a1bSJed Brown   PetscFunctionReturn(0);
245c4762a1bSJed Brown }
246c4762a1bSJed Brown 
247c4762a1bSJed Brown static PetscErrorCode ComputeError(TS ts, Vec U, Vec E)
248c4762a1bSJed Brown {
249c4762a1bSJed Brown   MPI_Comm          comm;
250c4762a1bSJed Brown   DM                sdm;
251c4762a1bSJed Brown   AppCtx            *user;
252c4762a1bSJed Brown   const PetscScalar *u, *coords;
253c4762a1bSJed Brown   PetscScalar       *e;
254c4762a1bSJed Brown   PetscReal         t;
255c4762a1bSJed Brown   PetscInt          dim, Np, p;
256c4762a1bSJed Brown 
257c4762a1bSJed Brown   PetscFunctionBeginUser;
258*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject) ts, &comm));
259*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSGetDM(ts, &sdm));
260*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetApplicationContext(sdm, &user));
261*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(sdm, &dim));
262*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSGetSolveTime(ts, &t));
263*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(E, &e));
264*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayRead(U, &u));
265*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetLocalSize(U, &Np));
266c4762a1bSJed Brown   Np  /= 2*dim;
267*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSwarmGetField(sdm, DMSwarmPICField_coor, NULL, NULL, (void **) &coords));
268c4762a1bSJed Brown   for (p = 0; p < Np; ++p) {
269c4762a1bSJed Brown     const PetscScalar *x     = &u[(p*2+0)*dim];
270c4762a1bSJed Brown     const PetscScalar *v     = &u[(p*2+1)*dim];
271c4762a1bSJed Brown     const PetscReal   x0    = p+1.;
272c4762a1bSJed Brown     const PetscReal   omega = PetscSqrtReal(1000./(p+1.))/x0;
273c4762a1bSJed Brown     const PetscReal   xe[3] = { x0*PetscCosReal(omega*t),       x0*PetscSinReal(omega*t),       0.0};
274c4762a1bSJed Brown     const PetscReal   ve[3] = {-x0*omega*PetscSinReal(omega*t), x0*omega*PetscCosReal(omega*t), 0.0};
275c4762a1bSJed Brown     PetscInt          d;
276c4762a1bSJed Brown 
277c4762a1bSJed Brown     for (d = 0; d < dim; ++d) {
278c4762a1bSJed Brown       e[(p*2+0)*dim+d] = x[d] - xe[d];
279c4762a1bSJed Brown       e[(p*2+1)*dim+d] = v[d] - ve[d];
280c4762a1bSJed Brown     }
281*5f80ce2aSJacob Faibussowitsch     if (user->error) CHKERRQ(PetscPrintf(comm, "t %.4g: p%D error [%.2g %.2g] sol [(%.6lf %.6lf) (%.6lf %.6lf)] exact [(%.6lf %.6lf) (%.6lf %.6lf)] energy/exact energy %g / %g\n", t, p, (double) DMPlex_NormD_Internal(dim, &e[(p*2+0)*dim]), (double) DMPlex_NormD_Internal(dim, &e[(p*2+1)*dim]), (double) x[0], (double) x[1], (double) v[0], (double) v[1], (double) xe[0], (double) xe[1], (double) ve[0], (double) ve[1], 0.5*DMPlex_NormD_Internal(dim, v), (double) (0.5*(1000./(p+1)))));
282c4762a1bSJed Brown   }
283*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSwarmRestoreField(sdm, DMSwarmPICField_coor, NULL, NULL, (void **) &coords));
284*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayRead(U, &u));
285*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(E, &e));
286c4762a1bSJed Brown   PetscFunctionReturn(0);
287c4762a1bSJed Brown }
288c4762a1bSJed Brown 
289c4762a1bSJed Brown int main(int argc, char **argv)
290c4762a1bSJed Brown {
291c4762a1bSJed Brown   TS                 ts;
292c4762a1bSJed Brown   TSConvergedReason  reason;
293c4762a1bSJed Brown   DM                 dm, sw;
294c4762a1bSJed Brown   Vec                u;
295c4762a1bSJed Brown   IS                 is1, is2;
296c4762a1bSJed Brown   PetscInt          *idx1, *idx2;
297c4762a1bSJed Brown   MPI_Comm           comm;
298c4762a1bSJed Brown   AppCtx             user;
299c4762a1bSJed Brown   const PetscScalar *endVals;
300c4762a1bSJed Brown   PetscReal          ftime   = .1;
301c4762a1bSJed Brown   PetscInt           locSize, dim, d, Np, p, steps;
302c4762a1bSJed Brown   PetscErrorCode     ierr;
303c4762a1bSJed Brown 
304c4762a1bSJed Brown   ierr = PetscInitialize(&argc, &argv, NULL, help);if (ierr) return ierr;
305c4762a1bSJed Brown   comm = PETSC_COMM_WORLD;
306*5f80ce2aSJacob Faibussowitsch   CHKERRQ(ProcessOptions(comm, &user));
307c4762a1bSJed Brown 
308*5f80ce2aSJacob Faibussowitsch   CHKERRQ(CreateMesh(comm, &dm, &user));
309*5f80ce2aSJacob Faibussowitsch   CHKERRQ(CreateParticles(dm, &sw, &user));
310*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetApplicationContext(sw, &user));
311c4762a1bSJed Brown 
312*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSCreate(comm, &ts));
313*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetType(ts, TSBASICSYMPLECTIC));
314*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetDM(ts, sw));
315*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetMaxTime(ts, ftime));
316*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetTimeStep(ts, 0.0001));
317*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetMaxSteps(ts, 10));
318*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetExactFinalTime(ts, TS_EXACTFINALTIME_MATCHSTEP));
319*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetTime(ts, 0.0));
320*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetRHSFunction(ts, NULL, RHSFunctionParticles, &user));
321c4762a1bSJed Brown 
322*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSwarmCreateGlobalVectorFromField(sw, "kinematics", &u));
323*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(sw, &dim));
324*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetLocalSize(u, &locSize));
325c4762a1bSJed Brown   Np   = locSize/(2*dim);
326*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(locSize/2, &idx1));
327*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(locSize/2, &idx2));
328c4762a1bSJed Brown   for (p = 0; p < Np; ++p) {
329c4762a1bSJed Brown     for (d = 0; d < dim; ++d) {
330c4762a1bSJed Brown       idx1[p*dim+d] = (p*2+0)*dim + d;
331c4762a1bSJed Brown       idx2[p*dim+d] = (p*2+1)*dim + d;
332c4762a1bSJed Brown     }
333c4762a1bSJed Brown   }
334*5f80ce2aSJacob Faibussowitsch   CHKERRQ(ISCreateGeneral(comm, locSize/2, idx1, PETSC_OWN_POINTER, &is1));
335*5f80ce2aSJacob Faibussowitsch   CHKERRQ(ISCreateGeneral(comm, locSize/2, idx2, PETSC_OWN_POINTER, &is2));
336*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSRHSSplitSetIS(ts, "position", is1));
337*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSRHSSplitSetIS(ts, "momentum", is2));
338*5f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&is1));
339*5f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&is2));
340*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSRHSSplitSetRHSFunction(ts,"position",NULL,RHSFunction1,&user));
341*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSRHSSplitSetRHSFunction(ts,"momentum",NULL,RHSFunction2,&user));
342c4762a1bSJed Brown 
343*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetFromOptions(ts));
344*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetComputeInitialCondition(ts, InitializeSolve));
345*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetComputeExactError(ts, ComputeError));
346*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSComputeInitialCondition(ts, u));
347*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecViewFromOptions(u, NULL, "-init_view"));
348*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSolve(ts, u));
349*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSGetSolveTime(ts, &ftime));
350*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSGetConvergedReason(ts, &reason));
351*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSGetStepNumber(ts, &steps));
352*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscPrintf(comm,"%s at time %g after %D steps\n", TSConvergedReasons[reason], (double) ftime, steps));
353c4762a1bSJed Brown 
354*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayRead(u, &endVals));
355c4762a1bSJed Brown   for (p = 0; p < Np; ++p) {
356c4762a1bSJed Brown     const PetscReal norm = DMPlex_NormD_Internal(dim, &endVals[(p*2 + 1)*dim]);
357*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscPrintf(comm, "Particle %D initial Energy: %g  Final Energy: %g\n", p, (double) (0.5*(1000./(p+1))), (double) 0.5*PetscSqr(norm)));
358c4762a1bSJed Brown   }
359*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayRead(u, &endVals));
360*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSwarmDestroyGlobalVectorFromField(sw, "kinematics", &u));
361*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSDestroy(&ts));
362*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDestroy(&sw));
363*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDestroy(&dm));
364c4762a1bSJed Brown   ierr = PetscFinalize();
365c4762a1bSJed Brown   return ierr;
366c4762a1bSJed Brown }
367c4762a1bSJed Brown 
368c4762a1bSJed Brown /*TEST
369c4762a1bSJed Brown 
370c4762a1bSJed Brown    build:
371c4762a1bSJed Brown      requires: triangle !single !complex
372c4762a1bSJed Brown    test:
373c4762a1bSJed Brown      suffix: bsi1
374d7462660SMatthew Knepley      args: -dm_plex_box_faces 1,1 -dm_plex_box_lower -5,-5 -dm_plex_box_upper 5,5 \
375d7462660SMatthew Knepley            -ts_basicsymplectic_type 1 -ts_max_time 0.1 -ts_convergence_estimate -convest_num_refine 2 \
376d7462660SMatthew Knepley            -dm_view -sw_view -ts_monitor_sp_swarm -ts_monitor_sp_swarm_retain -ts_monitor_sp_swarm_phase 0
377c4762a1bSJed Brown    test:
378c4762a1bSJed Brown      suffix: bsi2
379d7462660SMatthew Knepley      args: -dm_plex_box_faces 1,1 -dm_plex_box_lower -5,-5 -dm_plex_box_upper 5,5 \
380d7462660SMatthew Knepley            -ts_basicsymplectic_type 2 -ts_max_time 0.1 -ts_convergence_estimate -convest_num_refine 2 \
381d7462660SMatthew Knepley            -dm_view -sw_view -ts_monitor_sp_swarm -ts_monitor_sp_swarm_retain -ts_monitor_sp_swarm_phase 0
382c4762a1bSJed Brown    test:
383c4762a1bSJed Brown      suffix: euler
384d7462660SMatthew Knepley      args: -dm_plex_box_faces 1,1 -dm_plex_box_lower -5,-5 -dm_plex_box_upper 5,5 \
385d7462660SMatthew Knepley            -ts_type euler -ts_max_time 0.1 -ts_convergence_estimate -convest_num_refine 2 \
386d7462660SMatthew Knepley            -dm_view -sw_view -ts_monitor_sp_swarm -ts_monitor_sp_swarm_retain -ts_monitor_sp_swarm_phase 0
387c4762a1bSJed Brown 
388c4762a1bSJed Brown TEST*/
389