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