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, ¢roid, 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