xref: /petsc/src/ts/tutorials/hamiltonian/ex2.c (revision 5f80ce2ab25dff0f4601e710601cbbcecf323266)
1b80bf5b1SJoe Pusztay static char help[] = "Two stream instability from Birdsal and Langdon with DMSwarm and TS basic symplectic integrators\n";
2b80bf5b1SJoe Pusztay 
3b80bf5b1SJoe Pusztay #include <petscdmplex.h>
4b80bf5b1SJoe Pusztay #include <petscfe.h>
5b80bf5b1SJoe Pusztay #include <petscdmswarm.h>
6b80bf5b1SJoe Pusztay #include <petscds.h>
7b80bf5b1SJoe Pusztay #include <petscksp.h>
8b80bf5b1SJoe Pusztay #include <petsc/private/petscfeimpl.h>
9b80bf5b1SJoe Pusztay #include <petsc/private/tsimpl.h>
10b80bf5b1SJoe Pusztay #include <petscts.h>
11b80bf5b1SJoe Pusztay #include <petscmath.h>
12b80bf5b1SJoe Pusztay 
13b80bf5b1SJoe Pusztay typedef struct {
14b80bf5b1SJoe Pusztay   PetscInt       dim;                              /* The topological mesh dimension */
15b80bf5b1SJoe Pusztay   PetscBool      simplex;                          /* Flag for simplices or tensor cells */
16b80bf5b1SJoe Pusztay   PetscBool      bdm;                              /* Flag for mixed form poisson */
17b80bf5b1SJoe Pusztay   PetscBool      monitor;                          /* Flag for use of the TS monitor */
18b80bf5b1SJoe Pusztay   PetscBool      uniform;                          /* Flag to uniformly space particles in x */
19b80bf5b1SJoe Pusztay   char           meshFilename[PETSC_MAX_PATH_LEN]; /* Name of the mesh filename if any */
20b80bf5b1SJoe Pusztay   PetscReal      sigma;                            /* Linear charge per box length */
21b80bf5b1SJoe Pusztay   PetscReal      timeScale;                        /* Nondimensionalizing time scaling */
22b80bf5b1SJoe Pusztay   PetscInt       particlesPerCell;                 /* The number of partices per cell */
23b80bf5b1SJoe Pusztay   PetscReal      particleRelDx;                    /* Relative particle position perturbation compared to average cell diameter h */
24b80bf5b1SJoe Pusztay   PetscInt       k;                                /* Mode number for test function */
25b80bf5b1SJoe Pusztay   PetscReal      momentTol;                        /* Tolerance for checking moment conservation */
26b80bf5b1SJoe Pusztay   SNES           snes;                             /* SNES object */
27b80bf5b1SJoe Pusztay   PetscInt       steps;                            /* TS iterations */
28b80bf5b1SJoe Pusztay   PetscReal      stepSize;                         /* Time stepper step size */
29b80bf5b1SJoe Pusztay   PetscErrorCode (*func)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *);
30b80bf5b1SJoe Pusztay } AppCtx;
31b80bf5b1SJoe Pusztay 
32b80bf5b1SJoe Pusztay static PetscErrorCode ProcessOptions(MPI_Comm comm, AppCtx *options)
33b80bf5b1SJoe Pusztay {
34b80bf5b1SJoe Pusztay   PetscErrorCode ierr;
35b80bf5b1SJoe Pusztay 
36b80bf5b1SJoe Pusztay   PetscFunctionBeginUser;
37b80bf5b1SJoe Pusztay   options->dim              = 2;
38b80bf5b1SJoe Pusztay   options->simplex          = PETSC_TRUE;
39b80bf5b1SJoe Pusztay   options->monitor          = PETSC_TRUE;
40b80bf5b1SJoe Pusztay   options->particlesPerCell = 1;
41b80bf5b1SJoe Pusztay   options->k                = 1;
42b80bf5b1SJoe Pusztay   options->particleRelDx    = 1.e-20;
43b80bf5b1SJoe Pusztay   options->momentTol        = 100.*PETSC_MACHINE_EPSILON;
44b80bf5b1SJoe Pusztay   options->sigma            = 1.;
45b80bf5b1SJoe Pusztay   options->timeScale        = 1.0e-6;
46b80bf5b1SJoe Pusztay   options->uniform          = PETSC_FALSE;
47b80bf5b1SJoe Pusztay   options->steps            = 1;
48b80bf5b1SJoe Pusztay   options->stepSize         = 0.01;
49b80bf5b1SJoe Pusztay   options->bdm              = PETSC_FALSE;
50b80bf5b1SJoe Pusztay 
51b80bf5b1SJoe Pusztay   ierr = PetscOptionsBegin(comm, "", "Two Stream options", "DMPLEX");CHKERRQ(ierr);
52*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcpy(options->meshFilename, ""));
53*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsInt("-dim", "The topological mesh dimension", "ex2.c", options->dim, &options->dim, NULL));
54*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsInt("-steps", "TS steps to take", "ex2.c", options->steps, &options->steps, NULL));
55*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-monitor", "To use the TS monitor or not", "ex2.c", options->monitor, &options->monitor, NULL));
56*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-simplex", "The flag for simplices or tensor cells", "ex2.c", options->simplex, &options->simplex, NULL));
57*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-uniform", "Uniform particle spacing", "ex2.c", options->uniform, &options->uniform, NULL));
58*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-bdm", "Use H1 instead of C0", "ex2.c", options->bdm, &options->bdm, NULL));
59*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsString("-mesh", "Name of the mesh filename if any", "ex2.c", options->meshFilename, options->meshFilename, PETSC_MAX_PATH_LEN, NULL));
60*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsInt("-k", "Mode number of test", "ex5.c", options->k, &options->k, NULL));
61*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsInt("-particlesPerCell", "Number of particles per cell", "ex2.c", options->particlesPerCell, &options->particlesPerCell, NULL));
62*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsReal("-sigma","parameter","<1>",options->sigma,&options->sigma,PETSC_NULL));
63*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsReal("-stepSize","parameter","<1e-2>",options->stepSize,&options->stepSize,PETSC_NULL));
64*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsReal("-timeScale","parameter","<1>",options->timeScale,&options->timeScale,PETSC_NULL));
65*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsReal("-particle_perturbation", "Relative perturbation of particles (0,1)", "ex2.c", options->particleRelDx, &options->particleRelDx, NULL));
66b80bf5b1SJoe Pusztay   ierr = PetscOptionsEnd();CHKERRQ(ierr);
67b80bf5b1SJoe Pusztay   PetscFunctionReturn(0);
68b80bf5b1SJoe Pusztay }
69b80bf5b1SJoe Pusztay 
70b80bf5b1SJoe Pusztay static PetscErrorCode CreateMesh(MPI_Comm comm, DM *dm, AppCtx *user)
71b80bf5b1SJoe Pusztay {
72b80bf5b1SJoe Pusztay   PetscFunctionBeginUser;
73*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreate(comm, dm));
74*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetType(*dm, DMPLEX));
75*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetFromOptions(*dm));
76*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMViewFromOptions(*dm, NULL, "-dm_view"));
77b80bf5b1SJoe Pusztay   PetscFunctionReturn(0);
78b80bf5b1SJoe Pusztay }
79b80bf5b1SJoe Pusztay 
80b80bf5b1SJoe Pusztay static void laplacian_f1(PetscInt dim, PetscInt Nf, PetscInt NfAux,
81b80bf5b1SJoe Pusztay                          const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
82b80bf5b1SJoe Pusztay                          const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
83b80bf5b1SJoe Pusztay                          PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[])
84b80bf5b1SJoe Pusztay {
85b80bf5b1SJoe Pusztay   PetscInt d;
86b80bf5b1SJoe Pusztay   for (d = 0; d < dim; ++d) {f1[d] = u_x[d];}
87b80bf5b1SJoe Pusztay }
88b80bf5b1SJoe Pusztay 
89b80bf5b1SJoe Pusztay static void laplacian(PetscInt dim, PetscInt Nf, PetscInt NfAux,
90b80bf5b1SJoe Pusztay                       const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
91b80bf5b1SJoe Pusztay                       const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
92b80bf5b1SJoe Pusztay                       PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])
93b80bf5b1SJoe Pusztay {
94b80bf5b1SJoe Pusztay   PetscInt d;
95b80bf5b1SJoe Pusztay   for (d = 0; d < dim; ++d) {g3[d*dim+d] = 1.0;}
96b80bf5b1SJoe Pusztay }
97b80bf5b1SJoe Pusztay 
98b80bf5b1SJoe Pusztay static PetscErrorCode CreateFEM(DM dm, AppCtx *user)
99b80bf5b1SJoe Pusztay {
100b80bf5b1SJoe Pusztay   PetscFE        fe;
101b80bf5b1SJoe Pusztay   PetscDS        ds;
102b80bf5b1SJoe Pusztay   DMPolytopeType ct;
103b80bf5b1SJoe Pusztay   PetscBool      simplex;
104b80bf5b1SJoe Pusztay   PetscInt       dim, cStart;
105b80bf5b1SJoe Pusztay 
106b80bf5b1SJoe Pusztay   PetscFunctionBeginUser;
107*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(dm, &dim));
108*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetHeightStratum(dm, 0, &cStart, NULL));
109*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetCellType(dm, cStart, &ct));
110b80bf5b1SJoe Pusztay   simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE;
111*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFECreateDefault(PetscObjectComm((PetscObject) dm), dim, 1, simplex, NULL, -1, &fe));
112*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) fe, "potential"));
113*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetField(dm, 0, NULL, (PetscObject) fe));
114*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateDS(dm));
115*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFEDestroy(&fe));
116*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDS(dm, &ds));
117*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscDSSetResidual(ds, 0, NULL, laplacian_f1));
118*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscDSSetJacobian(ds, 0, 0, NULL, NULL, NULL, laplacian));
119b80bf5b1SJoe Pusztay   PetscFunctionReturn(0);
120b80bf5b1SJoe Pusztay }
121b80bf5b1SJoe Pusztay 
122b80bf5b1SJoe Pusztay /*
123b80bf5b1SJoe Pusztay   Initialize particle coordinates uniformly and with opposing velocities
124b80bf5b1SJoe Pusztay */
125b80bf5b1SJoe Pusztay static PetscErrorCode CreateParticles(DM dm, DM *sw, AppCtx *user)
126b80bf5b1SJoe Pusztay {
127b80bf5b1SJoe Pusztay   PetscRandom    rnd, rndp;
128b80bf5b1SJoe Pusztay   PetscReal      interval = user->particleRelDx;
129b80bf5b1SJoe Pusztay   PetscScalar    value, *vals;
130b80bf5b1SJoe Pusztay   PetscReal     *centroid, *coords, *xi0, *v0, *J, *invJ, detJ, *initialConditions, normalized_vel;
131b80bf5b1SJoe Pusztay   PetscInt      *cellid, cStart;
132b80bf5b1SJoe Pusztay   PetscInt       Ncell, Np = user->particlesPerCell, p, c, dim, d;
133b80bf5b1SJoe Pusztay 
134b80bf5b1SJoe Pusztay   PetscFunctionBeginUser;
135*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(dm, &dim));
136*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreate(PetscObjectComm((PetscObject) dm), sw));
137*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetType(*sw, DMSWARM));
138*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetDimension(*sw, dim));
139*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscRandomCreate(PetscObjectComm((PetscObject) dm), &rnd));
140*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscRandomSetInterval(rnd, 0.0, 1.0));
141*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscRandomSetFromOptions(rnd));
142*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscRandomCreate(PetscObjectComm((PetscObject) dm), &rndp));
143*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscRandomSetInterval(rndp, -interval, interval));
144*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscRandomSetFromOptions(rndp));
145*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSwarmSetType(*sw, DMSWARM_PIC));
146*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSwarmSetCellDM(*sw, dm));
147*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSwarmRegisterPetscDatatypeField(*sw, "w_q", 1, PETSC_SCALAR));
148*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSwarmRegisterPetscDatatypeField(*sw, "kinematics", dim, PETSC_REAL));
149*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSwarmFinalizeFieldRegister(*sw));
150*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetHeightStratum(dm, 0, &cStart, &Ncell));
151*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSwarmSetLocalSizes(*sw, Ncell * Np, 0));
152*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetFromOptions(*sw));
153*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSwarmGetField(*sw, DMSwarmPICField_coor, NULL, NULL, (void **) &coords));
154*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSwarmGetField(*sw, DMSwarmPICField_cellid, NULL, NULL, (void **) &cellid));
155*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSwarmGetField(*sw, "w_q", NULL, NULL, (void **) &vals));
156*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSwarmGetField(*sw, "kinematics", NULL, NULL, (void **) &initialConditions));
157*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc5(dim, &centroid, dim, &xi0, dim, &v0, dim*dim, &J, dim*dim, &invJ));
158b80bf5b1SJoe Pusztay   for (c = cStart; c < Ncell; c++) {
159b80bf5b1SJoe Pusztay     if (Np == 1) {
160*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexComputeCellGeometryFVM(dm, c, NULL, centroid, NULL));
161b80bf5b1SJoe Pusztay       cellid[c] = c;
162b80bf5b1SJoe Pusztay       for (d = 0; d < dim; ++d) coords[c*dim+d] = centroid[d];
163b80bf5b1SJoe Pusztay     } else {
164b80bf5b1SJoe Pusztay       for (d = 0; d < dim; ++d) xi0[d] = -1.0;
165*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ)); /* affine */
166b80bf5b1SJoe Pusztay       for (p = 0; p < Np; ++p) {
167b80bf5b1SJoe Pusztay         const PetscInt n   = c*Np + p;
168b80bf5b1SJoe Pusztay         PetscReal      refcoords[3], spacing;
169b80bf5b1SJoe Pusztay 
170b80bf5b1SJoe Pusztay         cellid[n] = c;
171b80bf5b1SJoe Pusztay         if (user->uniform) {
172b80bf5b1SJoe Pusztay           spacing = 2./Np;
173*5f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscRandomGetValue(rnd, &value));
174b80bf5b1SJoe Pusztay           for (d=0; d<dim; ++d) refcoords[d] = d == 0 ? -1. + spacing/2. + p*spacing + value/100. : 0.;
175b80bf5b1SJoe Pusztay         }
176b80bf5b1SJoe Pusztay         else{
177*5f80ce2aSJacob Faibussowitsch           for (d = 0; d < dim; ++d) {CHKERRQ(PetscRandomGetValue(rnd, &value)); refcoords[d] = d == 0 ? PetscRealPart(value) : 0. ;}
178b80bf5b1SJoe Pusztay         }
179b80bf5b1SJoe Pusztay         CoordinatesRefToReal(dim, dim, xi0, v0, J, refcoords, &coords[n*dim]);
180b80bf5b1SJoe Pusztay         /* constant particle weights */
181b80bf5b1SJoe Pusztay         for (d = 0; d < dim; ++d) vals[n] = user->sigma/Np;
182b80bf5b1SJoe Pusztay       }
183b80bf5b1SJoe Pusztay     }
184b80bf5b1SJoe Pusztay   }
185*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree5(centroid, xi0, v0, J, invJ));
186b80bf5b1SJoe Pusztay   normalized_vel = 1.;
187b80bf5b1SJoe Pusztay   for (c = 0; c < Ncell; ++c) {
188b80bf5b1SJoe Pusztay     for (p = 0; p < Np; ++p) {
189b80bf5b1SJoe Pusztay       if (p%2 == 0) {
190b80bf5b1SJoe Pusztay         for (d = 0; d < dim; ++d) initialConditions[(c*Np + p)*dim + d] = d == 0 ? normalized_vel : 0.;
191b80bf5b1SJoe Pusztay       }
192b80bf5b1SJoe Pusztay       else {
193b80bf5b1SJoe Pusztay         for (d = 0; d < dim; ++d) initialConditions[(c*Np + p)*dim + d] = d == 0 ? -(normalized_vel) : 0.;
194b80bf5b1SJoe Pusztay       }
195b80bf5b1SJoe Pusztay     }
196b80bf5b1SJoe Pusztay   }
197*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSwarmRestoreField(*sw, DMSwarmPICField_coor, NULL, NULL, (void **) &coords));
198*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSwarmRestoreField(*sw, DMSwarmPICField_cellid, NULL, NULL, (void **) &cellid));
199*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSwarmRestoreField(*sw, "w_q", NULL, NULL, (void **) &vals));
200*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSwarmRestoreField(*sw, "kinematics", NULL, NULL, (void **) &initialConditions));
201*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscRandomDestroy(&rnd));
202*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscRandomDestroy(&rndp));
203*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) *sw, "Particles"));
204*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMViewFromOptions(*sw, NULL, "-sw_view"));
205*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLocalizeCoordinates(*sw));
206b80bf5b1SJoe Pusztay   PetscFunctionReturn(0);
207b80bf5b1SJoe Pusztay }
208b80bf5b1SJoe Pusztay 
209b80bf5b1SJoe Pusztay /* Solve for particle position updates */
210b80bf5b1SJoe Pusztay static PetscErrorCode RHSFunction1(TS ts,PetscReal t,Vec V,Vec Posres,void *ctx)
211b80bf5b1SJoe Pusztay {
212b80bf5b1SJoe Pusztay   const PetscScalar *v;
213b80bf5b1SJoe Pusztay   PetscScalar       *posres;
214b80bf5b1SJoe Pusztay   PetscInt          Np, p, dim, d;
215b80bf5b1SJoe Pusztay   DM                dm;
216b80bf5b1SJoe Pusztay 
217b80bf5b1SJoe Pusztay   PetscFunctionBeginUser;
218*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetLocalSize(Posres, &Np));
219*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(Posres,&posres));
220*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayRead(V,&v));
221*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSGetDM(ts, &dm));
222*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(dm, &dim));
223b80bf5b1SJoe Pusztay   Np  /= dim;
224b80bf5b1SJoe Pusztay   for (p = 0; p < Np; ++p) {
225b80bf5b1SJoe Pusztay      for (d = 0; d < dim; ++d) {
226b80bf5b1SJoe Pusztay        posres[p*dim+d] = v[p*dim+d];
227b80bf5b1SJoe Pusztay      }
228b80bf5b1SJoe Pusztay   }
229*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayRead(V,&v));
230*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(Posres,&posres));
231b80bf5b1SJoe Pusztay   PetscFunctionReturn(0);
232b80bf5b1SJoe Pusztay 
233b80bf5b1SJoe Pusztay }
234b80bf5b1SJoe Pusztay 
235b80bf5b1SJoe Pusztay /*
236b80bf5b1SJoe Pusztay   Solve for the gradient of the electric field and apply force to particles.
237b80bf5b1SJoe Pusztay  */
238b80bf5b1SJoe Pusztay static PetscErrorCode RHSFunction2(TS ts,PetscReal t,Vec X,Vec Vres,void *ctx)
239b80bf5b1SJoe Pusztay {
240b80bf5b1SJoe Pusztay  AppCtx             *user = (AppCtx *) ctx;
241b80bf5b1SJoe Pusztay   DM                 dm, plex;
242b80bf5b1SJoe Pusztay   PetscDS            prob;
243b80bf5b1SJoe Pusztay   PetscFE            fe;
244b80bf5b1SJoe Pusztay   Mat                M_p;
245b80bf5b1SJoe Pusztay   Vec                phi, locPhi, rho, f;
246b80bf5b1SJoe Pusztay   const PetscScalar *x;
247b80bf5b1SJoe Pusztay   PetscScalar       *vres;
248b80bf5b1SJoe Pusztay   PetscReal         *coords, phi_0;
249b80bf5b1SJoe Pusztay   PetscInt           dim, d, cStart, cEnd, cell, cdim;
250b80bf5b1SJoe Pusztay   PetscReal          m_e = 9.11e-31, q_e = 1.60e-19, epsi_0 = 8.85e-12;
251b80bf5b1SJoe Pusztay 
252b80bf5b1SJoe Pusztay   PetscFunctionBeginUser;
253b80bf5b1SJoe Pusztay   PetscObjectSetName((PetscObject) X, "rhsf2 position");
254b80bf5b1SJoe Pusztay   VecViewFromOptions(X, NULL, "-rhsf2_x_view");
255*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayRead(X,&x));
256*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(Vres,&vres));
257*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSGetDM(ts, &dm));
258*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(dm, &dim));
259*5f80ce2aSJacob Faibussowitsch   CHKERRQ(SNESGetDM(user->snes, &plex));
260*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateDim(plex, &cdim));
261*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDS(plex, &prob));
262*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscDSGetDiscretization(prob, 0, (PetscObject *) &fe));
263*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetGlobalVector(plex, &phi));
264*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetLocalVector(plex, &locPhi));
265*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateMassMatrix(dm, plex, &M_p));
266*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatViewFromOptions(M_p, NULL, "-mp_view"));
267*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetGlobalVector(plex, &rho));
268*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSwarmCreateGlobalVectorFromField(dm, "w_q", &f));
269*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) f, "weights vector"));
270*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecViewFromOptions(f, NULL, "-weights_view"));
271*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatMultTranspose(M_p, f, rho));
272*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSwarmDestroyGlobalVectorFromField(dm, "w_q", &f));
273*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) rho, "rho"));
274*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecViewFromOptions(rho, NULL, "-poisson_rho_view"));
275b80bf5b1SJoe Pusztay   /* Take nullspace out of rhs */
276b80bf5b1SJoe Pusztay   {
277b80bf5b1SJoe Pusztay     PetscScalar sum;
278b80bf5b1SJoe Pusztay     PetscInt    n;
279b80bf5b1SJoe Pusztay     phi_0 = (user->sigma*user->sigma*user->sigma)*(user->timeScale*user->timeScale)/(m_e*q_e*epsi_0);
280b80bf5b1SJoe Pusztay 
281*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetSize(rho, &n));
282*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecSum(rho, &sum));
283*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecShift(rho, -sum/n));
284b80bf5b1SJoe Pusztay 
285*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecSum(rho, &sum));
2863c633725SBarry Smith     PetscCheck(PetscAbsScalar(sum) <= 1.0e-10,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Charge should have no DC component %g", sum);
287*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScale(rho, phi_0));
288b80bf5b1SJoe Pusztay   }
289*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSet(phi, 0.0));
290*5f80ce2aSJacob Faibussowitsch   CHKERRQ(SNESSolve(user->snes, rho, phi));
291*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecViewFromOptions(phi, NULL, "-phi_view"));
292*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMRestoreGlobalVector(plex, &rho));
293*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDestroy(&M_p));
294*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGlobalToLocalBegin(plex, phi, INSERT_VALUES, locPhi));
295*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGlobalToLocalEnd(plex, phi, INSERT_VALUES, locPhi));
296*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSwarmSortGetAccess(dm));
297*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSwarmGetField(dm, DMSwarmPICField_coor, NULL, NULL, (void **) &coords));
298*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetHeightStratum(plex, 0, &cStart, &cEnd));
299b80bf5b1SJoe Pusztay   for (cell = cStart; cell < cEnd; ++cell) {
300b80bf5b1SJoe Pusztay     PetscTabulation tab;
301b80bf5b1SJoe Pusztay     PetscReal    v[3], J[9], invJ[9], detJ;
302b80bf5b1SJoe Pusztay     PetscScalar *ph       = PETSC_NULL;
303b80bf5b1SJoe Pusztay     PetscReal   *pcoord   = PETSC_NULL;
304b80bf5b1SJoe Pusztay     PetscReal   *refcoord = PETSC_NULL;
305b80bf5b1SJoe Pusztay     PetscInt    *points   = PETSC_NULL, Ncp, cp;
306b80bf5b1SJoe Pusztay     PetscScalar  gradPhi[3];
307b80bf5b1SJoe Pusztay 
308*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexComputeCellGeometryFEM(plex, cell, NULL, v, J, invJ, &detJ));
309*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSwarmSortGetPointsPerCell(dm, cell, &Ncp, &points));
310*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetWorkArray(dm, Ncp*cdim, MPIU_REAL, &pcoord));
311*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetWorkArray(dm, Ncp*cdim, MPIU_REAL, &refcoord));
312b80bf5b1SJoe Pusztay     for (cp = 0; cp < Ncp; ++cp) {
313b80bf5b1SJoe Pusztay       for (d = 0; d < cdim; ++d) {
314b80bf5b1SJoe Pusztay         pcoord[cp*cdim+d] = coords[points[cp]*cdim+d];
315b80bf5b1SJoe Pusztay       }
316b80bf5b1SJoe Pusztay     }
317*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexCoordinatesToReference(plex, cell, Ncp, pcoord, refcoord));
318*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFECreateTabulation(fe, 1, Ncp, refcoord, 1, &tab));
319*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexVecGetClosure(plex, NULL, locPhi, cell, NULL, &ph));
320b80bf5b1SJoe Pusztay     for (cp = 0; cp < Ncp; ++cp) {
321b80bf5b1SJoe Pusztay       const PetscInt p = points[cp];
322b80bf5b1SJoe Pusztay       gradPhi[0] = 0.0;
323b80bf5b1SJoe Pusztay       gradPhi[1] = 0.0;
324b80bf5b1SJoe Pusztay       gradPhi[2] = 0.0;
325b80bf5b1SJoe Pusztay       const PetscReal *basisDer = tab->T[1];
326b80bf5b1SJoe Pusztay 
327*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFEFreeInterpolateGradient_Static(fe, basisDer, ph, cdim, invJ, NULL, cp, gradPhi));
328b80bf5b1SJoe Pusztay       for (d = 0; d < cdim; ++d) {
329b80bf5b1SJoe Pusztay         vres[p*cdim+d] = d == 0 ? gradPhi[d] : 0.;
330b80bf5b1SJoe Pusztay       }
331b80bf5b1SJoe Pusztay     }
332*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexVecRestoreClosure(plex, NULL, locPhi, cell, NULL, &ph));
333*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscTabulationDestroy(&tab));
334*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMRestoreWorkArray(dm, Ncp*cdim, MPIU_REAL, &pcoord));
335*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMRestoreWorkArray(dm, Ncp*cdim, MPIU_REAL, &refcoord));
336*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(points));
337b80bf5b1SJoe Pusztay   }
338*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSwarmRestoreField(dm, DMSwarmPICField_coor, NULL, NULL, (void **) &coords));
339*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSwarmSortRestoreAccess(dm));
340*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMRestoreLocalVector(plex, &locPhi));
341*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMRestoreGlobalVector(plex, &phi));
342*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(Vres,&vres));
343*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayRead(X,&x));
344*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecViewFromOptions(Vres, NULL, "-vel_res_view"));
345b80bf5b1SJoe Pusztay   PetscFunctionReturn(0);
346b80bf5b1SJoe Pusztay }
347b80bf5b1SJoe Pusztay 
348b80bf5b1SJoe Pusztay int main(int argc,char **argv)
349b80bf5b1SJoe Pusztay {
350b80bf5b1SJoe Pusztay   PetscInt          i, par;
351b80bf5b1SJoe Pusztay   PetscInt          locSize, p, d, dim, Np, step, *idx1, *idx2;
352b80bf5b1SJoe Pusztay   TS                ts;
353b80bf5b1SJoe Pusztay   DM                dm, sw;
354b80bf5b1SJoe Pusztay   AppCtx            user;
355b80bf5b1SJoe Pusztay   MPI_Comm          comm;
356b80bf5b1SJoe Pusztay   Vec               coorVec, kinVec, probVec, solution, position, momentum;
357b80bf5b1SJoe Pusztay   const PetscScalar *coorArr, *kinArr;
358b80bf5b1SJoe Pusztay   PetscReal         ftime   = 10., *probArr, *probVecArr;
359b80bf5b1SJoe Pusztay   IS                is1,is2;
360b80bf5b1SJoe Pusztay   PetscReal         *coor, *kin, *pos, *mom;
361*5f80ce2aSJacob Faibussowitsch   PetscErrorCode    ierr;
362b80bf5b1SJoe Pusztay 
363b80bf5b1SJoe Pusztay   ierr = PetscInitialize(&argc,&argv,NULL,help);if (ierr) return ierr;
364b80bf5b1SJoe Pusztay   comm = PETSC_COMM_WORLD;
365*5f80ce2aSJacob Faibussowitsch   CHKERRQ(ProcessOptions(comm, &user));
366b80bf5b1SJoe Pusztay   /* Create dm and particles */
367*5f80ce2aSJacob Faibussowitsch   CHKERRQ(CreateMesh(comm, &dm, &user));
368*5f80ce2aSJacob Faibussowitsch   CHKERRQ(CreateFEM(dm, &user));
369*5f80ce2aSJacob Faibussowitsch   CHKERRQ(CreateParticles(dm, &sw, &user));
370*5f80ce2aSJacob Faibussowitsch   CHKERRQ(SNESCreate(comm, &user.snes));
371*5f80ce2aSJacob Faibussowitsch   CHKERRQ(SNESSetDM(user.snes, dm));
372*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexSetSNESLocalFEM(dm,&user,&user,&user));
373*5f80ce2aSJacob Faibussowitsch   CHKERRQ(SNESSetFromOptions(user.snes));
374b80bf5b1SJoe Pusztay   {
375b80bf5b1SJoe Pusztay     Mat          J;
376b80bf5b1SJoe Pusztay     MatNullSpace nullSpace;
377b80bf5b1SJoe Pusztay 
378*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMCreateMatrix(dm, &J));
379*5f80ce2aSJacob Faibussowitsch     CHKERRQ(MatNullSpaceCreate(PetscObjectComm((PetscObject) dm), PETSC_TRUE, 0, NULL, &nullSpace));
380*5f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetNullSpace(J, nullSpace));
381*5f80ce2aSJacob Faibussowitsch     CHKERRQ(MatNullSpaceDestroy(&nullSpace));
382*5f80ce2aSJacob Faibussowitsch     CHKERRQ(SNESSetJacobian(user.snes, J, J, NULL, NULL));
383*5f80ce2aSJacob Faibussowitsch     CHKERRQ(MatDestroy(&J));
384b80bf5b1SJoe Pusztay   }
385b80bf5b1SJoe Pusztay   /* Place TSSolve in a loop to handle resetting the TS at every manual call of TSStep() */
386*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSCreate(comm, &ts));
387*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetMaxTime(ts,ftime));
388*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetTimeStep(ts,user.stepSize));
389*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetMaxSteps(ts,100000));
390*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetExactFinalTime(ts,TS_EXACTFINALTIME_MATCHSTEP));
391b80bf5b1SJoe Pusztay   for (step = 0; step < user.steps ; ++step){
392b80bf5b1SJoe Pusztay 
393*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSwarmCreateGlobalVectorFromField(sw, "kinematics", &kinVec));
394*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSwarmCreateGlobalVectorFromField(sw, DMSwarmPICField_coor, &coorVec));
395*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecViewFromOptions(kinVec, NULL, "-ic_vec_view"));
396*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetDimension(sw, &dim));
397*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetLocalSize(kinVec, &locSize));
398*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(locSize, &idx1));
399*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(locSize, &idx2));
400*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(2*locSize, &probArr));
401b80bf5b1SJoe Pusztay     Np = locSize/dim;
402*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArrayRead(kinVec, &kinArr));
403*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArrayRead(coorVec, &coorArr));
404b80bf5b1SJoe Pusztay     for (p=0; p<Np; ++p){
405b80bf5b1SJoe Pusztay         for (d=0; d<dim;++d) {
406b80bf5b1SJoe Pusztay             probArr[p*2*dim + d] = coorArr[p*dim+d];
407b80bf5b1SJoe Pusztay             probArr[(p*2+1)*dim + d] = kinArr[p*dim+d];
408b80bf5b1SJoe Pusztay         }
409b80bf5b1SJoe Pusztay     }
410*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArrayRead(kinVec, &kinArr));
411*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArrayRead(coorVec, &coorArr));
412b80bf5b1SJoe Pusztay     /* Allocate for IS Strides that will contain x, y and vx, vy */
413b80bf5b1SJoe Pusztay     for (p = 0; p < Np; ++p) {
414b80bf5b1SJoe Pusztay       for (d = 0; d < dim; ++d) {
415b80bf5b1SJoe Pusztay         idx1[p*dim+d] = (p*2+0)*dim + d;
416b80bf5b1SJoe Pusztay         idx2[p*dim+d] = (p*2+1)*dim + d;
417b80bf5b1SJoe Pusztay       }
418b80bf5b1SJoe Pusztay     }
419b80bf5b1SJoe Pusztay 
420*5f80ce2aSJacob Faibussowitsch     CHKERRQ(ISCreateGeneral(comm, locSize, idx1, PETSC_OWN_POINTER, &is1));
421*5f80ce2aSJacob Faibussowitsch     CHKERRQ(ISCreateGeneral(comm, locSize, idx2, PETSC_OWN_POINTER, &is2));
422b80bf5b1SJoe Pusztay     /* DM needs to be set before splits so it propogates to sub TSs */
423*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSSetDM(ts, sw));
424*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSSetType(ts,TSBASICSYMPLECTIC));
425*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSRHSSplitSetIS(ts,"position",is1));
426*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSRHSSplitSetIS(ts,"momentum",is2));
427*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSRHSSplitSetRHSFunction(ts,"position",NULL,RHSFunction1,&user));
428*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSRHSSplitSetRHSFunction(ts,"momentum",NULL,RHSFunction2,&user));
429*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSSetTime(ts, step*user.stepSize));
430b80bf5b1SJoe Pusztay     if (step == 0) {
431*5f80ce2aSJacob Faibussowitsch       CHKERRQ(TSSetFromOptions(ts));
432b80bf5b1SJoe Pusztay     }
433b80bf5b1SJoe Pusztay     /* Compose vector from array for TS solve with all kinematic variables */
434*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecCreate(comm,&probVec));
435*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecSetBlockSize(probVec,1));
436*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecSetSizes(probVec,PETSC_DECIDE,2*locSize));
437*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecSetUp(probVec));
438*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArray(probVec,&probVecArr));
439*5f80ce2aSJacob Faibussowitsch     for (i=0; i < 2*locSize; ++i) probVecArr[i] = probArr[i];
440*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArray(probVec,&probVecArr));
441*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSSetSolution(ts, probVec));
442*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(probArr));
443*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecViewFromOptions(kinVec, NULL, "-ic_view"));
444*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSwarmDestroyGlobalVectorFromField(sw, "kinematics", &kinVec));
445*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSwarmDestroyGlobalVectorFromField(sw, DMSwarmPICField_coor, &coorVec));
446*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSMonitor(ts, step, ts->ptime, ts->vec_sol));
447b80bf5b1SJoe Pusztay     if (!ts->steprollback) {
448*5f80ce2aSJacob Faibussowitsch       CHKERRQ(TSPreStep(ts));
449b80bf5b1SJoe Pusztay     }
450*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSStep(ts));
451b80bf5b1SJoe Pusztay     if (ts->steprollback) {
452*5f80ce2aSJacob Faibussowitsch       CHKERRQ(TSPostEvaluate(ts));
453b80bf5b1SJoe Pusztay     }
454b80bf5b1SJoe Pusztay     if (!ts->steprollback) {
455b80bf5b1SJoe Pusztay 
456b80bf5b1SJoe Pusztay       TSPostStep(ts);
457*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMSwarmGetField(sw, DMSwarmPICField_coor, NULL, NULL, (void **) &coor));
458*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMSwarmGetField(sw, "kinematics", NULL, NULL, (void **) &kin));
459*5f80ce2aSJacob Faibussowitsch       CHKERRQ(TSGetSolution(ts, &solution));
460*5f80ce2aSJacob Faibussowitsch       CHKERRQ(VecGetSubVector(solution,is1,&position));
461*5f80ce2aSJacob Faibussowitsch       CHKERRQ(VecGetSubVector(solution,is2,&momentum));
462*5f80ce2aSJacob Faibussowitsch       CHKERRQ(VecGetArray(position, &pos));
463*5f80ce2aSJacob Faibussowitsch       CHKERRQ(VecGetArray(momentum, &mom));
464b80bf5b1SJoe Pusztay       for (par = 0; par < Np; ++par){
465b80bf5b1SJoe Pusztay         for (d=0; d<dim; ++d){
466b80bf5b1SJoe Pusztay           if (pos[par*dim+d] < 0.) {
467b80bf5b1SJoe Pusztay             coor[par*dim+d] = pos[par*dim+d] + 2.*PETSC_PI;
468b80bf5b1SJoe Pusztay           }
469b80bf5b1SJoe Pusztay           else if (pos[par*dim+d] > 2.*PETSC_PI) {
470b80bf5b1SJoe Pusztay             coor[par*dim+d] = pos[par*dim+d] - 2.*PETSC_PI;
471b80bf5b1SJoe Pusztay           }
472b80bf5b1SJoe Pusztay           else{
473b80bf5b1SJoe Pusztay             coor[par*dim+d] = pos[par*dim+d];
474b80bf5b1SJoe Pusztay           }
475b80bf5b1SJoe Pusztay           kin[par*dim+d] = mom[par*dim+d];
476b80bf5b1SJoe Pusztay         }
477b80bf5b1SJoe Pusztay       }
478*5f80ce2aSJacob Faibussowitsch       CHKERRQ(VecRestoreArray(position, &pos));
479*5f80ce2aSJacob Faibussowitsch       CHKERRQ(VecRestoreArray(momentum, &mom));
480*5f80ce2aSJacob Faibussowitsch       CHKERRQ(VecRestoreSubVector(solution,is1,&position));
481*5f80ce2aSJacob Faibussowitsch       CHKERRQ(VecRestoreSubVector(solution,is2,&momentum));
482*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **) &coor));
483*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMSwarmRestoreField(sw, "kinematics", NULL, NULL, (void **) &kin));
484b80bf5b1SJoe Pusztay     }
485*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSwarmMigrate(sw, PETSC_TRUE));
486*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLocalizeCoordinates(sw));
487*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSReset(ts));
488*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecDestroy(&probVec));
489*5f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&is1));
490*5f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&is2));
491b80bf5b1SJoe Pusztay   }
492*5f80ce2aSJacob Faibussowitsch   CHKERRQ(SNESDestroy(&user.snes));
493*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSDestroy(&ts));
494*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDestroy(&sw));
495*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDestroy(&dm));
496b80bf5b1SJoe Pusztay   ierr = PetscFinalize();
497b80bf5b1SJoe Pusztay   return ierr;
498b80bf5b1SJoe Pusztay }
499b80bf5b1SJoe Pusztay 
500b80bf5b1SJoe Pusztay /*TEST
501b80bf5b1SJoe Pusztay 
502b80bf5b1SJoe Pusztay    build:
503b80bf5b1SJoe Pusztay      requires: triangle !single !complex
504b80bf5b1SJoe Pusztay    test:
505b80bf5b1SJoe Pusztay      suffix: bsi1q3
506b80bf5b1SJoe Pusztay      args: -particlesPerCell 200\
507b80bf5b1SJoe Pusztay       -petscspace_degree 2\
508b80bf5b1SJoe Pusztay       -petscfe_default_quadrature_order 3\
509b80bf5b1SJoe Pusztay       -ts_basicsymplectic_type 1\
510b80bf5b1SJoe Pusztay       -pc_type svd\
511b80bf5b1SJoe Pusztay       -uniform\
512b80bf5b1SJoe Pusztay       -sigma 1.0e-8\
513b80bf5b1SJoe Pusztay       -timeScale 2.0e-14\
514b80bf5b1SJoe Pusztay       -stepSize 1.0e-2\
515b80bf5b1SJoe Pusztay       -ts_monitor_sp_swarm\
516b80bf5b1SJoe Pusztay       -steps 10\
517b80bf5b1SJoe Pusztay       -dm_view\
518b80bf5b1SJoe Pusztay       -dm_plex_simplex 0 -dm_plex_dim 2\
519b80bf5b1SJoe Pusztay       -dm_plex_box_lower 0,-1\
520b80bf5b1SJoe Pusztay       -dm_plex_box_upper 6.283185307179586,1\
521b80bf5b1SJoe Pusztay       -dm_plex_box_bd periodic,none\
522b80bf5b1SJoe Pusztay       -dm_plex_box_faces 4,1
523b80bf5b1SJoe Pusztay    test:
524b80bf5b1SJoe Pusztay      suffix: bsi2q3
525b80bf5b1SJoe Pusztay      args: -particlesPerCell 200\
526b80bf5b1SJoe Pusztay       -petscspace_degree 2\
527b80bf5b1SJoe Pusztay       -petscfe_default_quadrature_order 3\
528b80bf5b1SJoe Pusztay       -ts_basicsymplectic_type 2\
529b80bf5b1SJoe Pusztay       -pc_type svd\
530b80bf5b1SJoe Pusztay       -uniform\
531b80bf5b1SJoe Pusztay       -sigma 1.0e-8\
532b80bf5b1SJoe Pusztay       -timeScale 2.0e-14\
533b80bf5b1SJoe Pusztay       -stepSize 1.0e-2\
534b80bf5b1SJoe Pusztay       -ts_monitor_sp_swarm\
535b80bf5b1SJoe Pusztay       -steps 10\
536b80bf5b1SJoe Pusztay       -dm_view\
537b80bf5b1SJoe Pusztay       -dm_plex_simplex 0 -dm_plex_dim 2\
538b80bf5b1SJoe Pusztay       -dm_plex_box_lower 0,-1\
539b80bf5b1SJoe Pusztay       -dm_plex_box_upper 6.283185307179586,1\
540b80bf5b1SJoe Pusztay       -dm_plex_box_bd periodic,none\
541b80bf5b1SJoe Pusztay       -dm_plex_box_faces 4,1
542b80bf5b1SJoe Pusztay TEST*/
543