18214e71cSJoe static char help[] = "Landau Damping/Two Stream instability test using Vlasov-Poisson equations\n";
2b80bf5b1SJoe Pusztay
38214e71cSJoe /*
49072cb8bSMatthew G. Knepley TODO:
59072cb8bSMatthew G. Knepley - Cache mesh geometry
69072cb8bSMatthew G. Knepley - Move electrostatic solver to MG+SVD
79072cb8bSMatthew G. Knepley
88214e71cSJoe To run the code with particles sinusoidally perturbed in x space use the test "pp_poisson_bsi_1d_4" or "pp_poisson_bsi_2d_4"
98214e71cSJoe According to Lukas, good damping results come at ~16k particles per cell
108214e71cSJoe
119072cb8bSMatthew G. Knepley To visualize the maximum electric field use
128214e71cSJoe
139072cb8bSMatthew G. Knepley -efield_monitor
148214e71cSJoe
159072cb8bSMatthew G. Knepley To monitor velocity moments of the distribution use
16f1e6e573SMatthew G. Knepley
179072cb8bSMatthew G. Knepley -ptof_pc_type lu -moments_monitor
189072cb8bSMatthew G. Knepley
199072cb8bSMatthew G. Knepley To monitor the particle positions in phase space use
209072cb8bSMatthew G. Knepley
219072cb8bSMatthew G. Knepley -positions_monitor
229072cb8bSMatthew G. Knepley
239072cb8bSMatthew G. Knepley To monitor the charge density, E field, and potential use
249072cb8bSMatthew G. Knepley
259072cb8bSMatthew G. Knepley -poisson_monitor
269072cb8bSMatthew G. Knepley
279072cb8bSMatthew G. Knepley To monitor the remapping field use
289072cb8bSMatthew G. Knepley
299072cb8bSMatthew G. Knepley -remap_uf_view draw
30f1e6e573SMatthew G. Knepley
318214e71cSJoe To visualize the swarm distribution use
328214e71cSJoe
338214e71cSJoe -ts_monitor_hg_swarm
348214e71cSJoe
358214e71cSJoe To visualize the particles, we can use
368214e71cSJoe
378214e71cSJoe -ts_monitor_sp_swarm -ts_monitor_sp_swarm_retain 0 -ts_monitor_sp_swarm_phase 1 -draw_size 500,500
388214e71cSJoe
3984467f86SMatthew G. Knepley For a Landau Damping verification run, we use
4084467f86SMatthew G. Knepley
41045208b8SMatthew G. Knepley # Physics
42045208b8SMatthew G. Knepley -cosine_coefficients 0.01 -dm_swarm_num_species 1 -charges -1. -perturbed_weights -total_weight 1.
43045208b8SMatthew G. Knepley # Spatial Mesh
44045208b8SMatthew G. Knepley -dm_plex_dim 1 -dm_plex_box_faces 40 -dm_plex_box_lower 0. -dm_plex_box_upper 12.5664 -dm_plex_box_bd periodic -dm_plex_hash_location
45045208b8SMatthew G. Knepley # Velocity Mesh
46045208b8SMatthew G. Knepley -vdm_plex_dim 1 -vdm_plex_box_faces 40 -vdm_plex_box_lower -6 -vdm_plex_box_upper 6 -vpetscspace_degree 2 -vdm_plex_hash_location
47045208b8SMatthew G. Knepley # Remap Space
48045208b8SMatthew G. Knepley -dm_swarm_remap_type pfak -remap_freq 100
49045208b8SMatthew G. Knepley -remap_dm_plex_dim 2 -remap_dm_plex_simplex 0 -remap_dm_plex_box_faces 20,20 -remap_dm_plex_box_bd periodic,none -remap_dm_plex_box_lower 0.,-6.
50045208b8SMatthew G. Knepley -remap_dm_plex_box_upper 12.5664,6. -remap_petscspace_degree 1 -remap_dm_plex_hash_location
51045208b8SMatthew G. Knepley # Remap Solve
52045208b8SMatthew G. Knepley -ftop_ksp_type lsqr -ftop_pc_type none -ftop_ksp_rtol 1.e-14 -ptof_pc_type lu
53045208b8SMatthew G. Knepley # EM Solve
54045208b8SMatthew G. Knepley -em_type primal -petscspace_degree 1 -em_snes_atol 1.e-12 -em_snes_error_if_not_converged -em_ksp_error_if_not_converged -em_pc_type svd -em_proj_pc_type lu
55045208b8SMatthew G. Knepley # Timestepping
56188af4bfSBarry Smith -ts_type basicsymplectic -ts_basicsymplectic_type 1 -ts_time_step 0.03 -ts_max_steps 1500 -ts_max_time 100
57045208b8SMatthew G. Knepley # Monitoring
58045208b8SMatthew G. Knepley -output_step 1 -check_vel_res -efield_monitor -poisson_monitor -positions_monitor -dm_swarm_print_coords 0 -remap_uf_view draw
59045208b8SMatthew G. Knepley -ftop_ksp_lsqr_monitor -ftop_ksp_converged_reason
6084467f86SMatthew G. Knepley
618214e71cSJoe */
62b80bf5b1SJoe Pusztay #include <petscts.h>
638214e71cSJoe #include <petscdmplex.h>
648214e71cSJoe #include <petscdmswarm.h>
658214e71cSJoe #include <petscfe.h>
668214e71cSJoe #include <petscds.h>
678214e71cSJoe #include <petscbag.h>
688214e71cSJoe #include <petscdraw.h>
698214e71cSJoe #include <petsc/private/dmpleximpl.h> /* For norm and dot */
708214e71cSJoe #include <petsc/private/petscfeimpl.h> /* For interpolation */
7184467f86SMatthew G. Knepley #include <petsc/private/dmswarmimpl.h> /* For swarm debugging */
728214e71cSJoe #include "petscdm.h"
738214e71cSJoe #include "petscdmlabel.h"
748214e71cSJoe
758214e71cSJoe PETSC_EXTERN PetscErrorCode stream(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
768214e71cSJoe PETSC_EXTERN PetscErrorCode line(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
778214e71cSJoe
788214e71cSJoe const char *EMTypes[] = {"primal", "mixed", "coulomb", "none", "EMType", "EM_", NULL};
798214e71cSJoe typedef enum {
808214e71cSJoe EM_PRIMAL,
818214e71cSJoe EM_MIXED,
828214e71cSJoe EM_COULOMB,
838214e71cSJoe EM_NONE
848214e71cSJoe } EMType;
858214e71cSJoe
868214e71cSJoe typedef enum {
878214e71cSJoe V0,
888214e71cSJoe X0,
898214e71cSJoe T0,
908214e71cSJoe M0,
918214e71cSJoe Q0,
928214e71cSJoe PHI0,
938214e71cSJoe POISSON,
948214e71cSJoe VLASOV,
958214e71cSJoe SIGMA,
968214e71cSJoe NUM_CONSTANTS
978214e71cSJoe } ConstantType;
988214e71cSJoe typedef struct {
998214e71cSJoe PetscScalar v0; /* Velocity scale, often the thermal velocity */
1008214e71cSJoe PetscScalar t0; /* Time scale */
1018214e71cSJoe PetscScalar x0; /* Space scale */
1028214e71cSJoe PetscScalar m0; /* Mass scale */
1038214e71cSJoe PetscScalar q0; /* Charge scale */
1048214e71cSJoe PetscScalar kb;
1058214e71cSJoe PetscScalar epsi0;
1068214e71cSJoe PetscScalar phi0; /* Potential scale */
1078214e71cSJoe PetscScalar poissonNumber; /* Non-Dimensional Poisson Number */
1088214e71cSJoe PetscScalar vlasovNumber; /* Non-Dimensional Vlasov Number */
1098214e71cSJoe PetscReal sigma; /* Nondimensional charge per length in x */
1108214e71cSJoe } Parameter;
111b80bf5b1SJoe Pusztay
112b80bf5b1SJoe Pusztay typedef struct {
1139072cb8bSMatthew G. Knepley PetscBag bag; // Problem parameters
1149072cb8bSMatthew G. Knepley PetscBool error; // Flag for printing the error
1159072cb8bSMatthew G. Knepley PetscInt remapFreq; // Number of timesteps between remapping
1169072cb8bSMatthew G. Knepley PetscBool efield_monitor; // Flag to show electric field monitor
1179072cb8bSMatthew G. Knepley PetscBool moment_monitor; // Flag to show distribution moment monitor
1189072cb8bSMatthew G. Knepley PetscBool positions_monitor; // Flag to show particle positins at each time step
1199072cb8bSMatthew G. Knepley PetscBool poisson_monitor; // Flag to display charge, E field, and potential at each solve
1209072cb8bSMatthew G. Knepley PetscBool initial_monitor; // Flag to monitor the initial conditions
121fd7102fcSMatthew G. Knepley PetscInt velocity_monitor; // Cell to monitor the velocity distribution for
1229072cb8bSMatthew G. Knepley PetscBool perturbed_weights; // Uniformly sample x,v space with gaussian weights
1239072cb8bSMatthew G. Knepley PetscInt ostep; // Print the energy at each ostep time steps
1248214e71cSJoe PetscInt numParticles;
1258214e71cSJoe PetscReal timeScale; /* Nondimensionalizing time scale */
1268214e71cSJoe PetscReal charges[2]; /* The charges of each species */
1278214e71cSJoe PetscReal masses[2]; /* The masses of each species */
1288214e71cSJoe PetscReal thermal_energy[2]; /* Thermal Energy (used to get other constants)*/
1298214e71cSJoe PetscReal cosine_coefficients[2]; /*(alpha, k)*/
1308214e71cSJoe PetscReal totalWeight;
1318214e71cSJoe PetscReal stepSize;
1328214e71cSJoe PetscInt steps;
1338214e71cSJoe PetscReal initVel;
134f1e6e573SMatthew G. Knepley EMType em; // Type of electrostatic model
135f1e6e573SMatthew G. Knepley SNES snes; // EM solver
1364a0cbf56SMatthew G. Knepley DM dmPot; // The DM for potential
137b02f317dSMatthew G. Knepley Mat fftPot; // Fourier Transform operator for the potential
138fd7102fcSMatthew G. Knepley Vec fftX, fftY; // FFT vectors with phases added (complex parts)
139fd7102fcSMatthew G. Knepley IS fftReal; // The indices for real parts
1404a0cbf56SMatthew G. Knepley IS isPot; // The IS for potential, or NULL in primal
1414a0cbf56SMatthew G. Knepley Mat M; // The finite element mass matrix for potential
142f1e6e573SMatthew G. Knepley PetscFEGeom *fegeom; // Geometric information for the DM cells
143b02f317dSMatthew G. Knepley PetscDrawHG drawhgic_x; // Histogram of the particle weight in each X cell
144b02f317dSMatthew G. Knepley PetscDrawHG drawhgic_v; // Histogram of the particle weight in each X cell
145fd7102fcSMatthew G. Knepley PetscDrawHG drawhgcell_v; // Histogram of the particle weight in a given cell
1469072cb8bSMatthew G. Knepley PetscBool validE; // Flag to indicate E-field in swarm is valid
14775155f48SMatthew G. Knepley PetscReal drawlgEmin; // The minimum lg(E) to plot
14875155f48SMatthew G. Knepley PetscDrawLG drawlgE; // Logarithm of maximum electric field
14975155f48SMatthew G. Knepley PetscDrawSP drawspE; // Electric field at particle positions
15075155f48SMatthew G. Knepley PetscDrawSP drawspX; // Particle positions
15175155f48SMatthew G. Knepley PetscViewer viewerRho; // Charge density viewer
152b02f317dSMatthew G. Knepley PetscViewer viewerRhoHat; // Charge density Fourier Transform viewer
15375155f48SMatthew G. Knepley PetscViewer viewerPhi; // Potential viewer
1548214e71cSJoe DM swarm;
1558214e71cSJoe PetscRandom random;
1568214e71cSJoe PetscBool twostream;
1578214e71cSJoe PetscBool checkweights;
158b02f317dSMatthew G. Knepley PetscInt checkVRes; // Flag to check/output velocity residuals for nightly tests
15984467f86SMatthew G. Knepley
16084467f86SMatthew G. Knepley PetscLogEvent RhsXEvent, RhsVEvent, ESolveEvent, ETabEvent;
161b80bf5b1SJoe Pusztay } AppCtx;
162b80bf5b1SJoe Pusztay
ProcessOptions(MPI_Comm comm,AppCtx * options)163d71ae5a4SJacob Faibussowitsch static PetscErrorCode ProcessOptions(MPI_Comm comm, AppCtx *options)
164d71ae5a4SJacob Faibussowitsch {
165b80bf5b1SJoe Pusztay PetscFunctionBeginUser;
1668214e71cSJoe PetscInt d = 2;
1678214e71cSJoe PetscInt maxSpecies = 2;
1688214e71cSJoe options->error = PETSC_FALSE;
1699072cb8bSMatthew G. Knepley options->remapFreq = 1;
1708214e71cSJoe options->efield_monitor = PETSC_FALSE;
171f1e6e573SMatthew G. Knepley options->moment_monitor = PETSC_FALSE;
1728214e71cSJoe options->initial_monitor = PETSC_FALSE;
1738214e71cSJoe options->perturbed_weights = PETSC_FALSE;
1748214e71cSJoe options->poisson_monitor = PETSC_FALSE;
1759072cb8bSMatthew G. Knepley options->positions_monitor = PETSC_FALSE;
176fd7102fcSMatthew G. Knepley options->velocity_monitor = -1;
1778214e71cSJoe options->ostep = 100;
1788214e71cSJoe options->timeScale = 2.0e-14;
1798214e71cSJoe options->charges[0] = -1.0;
1808214e71cSJoe options->charges[1] = 1.0;
1818214e71cSJoe options->masses[0] = 1.0;
1828214e71cSJoe options->masses[1] = 1000.0;
1838214e71cSJoe options->thermal_energy[0] = 1.0;
1848214e71cSJoe options->thermal_energy[1] = 1.0;
1858214e71cSJoe options->cosine_coefficients[0] = 0.01;
1868214e71cSJoe options->cosine_coefficients[1] = 0.5;
1878214e71cSJoe options->initVel = 1;
1888214e71cSJoe options->totalWeight = 1.0;
1898214e71cSJoe options->drawhgic_x = NULL;
1908214e71cSJoe options->drawhgic_v = NULL;
191fd7102fcSMatthew G. Knepley options->drawhgcell_v = NULL;
192f940b0e3Sdanofinn options->validE = PETSC_FALSE;
19375155f48SMatthew G. Knepley options->drawlgEmin = -6;
19475155f48SMatthew G. Knepley options->drawlgE = NULL;
19575155f48SMatthew G. Knepley options->drawspE = NULL;
19675155f48SMatthew G. Knepley options->drawspX = NULL;
19775155f48SMatthew G. Knepley options->viewerRho = NULL;
198b02f317dSMatthew G. Knepley options->viewerRhoHat = NULL;
19975155f48SMatthew G. Knepley options->viewerPhi = NULL;
2008214e71cSJoe options->em = EM_COULOMB;
2014a0cbf56SMatthew G. Knepley options->snes = NULL;
2024a0cbf56SMatthew G. Knepley options->dmPot = NULL;
203b02f317dSMatthew G. Knepley options->fftPot = NULL;
204fd7102fcSMatthew G. Knepley options->fftX = NULL;
205fd7102fcSMatthew G. Knepley options->fftY = NULL;
206fd7102fcSMatthew G. Knepley options->fftReal = NULL;
2074a0cbf56SMatthew G. Knepley options->isPot = NULL;
2084a0cbf56SMatthew G. Knepley options->M = NULL;
2098214e71cSJoe options->numParticles = 32768;
2108214e71cSJoe options->twostream = PETSC_FALSE;
2118214e71cSJoe options->checkweights = PETSC_FALSE;
2128214e71cSJoe options->checkVRes = 0;
213b80bf5b1SJoe Pusztay
2148214e71cSJoe PetscOptionsBegin(comm, "", "Landau Damping and Two Stream options", "DMSWARM");
2158214e71cSJoe PetscCall(PetscOptionsBool("-error", "Flag to print the error", "ex2.c", options->error, &options->error, NULL));
2169072cb8bSMatthew G. Knepley PetscCall(PetscOptionsInt("-remap_freq", "Number", "ex2.c", options->remapFreq, &options->remapFreq, NULL));
2179072cb8bSMatthew G. Knepley PetscCall(PetscOptionsBool("-efield_monitor", "Flag to plot log(max E) over time", "ex2.c", options->efield_monitor, &options->efield_monitor, NULL));
2189072cb8bSMatthew G. Knepley PetscCall(PetscOptionsReal("-efield_min_monitor", "Minimum E field to plot", "ex2.c", options->drawlgEmin, &options->drawlgEmin, NULL));
2199072cb8bSMatthew G. Knepley PetscCall(PetscOptionsBool("-moments_monitor", "Flag to show moments table", "ex2.c", options->moment_monitor, &options->moment_monitor, NULL));
2209072cb8bSMatthew G. Knepley PetscCall(PetscOptionsBool("-ics_monitor", "Flag to show initial condition histograms", "ex2.c", options->initial_monitor, &options->initial_monitor, NULL));
2219072cb8bSMatthew G. Knepley PetscCall(PetscOptionsBool("-positions_monitor", "The flag to show particle positions", "ex2.c", options->positions_monitor, &options->positions_monitor, NULL));
2229072cb8bSMatthew G. Knepley PetscCall(PetscOptionsBool("-poisson_monitor", "The flag to show charges, Efield and potential solve", "ex2.c", options->poisson_monitor, &options->poisson_monitor, NULL));
223fd7102fcSMatthew G. Knepley PetscCall(PetscOptionsInt("-velocity_monitor", "Cell to show velocity histograms", "ex2.c", options->velocity_monitor, &options->velocity_monitor, NULL));
2248214e71cSJoe PetscCall(PetscOptionsBool("-twostream", "Run two stream instability", "ex2.c", options->twostream, &options->twostream, NULL));
2258214e71cSJoe PetscCall(PetscOptionsBool("-perturbed_weights", "Flag to run uniform sampling with perturbed weights", "ex2.c", options->perturbed_weights, &options->perturbed_weights, NULL));
2268214e71cSJoe PetscCall(PetscOptionsBool("-check_weights", "Ensure all particle weights are positive", "ex2.c", options->checkweights, &options->checkweights, NULL));
2278214e71cSJoe PetscCall(PetscOptionsInt("-check_vel_res", "Check particle velocity residuals for nightly tests", "ex2.c", options->checkVRes, &options->checkVRes, NULL));
2288214e71cSJoe PetscCall(PetscOptionsInt("-output_step", "Number of time steps between output", "ex2.c", options->ostep, &options->ostep, NULL));
2298214e71cSJoe PetscCall(PetscOptionsReal("-timeScale", "Nondimensionalizing time scale", "ex2.c", options->timeScale, &options->timeScale, NULL));
2308214e71cSJoe PetscCall(PetscOptionsReal("-initial_velocity", "Initial velocity of perturbed particle", "ex2.c", options->initVel, &options->initVel, NULL));
2318214e71cSJoe PetscCall(PetscOptionsReal("-total_weight", "Total weight of all particles", "ex2.c", options->totalWeight, &options->totalWeight, NULL));
2328214e71cSJoe PetscCall(PetscOptionsRealArray("-cosine_coefficients", "Amplitude and frequency of cosine equation used in initialization", "ex2.c", options->cosine_coefficients, &d, NULL));
2338214e71cSJoe PetscCall(PetscOptionsRealArray("-charges", "Species charges", "ex2.c", options->charges, &maxSpecies, NULL));
2348214e71cSJoe PetscCall(PetscOptionsEnum("-em_type", "Type of electrostatic solver", "ex2.c", EMTypes, (PetscEnum)options->em, (PetscEnum *)&options->em, NULL));
235d0609cedSBarry Smith PetscOptionsEnd();
23684467f86SMatthew G. Knepley
23784467f86SMatthew G. Knepley PetscCall(PetscLogEventRegister("RhsX", TS_CLASSID, &options->RhsXEvent));
23884467f86SMatthew G. Knepley PetscCall(PetscLogEventRegister("RhsV", TS_CLASSID, &options->RhsVEvent));
23984467f86SMatthew G. Knepley PetscCall(PetscLogEventRegister("ESolve", TS_CLASSID, &options->ESolveEvent));
24084467f86SMatthew G. Knepley PetscCall(PetscLogEventRegister("ETab", TS_CLASSID, &options->ETabEvent));
2413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
242b80bf5b1SJoe Pusztay }
243b80bf5b1SJoe Pusztay
SetupContext(DM dm,DM sw,AppCtx * ctx)244*2a8381b2SBarry Smith static PetscErrorCode SetupContext(DM dm, DM sw, AppCtx *ctx)
2458214e71cSJoe {
246b02f317dSMatthew G. Knepley MPI_Comm comm;
247b02f317dSMatthew G. Knepley
2488214e71cSJoe PetscFunctionBeginUser;
249b02f317dSMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
250*2a8381b2SBarry Smith if (ctx->efield_monitor) {
25175155f48SMatthew G. Knepley PetscDraw draw;
25275155f48SMatthew G. Knepley PetscDrawAxis axis;
25375155f48SMatthew G. Knepley
254b02f317dSMatthew G. Knepley PetscCall(PetscDrawCreate(comm, NULL, "Max Electric Field", 0, 300, 400, 300, &draw));
255fd7102fcSMatthew G. Knepley PetscCall(PetscDrawSetSave(draw, "ex2_Efield"));
25675155f48SMatthew G. Knepley PetscCall(PetscDrawSetFromOptions(draw));
257*2a8381b2SBarry Smith PetscCall(PetscDrawLGCreate(draw, 1, &ctx->drawlgE));
25875155f48SMatthew G. Knepley PetscCall(PetscDrawDestroy(&draw));
259*2a8381b2SBarry Smith PetscCall(PetscDrawLGGetAxis(ctx->drawlgE, &axis));
26075155f48SMatthew G. Knepley PetscCall(PetscDrawAxisSetLabels(axis, "Electron Electric Field", "time", "E_max"));
261*2a8381b2SBarry Smith PetscCall(PetscDrawLGSetLimits(ctx->drawlgE, 0., ctx->steps * ctx->stepSize, ctx->drawlgEmin, 0.));
2628214e71cSJoe }
263b02f317dSMatthew G. Knepley
264*2a8381b2SBarry Smith if (ctx->initial_monitor) {
265fd7102fcSMatthew G. Knepley PetscDraw drawic_x, drawic_v;
266b02f317dSMatthew G. Knepley PetscDrawAxis axis1, axis2;
2678214e71cSJoe PetscReal dmboxlower[2], dmboxupper[2];
2688214e71cSJoe PetscInt dim, cStart, cEnd;
269b02f317dSMatthew G. Knepley
2708214e71cSJoe PetscCall(DMGetDimension(sw, &dim));
2718214e71cSJoe PetscCall(DMGetBoundingBox(dm, dmboxlower, dmboxupper));
2728214e71cSJoe PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
2738214e71cSJoe
274fd7102fcSMatthew G. Knepley PetscCall(PetscDrawCreate(comm, NULL, "monitor_initial_conditions_x", 0, 300, 400, 300, &drawic_x));
275fd7102fcSMatthew G. Knepley PetscCall(PetscDrawSetSave(drawic_x, "ex2_ic_x"));
276fd7102fcSMatthew G. Knepley PetscCall(PetscDrawSetFromOptions(drawic_x));
277*2a8381b2SBarry Smith PetscCall(PetscDrawHGCreate(drawic_x, (int)dim, &ctx->drawhgic_x));
278*2a8381b2SBarry Smith PetscCall(PetscDrawHGCalcStats(ctx->drawhgic_x, PETSC_TRUE));
279*2a8381b2SBarry Smith PetscCall(PetscDrawHGGetAxis(ctx->drawhgic_x, &axis1));
280*2a8381b2SBarry Smith PetscCall(PetscDrawHGSetNumberBins(ctx->drawhgic_x, (int)(cEnd - cStart)));
281fd7102fcSMatthew G. Knepley PetscCall(PetscDrawAxisSetLabels(axis1, "Initial X Distribution", "X", "weight"));
282b02f317dSMatthew G. Knepley PetscCall(PetscDrawAxisSetLimits(axis1, dmboxlower[0], dmboxupper[0], 0, 0));
283fd7102fcSMatthew G. Knepley PetscCall(PetscDrawDestroy(&drawic_x));
2848214e71cSJoe
285fd7102fcSMatthew G. Knepley PetscCall(PetscDrawCreate(comm, NULL, "monitor_initial_conditions_v", 400, 300, 400, 300, &drawic_v));
286fd7102fcSMatthew G. Knepley PetscCall(PetscDrawSetSave(drawic_v, "ex9_ic_v"));
287fd7102fcSMatthew G. Knepley PetscCall(PetscDrawSetFromOptions(drawic_v));
288*2a8381b2SBarry Smith PetscCall(PetscDrawHGCreate(drawic_v, (int)dim, &ctx->drawhgic_v));
289*2a8381b2SBarry Smith PetscCall(PetscDrawHGCalcStats(ctx->drawhgic_v, PETSC_TRUE));
290*2a8381b2SBarry Smith PetscCall(PetscDrawHGGetAxis(ctx->drawhgic_v, &axis2));
291*2a8381b2SBarry Smith PetscCall(PetscDrawHGSetNumberBins(ctx->drawhgic_v, 21));
292fd7102fcSMatthew G. Knepley PetscCall(PetscDrawAxisSetLabels(axis2, "Initial V_x Distribution", "V", "weight"));
293b02f317dSMatthew G. Knepley PetscCall(PetscDrawAxisSetLimits(axis2, -6, 6, 0, 0));
294fd7102fcSMatthew G. Knepley PetscCall(PetscDrawDestroy(&drawic_v));
295fd7102fcSMatthew G. Knepley }
296fd7102fcSMatthew G. Knepley
297*2a8381b2SBarry Smith if (ctx->velocity_monitor >= 0) {
298fd7102fcSMatthew G. Knepley DM vdm;
299fd7102fcSMatthew G. Knepley DMSwarmCellDM celldm;
300fd7102fcSMatthew G. Knepley PetscDraw drawcell_v;
301fd7102fcSMatthew G. Knepley PetscDrawAxis axis;
302fd7102fcSMatthew G. Knepley PetscReal dmboxlower[2], dmboxupper[2];
303fd7102fcSMatthew G. Knepley PetscInt dim;
304fd7102fcSMatthew G. Knepley char title[PETSC_MAX_PATH_LEN];
305fd7102fcSMatthew G. Knepley
306fd7102fcSMatthew G. Knepley PetscCall(DMSwarmGetCellDMByName(sw, "velocity", &celldm));
307fd7102fcSMatthew G. Knepley PetscCall(DMSwarmCellDMGetDM(celldm, &vdm));
308fd7102fcSMatthew G. Knepley PetscCall(DMGetDimension(vdm, &dim));
309fd7102fcSMatthew G. Knepley PetscCall(DMGetBoundingBox(vdm, dmboxlower, dmboxupper));
310fd7102fcSMatthew G. Knepley
311*2a8381b2SBarry Smith PetscCall(PetscSNPrintf(title, PETSC_MAX_PATH_LEN, "Cell %" PetscInt_FMT ": Velocity Distribution", ctx->velocity_monitor));
312fd7102fcSMatthew G. Knepley PetscCall(PetscDrawCreate(comm, NULL, title, 400, 300, 400, 300, &drawcell_v));
313fd7102fcSMatthew G. Knepley PetscCall(PetscDrawSetSave(drawcell_v, "ex2_cell_v"));
314fd7102fcSMatthew G. Knepley PetscCall(PetscDrawSetFromOptions(drawcell_v));
315*2a8381b2SBarry Smith PetscCall(PetscDrawHGCreate(drawcell_v, (int)dim, &ctx->drawhgcell_v));
316*2a8381b2SBarry Smith PetscCall(PetscDrawHGCalcStats(ctx->drawhgcell_v, PETSC_TRUE));
317*2a8381b2SBarry Smith PetscCall(PetscDrawHGGetAxis(ctx->drawhgcell_v, &axis));
318*2a8381b2SBarry Smith PetscCall(PetscDrawHGSetNumberBins(ctx->drawhgcell_v, 21));
319fd7102fcSMatthew G. Knepley PetscCall(PetscDrawAxisSetLabels(axis, "V_x Distribution", "V", "weight"));
320fd7102fcSMatthew G. Knepley PetscCall(PetscDrawAxisSetLimits(axis, dmboxlower[0], dmboxupper[0], 0, 0));
321fd7102fcSMatthew G. Knepley PetscCall(PetscDrawDestroy(&drawcell_v));
3228214e71cSJoe }
323b02f317dSMatthew G. Knepley
324*2a8381b2SBarry Smith if (ctx->positions_monitor) {
32575155f48SMatthew G. Knepley PetscDraw draw;
3268214e71cSJoe PetscDrawAxis axis;
3278214e71cSJoe
328b02f317dSMatthew G. Knepley PetscCall(PetscDrawCreate(comm, NULL, "Particle Position", 0, 0, 400, 300, &draw));
32975155f48SMatthew G. Knepley PetscCall(PetscDrawSetSave(draw, "ex9_pos"));
33075155f48SMatthew G. Knepley PetscCall(PetscDrawSetFromOptions(draw));
331*2a8381b2SBarry Smith PetscCall(PetscDrawSPCreate(draw, 10, &ctx->drawspX));
33275155f48SMatthew G. Knepley PetscCall(PetscDrawDestroy(&draw));
333*2a8381b2SBarry Smith PetscCall(PetscDrawSPSetDimension(ctx->drawspX, 1));
334*2a8381b2SBarry Smith PetscCall(PetscDrawSPGetAxis(ctx->drawspX, &axis));
3358214e71cSJoe PetscCall(PetscDrawAxisSetLabels(axis, "Particles", "x", "v"));
336*2a8381b2SBarry Smith PetscCall(PetscDrawSPReset(ctx->drawspX));
3378214e71cSJoe }
338*2a8381b2SBarry Smith if (ctx->poisson_monitor) {
339b02f317dSMatthew G. Knepley Vec rho, rhohat, phi;
34075155f48SMatthew G. Knepley PetscDraw draw;
34175155f48SMatthew G. Knepley PetscDrawAxis axis;
3428214e71cSJoe
343b02f317dSMatthew G. Knepley PetscCall(PetscDrawCreate(comm, NULL, "Electric_Field", 0, 0, 400, 300, &draw));
34475155f48SMatthew G. Knepley PetscCall(PetscDrawSetFromOptions(draw));
34575155f48SMatthew G. Knepley PetscCall(PetscDrawSetSave(draw, "ex9_E_spatial"));
346*2a8381b2SBarry Smith PetscCall(PetscDrawSPCreate(draw, 10, &ctx->drawspE));
34775155f48SMatthew G. Knepley PetscCall(PetscDrawDestroy(&draw));
348*2a8381b2SBarry Smith PetscCall(PetscDrawSPSetDimension(ctx->drawspE, 1));
349*2a8381b2SBarry Smith PetscCall(PetscDrawSPGetAxis(ctx->drawspE, &axis));
35075155f48SMatthew G. Knepley PetscCall(PetscDrawAxisSetLabels(axis, "Particles", "x", "E"));
351*2a8381b2SBarry Smith PetscCall(PetscDrawSPReset(ctx->drawspE));
3528214e71cSJoe
353*2a8381b2SBarry Smith PetscCall(PetscViewerDrawOpen(comm, NULL, "Charge Density", 0, 0, 400, 300, &ctx->viewerRho));
354*2a8381b2SBarry Smith PetscCall(PetscObjectSetOptionsPrefix((PetscObject)ctx->viewerRho, "rho_"));
355*2a8381b2SBarry Smith PetscCall(PetscViewerDrawGetDraw(ctx->viewerRho, 0, &draw));
35675155f48SMatthew G. Knepley PetscCall(PetscDrawSetSave(draw, "ex9_rho_spatial"));
357*2a8381b2SBarry Smith PetscCall(PetscViewerSetFromOptions(ctx->viewerRho));
358*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmPot, "rho", &rho));
35975155f48SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)rho, "charge_density"));
360*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmPot, "rho", &rho));
3618214e71cSJoe
362b02f317dSMatthew G. Knepley PetscInt dim, N;
363b02f317dSMatthew G. Knepley
364*2a8381b2SBarry Smith PetscCall(DMGetDimension(ctx->dmPot, &dim));
365b02f317dSMatthew G. Knepley if (dim == 1) {
366*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmPot, "rhohat", &rhohat));
367b02f317dSMatthew G. Knepley PetscCall(VecGetSize(rhohat, &N));
368*2a8381b2SBarry Smith PetscCall(MatCreateFFT(comm, dim, &N, MATFFTW, &ctx->fftPot));
369*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmPot, "rhohat", &rhohat));
370*2a8381b2SBarry Smith PetscCall(MatCreateVecs(ctx->fftPot, &ctx->fftX, &ctx->fftY));
371*2a8381b2SBarry Smith PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &ctx->fftReal));
372b02f317dSMatthew G. Knepley }
373b02f317dSMatthew G. Knepley
374*2a8381b2SBarry Smith PetscCall(PetscViewerDrawOpen(comm, NULL, "rhohat: Charge Density FT", 0, 0, 400, 300, &ctx->viewerRhoHat));
375*2a8381b2SBarry Smith PetscCall(PetscObjectSetOptionsPrefix((PetscObject)ctx->viewerRhoHat, "rhohat_"));
376*2a8381b2SBarry Smith PetscCall(PetscViewerDrawGetDraw(ctx->viewerRhoHat, 0, &draw));
377b02f317dSMatthew G. Knepley PetscCall(PetscDrawSetSave(draw, "ex9_rho_ft"));
378*2a8381b2SBarry Smith PetscCall(PetscViewerSetFromOptions(ctx->viewerRhoHat));
379*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmPot, "rhohat", &rhohat));
380b02f317dSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)rhohat, "charge_density_ft"));
381*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmPot, "rhohat", &rhohat));
382b02f317dSMatthew G. Knepley
383*2a8381b2SBarry Smith PetscCall(PetscViewerDrawOpen(comm, NULL, "Potential", 400, 0, 400, 300, &ctx->viewerPhi));
384*2a8381b2SBarry Smith PetscCall(PetscObjectSetOptionsPrefix((PetscObject)ctx->viewerPhi, "phi_"));
385*2a8381b2SBarry Smith PetscCall(PetscViewerDrawGetDraw(ctx->viewerPhi, 0, &draw));
38675155f48SMatthew G. Knepley PetscCall(PetscDrawSetSave(draw, "ex9_phi_spatial"));
387*2a8381b2SBarry Smith PetscCall(PetscViewerSetFromOptions(ctx->viewerPhi));
388*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmPot, "phi", &phi));
38975155f48SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)phi, "potential"));
390*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmPot, "phi", &phi));
3918214e71cSJoe }
3928214e71cSJoe PetscFunctionReturn(PETSC_SUCCESS);
3938214e71cSJoe }
3948214e71cSJoe
DestroyContext(AppCtx * ctx)395*2a8381b2SBarry Smith static PetscErrorCode DestroyContext(AppCtx *ctx)
3968214e71cSJoe {
3978214e71cSJoe PetscFunctionBeginUser;
398*2a8381b2SBarry Smith PetscCall(PetscDrawHGDestroy(&ctx->drawhgic_x));
399*2a8381b2SBarry Smith PetscCall(PetscDrawHGDestroy(&ctx->drawhgic_v));
400*2a8381b2SBarry Smith PetscCall(PetscDrawHGDestroy(&ctx->drawhgcell_v));
4018214e71cSJoe
402*2a8381b2SBarry Smith PetscCall(PetscDrawLGDestroy(&ctx->drawlgE));
403*2a8381b2SBarry Smith PetscCall(PetscDrawSPDestroy(&ctx->drawspE));
404*2a8381b2SBarry Smith PetscCall(PetscDrawSPDestroy(&ctx->drawspX));
405*2a8381b2SBarry Smith PetscCall(PetscViewerDestroy(&ctx->viewerRho));
406*2a8381b2SBarry Smith PetscCall(PetscViewerDestroy(&ctx->viewerRhoHat));
407*2a8381b2SBarry Smith PetscCall(MatDestroy(&ctx->fftPot));
408*2a8381b2SBarry Smith PetscCall(VecDestroy(&ctx->fftX));
409*2a8381b2SBarry Smith PetscCall(VecDestroy(&ctx->fftY));
410*2a8381b2SBarry Smith PetscCall(ISDestroy(&ctx->fftReal));
411*2a8381b2SBarry Smith PetscCall(PetscViewerDestroy(&ctx->viewerPhi));
4128214e71cSJoe
413*2a8381b2SBarry Smith PetscCall(PetscBagDestroy(&ctx->bag));
4148214e71cSJoe PetscFunctionReturn(PETSC_SUCCESS);
4158214e71cSJoe }
4168214e71cSJoe
CheckNonNegativeWeights(DM sw,AppCtx * ctx)417*2a8381b2SBarry Smith static PetscErrorCode CheckNonNegativeWeights(DM sw, AppCtx *ctx)
4188214e71cSJoe {
4198214e71cSJoe const PetscScalar *w;
4208214e71cSJoe PetscInt Np;
4218214e71cSJoe
4228214e71cSJoe PetscFunctionBeginUser;
423*2a8381b2SBarry Smith if (!ctx->checkweights) PetscFunctionReturn(PETSC_SUCCESS);
4248214e71cSJoe PetscCall(DMSwarmGetField(sw, "w_q", NULL, NULL, (void **)&w));
4258214e71cSJoe PetscCall(DMSwarmGetLocalSize(sw, &Np));
4268214e71cSJoe for (PetscInt p = 0; p < Np; ++p) PetscCheck(w[p] >= 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Particle %" PetscInt_FMT " has negative weight %g", p, w[p]);
4278214e71cSJoe PetscCall(DMSwarmRestoreField(sw, "w_q", NULL, NULL, (void **)&w));
4288214e71cSJoe PetscFunctionReturn(PETSC_SUCCESS);
4298214e71cSJoe }
4308214e71cSJoe
f0_Dirichlet(PetscInt dim,PetscInt Nf,PetscInt NfAux,const PetscInt uOff[],const PetscInt uOff_x[],const PetscScalar u[],const PetscScalar u_t[],const PetscScalar u_x[],const PetscInt aOff[],const PetscInt aOff_x[],const PetscScalar a[],const PetscScalar a_t[],const PetscScalar a_x[],PetscReal t,const PetscReal x[],PetscInt numConstants,const PetscScalar constants[],PetscScalar f0[])431f940b0e3Sdanofinn static void f0_Dirichlet(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
432f940b0e3Sdanofinn {
433f940b0e3Sdanofinn for (PetscInt d = 0; d < dim; ++d) f0[0] += 0.5 * PetscSqr(u_x[d]);
434f940b0e3Sdanofinn }
435f940b0e3Sdanofinn
computeFieldEnergy(DM dm,Vec u,PetscReal * En)436f940b0e3Sdanofinn static PetscErrorCode computeFieldEnergy(DM dm, Vec u, PetscReal *En)
437f940b0e3Sdanofinn {
438f940b0e3Sdanofinn PetscDS ds;
439f940b0e3Sdanofinn const PetscInt field = 0;
440f940b0e3Sdanofinn PetscInt Nf;
441f940b0e3Sdanofinn void *ctx;
442f940b0e3Sdanofinn
443f940b0e3Sdanofinn PetscFunctionBegin;
444f940b0e3Sdanofinn PetscCall(DMGetApplicationContext(dm, &ctx));
445f940b0e3Sdanofinn PetscCall(DMGetDS(dm, &ds));
446f940b0e3Sdanofinn PetscCall(PetscDSGetNumFields(ds, &Nf));
447f940b0e3Sdanofinn PetscCheck(Nf == 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "We currently only support 1 field, not %" PetscInt_FMT, Nf);
448f940b0e3Sdanofinn PetscCall(PetscDSSetObjective(ds, field, &f0_Dirichlet));
449f940b0e3Sdanofinn PetscCall(DMPlexComputeIntegralFEM(dm, u, En, ctx));
450f940b0e3Sdanofinn PetscFunctionReturn(PETSC_SUCCESS);
451f940b0e3Sdanofinn }
452f940b0e3Sdanofinn
computeVelocityFEMMoments(DM sw,PetscReal moments[],AppCtx * user)4539072cb8bSMatthew G. Knepley static PetscErrorCode computeVelocityFEMMoments(DM sw, PetscReal moments[], AppCtx *user)
4548214e71cSJoe {
4559072cb8bSMatthew G. Knepley DMSwarmCellDM celldm;
456f1e6e573SMatthew G. Knepley DM vdm;
457f1e6e573SMatthew G. Knepley Vec u[1];
458f1e6e573SMatthew G. Knepley const char *fields[1] = {"w_q"};
4598214e71cSJoe
460f1e6e573SMatthew G. Knepley PetscFunctionBegin;
4619072cb8bSMatthew G. Knepley PetscCall(DMSwarmSetCellDMActive(sw, "velocity"));
4629072cb8bSMatthew G. Knepley PetscCall(DMSwarmGetCellDMActive(sw, &celldm));
4639072cb8bSMatthew G. Knepley PetscCall(DMSwarmCellDMGetDM(celldm, &vdm));
464f940b0e3Sdanofinn #if 0
465f940b0e3Sdanofinn PetscReal *v, pvmin[3] = {0., 0., 0.}, pvmax[3] = {0., 0., 0.}, vmin[3], vmax[3], fact = 1.;
466f940b0e3Sdanofinn PetscInt dim, Np;
467f940b0e3Sdanofinn
468f940b0e3Sdanofinn PetscCall(PetscObjectQuery((PetscObject)sw, "__vdm__", (PetscObject *)&vdm));
469f940b0e3Sdanofinn // Check for particles outside the velocity grid
470f940b0e3Sdanofinn PetscCall(DMGetDimension(sw, &dim));
471f940b0e3Sdanofinn PetscCall(DMSwarmGetLocalSize(sw, &Np));
472f940b0e3Sdanofinn PetscCall(DMSwarmGetField(sw, "velocity", NULL, NULL, (void **)&v));
473f940b0e3Sdanofinn for (PetscInt p = 0; p < Np; ++p) {
474f940b0e3Sdanofinn for (PetscInt d = 0; d < dim; ++d) {
475f940b0e3Sdanofinn pvmin[d] = PetscMin(pvmax[d], v[p * dim + d]);
476f940b0e3Sdanofinn pvmax[d] = PetscMax(pvmax[d], v[p * dim + d]);
477f940b0e3Sdanofinn }
478f940b0e3Sdanofinn }
479f940b0e3Sdanofinn PetscCall(DMSwarmRestoreField(sw, "velocity", NULL, NULL, (void **)&v));
480f940b0e3Sdanofinn PetscCall(DMGetBoundingBox(vdm, vmin, vmax));
481f940b0e3Sdanofinn // To avoid particle loss, we enlarge the velocity grid if necessary
482f940b0e3Sdanofinn for (PetscInt d = 0; d < dim; ++d) {
483f940b0e3Sdanofinn fact = PetscMax(fact, pvmax[d] / vmax[d]);
484f940b0e3Sdanofinn fact = PetscMax(fact, pvmin[d] / vmin[d]);
485f940b0e3Sdanofinn }
486f940b0e3Sdanofinn if (fact > 1.) {
487f940b0e3Sdanofinn Vec coordinates, coordinatesLocal;
488f940b0e3Sdanofinn
489f940b0e3Sdanofinn fact *= 1.1;
490f940b0e3Sdanofinn PetscCall(PetscPrintf(PETSC_COMM_SELF, "Expanding velocity grid by %g\n", fact));
491f940b0e3Sdanofinn PetscCall(DMGetCoordinatesLocal(vdm, &coordinatesLocal));
492f940b0e3Sdanofinn PetscCall(DMGetCoordinates(vdm, &coordinates));
493f940b0e3Sdanofinn PetscCall(VecScale(coordinatesLocal, fact));
494f940b0e3Sdanofinn PetscCall(VecScale(coordinates, fact));
495f940b0e3Sdanofinn PetscCall(PetscGridHashDestroy(&((DM_Plex *)vdm->data)->lbox));
496f940b0e3Sdanofinn }
497f940b0e3Sdanofinn #endif
498f1e6e573SMatthew G. Knepley PetscCall(DMGetGlobalVector(vdm, &u[0]));
499f1e6e573SMatthew G. Knepley PetscCall(DMSwarmProjectFields(sw, vdm, 1, fields, u, SCATTER_FORWARD));
500f1e6e573SMatthew G. Knepley PetscCall(DMPlexComputeMoments(vdm, u[0], moments));
501f1e6e573SMatthew G. Knepley PetscCall(DMRestoreGlobalVector(vdm, &u[0]));
5029072cb8bSMatthew G. Knepley PetscCall(DMSwarmSetCellDMActive(sw, "space"));
5038214e71cSJoe PetscFunctionReturn(PETSC_SUCCESS);
5048214e71cSJoe }
5058214e71cSJoe
f0_grad_phi2(PetscInt dim,PetscInt Nf,PetscInt NfAux,const PetscInt uOff[],const PetscInt uOff_x[],const PetscScalar u[],const PetscScalar u_t[],const PetscScalar u_x[],const PetscInt aOff[],const PetscInt aOff_x[],const PetscScalar a[],const PetscScalar a_t[],const PetscScalar a_x[],PetscReal t,const PetscReal x[],PetscInt numConstants,const PetscScalar constants[],PetscScalar f0[])506fd7102fcSMatthew G. Knepley static void f0_grad_phi2(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
507fd7102fcSMatthew G. Knepley {
508fd7102fcSMatthew G. Knepley f0[0] = 0.;
509fd7102fcSMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) f0[0] += PetscSqr(u_x[uOff_x[0] + d * dim + d]);
510fd7102fcSMatthew G. Knepley }
511fd7102fcSMatthew G. Knepley
MonitorEField(TS ts,PetscInt step,PetscReal t,Vec U,void * Ctx)512*2a8381b2SBarry Smith static PetscErrorCode MonitorEField(TS ts, PetscInt step, PetscReal t, Vec U, void *Ctx)
5138214e71cSJoe {
514*2a8381b2SBarry Smith AppCtx *ctx = (AppCtx *)Ctx;
515f1e6e573SMatthew G. Knepley DM sw;
516fd7102fcSMatthew G. Knepley PetscScalar intESq;
517f1e6e573SMatthew G. Knepley PetscReal *E, *x, *weight;
518f1e6e573SMatthew G. Knepley PetscReal Enorm = 0., lgEnorm, lgEmax, sum = 0., Emax = 0., chargesum = 0.;
519f1e6e573SMatthew G. Knepley PetscReal pmoments[4]; /* \int f, \int v f, \int v^2 f */
520fd7102fcSMatthew G. Knepley PetscInt *species, dim, Np, gNp;
521fd7102fcSMatthew G. Knepley MPI_Comm comm;
5228214e71cSJoe
5238214e71cSJoe PetscFunctionBeginUser;
524*2a8381b2SBarry Smith if (step < 0 || !ctx->validE) PetscFunctionReturn(PETSC_SUCCESS);
525fd7102fcSMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)ts, &comm));
5268214e71cSJoe PetscCall(TSGetDM(ts, &sw));
5278214e71cSJoe PetscCall(DMGetDimension(sw, &dim));
5288214e71cSJoe PetscCall(DMSwarmGetLocalSize(sw, &Np));
529fd7102fcSMatthew G. Knepley PetscCall(DMSwarmGetSize(sw, &gNp));
5308214e71cSJoe PetscCall(DMSwarmSortGetAccess(sw));
5318214e71cSJoe PetscCall(DMSwarmGetField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&x));
5328214e71cSJoe PetscCall(DMSwarmGetField(sw, "E_field", NULL, NULL, (void **)&E));
5338214e71cSJoe PetscCall(DMSwarmGetField(sw, "species", NULL, NULL, (void **)&species));
5348214e71cSJoe PetscCall(DMSwarmGetField(sw, "w_q", NULL, NULL, (void **)&weight));
5358214e71cSJoe
536f1e6e573SMatthew G. Knepley for (PetscInt p = 0; p < Np; ++p) {
537f1e6e573SMatthew G. Knepley for (PetscInt d = 0; d < 1; ++d) {
538f1e6e573SMatthew G. Knepley PetscReal temp = PetscAbsReal(E[p * dim + d]);
5398214e71cSJoe if (temp > Emax) Emax = temp;
5408214e71cSJoe }
5418214e71cSJoe Enorm += PetscSqrtReal(E[p * dim] * E[p * dim]);
5428214e71cSJoe sum += E[p * dim];
543*2a8381b2SBarry Smith chargesum += ctx->charges[0] * weight[p];
5448214e71cSJoe }
545fd7102fcSMatthew G. Knepley PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &Emax, 1, MPIU_REAL, MPIU_MAX, comm));
5468214e71cSJoe lgEnorm = Enorm != 0 ? PetscLog10Real(Enorm) : -16.;
547*2a8381b2SBarry Smith lgEmax = Emax != 0 ? PetscLog10Real(Emax) : ctx->drawlgEmin;
5488214e71cSJoe
549fd7102fcSMatthew G. Knepley PetscDS ds;
550fd7102fcSMatthew G. Knepley Vec phi;
551fd7102fcSMatthew G. Knepley
552*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmPot, "phi", &phi));
553*2a8381b2SBarry Smith PetscCall(DMGetDS(ctx->dmPot, &ds));
554fd7102fcSMatthew G. Knepley PetscCall(PetscDSSetObjective(ds, 0, &f0_grad_phi2));
555*2a8381b2SBarry Smith PetscCall(DMPlexComputeIntegralFEM(ctx->dmPot, phi, &intESq, ctx));
556*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmPot, "phi", &phi));
557fd7102fcSMatthew G. Knepley
5588214e71cSJoe PetscCall(DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&x));
5598214e71cSJoe PetscCall(DMSwarmRestoreField(sw, "w_q", NULL, NULL, (void **)&weight));
5608214e71cSJoe PetscCall(DMSwarmRestoreField(sw, "E_field", NULL, NULL, (void **)&E));
5618214e71cSJoe PetscCall(DMSwarmRestoreField(sw, "species", NULL, NULL, (void **)&species));
562*2a8381b2SBarry Smith PetscCall(PetscDrawLGAddPoint(ctx->drawlgE, &t, &lgEmax));
563*2a8381b2SBarry Smith PetscCall(PetscDrawLGDraw(ctx->drawlgE));
56475155f48SMatthew G. Knepley PetscDraw draw;
565*2a8381b2SBarry Smith PetscCall(PetscDrawLGGetDraw(ctx->drawlgE, &draw));
56675155f48SMatthew G. Knepley PetscCall(PetscDrawSave(draw));
567f1e6e573SMatthew G. Knepley
568f1e6e573SMatthew G. Knepley PetscCall(DMSwarmComputeMoments(sw, "velocity", "w_q", pmoments));
569fd7102fcSMatthew G. Knepley PetscCall(PetscPrintf(comm, "E: %f\t%+e\t%e\t%f\t%20.15e\t%f\t%f\t%f\t%20.15e\t%20.15e\t%20.15e\t%" PetscInt_FMT "\t(%" PetscInt_FMT ")\n", (double)t, (double)sum, (double)Enorm, (double)lgEnorm, (double)Emax, (double)lgEmax, (double)chargesum, (double)pmoments[0], (double)pmoments[1], (double)pmoments[1 + dim], (double)PetscSqrtReal(intESq), gNp, step));
57075155f48SMatthew G. Knepley PetscCall(DMViewFromOptions(sw, NULL, "-sw_efield_view"));
571f1e6e573SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
572f1e6e573SMatthew G. Knepley }
573f1e6e573SMatthew G. Knepley
MonitorMoments(TS ts,PetscInt step,PetscReal t,Vec U,void * Ctx)574*2a8381b2SBarry Smith static PetscErrorCode MonitorMoments(TS ts, PetscInt step, PetscReal t, Vec U, void *Ctx)
575f1e6e573SMatthew G. Knepley {
576*2a8381b2SBarry Smith AppCtx *ctx = (AppCtx *)Ctx;
577f1e6e573SMatthew G. Knepley DM sw;
578f1e6e573SMatthew G. Knepley PetscReal pmoments[4], fmoments[4]; /* \int f, \int v f, \int v^2 f */
579f1e6e573SMatthew G. Knepley
580f1e6e573SMatthew G. Knepley PetscFunctionBeginUser;
581f1e6e573SMatthew G. Knepley if (step < 0) PetscFunctionReturn(PETSC_SUCCESS);
582f1e6e573SMatthew G. Knepley PetscCall(TSGetDM(ts, &sw));
583f1e6e573SMatthew G. Knepley
584f1e6e573SMatthew G. Knepley PetscCall(DMSwarmComputeMoments(sw, "velocity", "w_q", pmoments));
585*2a8381b2SBarry Smith PetscCall(computeVelocityFEMMoments(sw, fmoments, ctx));
586f1e6e573SMatthew G. Knepley
587f1e6e573SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_WORLD, "%f\t%f\t%f\t%f\t%f\t%f\t%f\n", (double)t, (double)pmoments[0], (double)pmoments[1], (double)pmoments[3], (double)fmoments[0], (double)fmoments[1], (double)fmoments[2]));
5888214e71cSJoe PetscFunctionReturn(PETSC_SUCCESS);
5898214e71cSJoe }
5908214e71cSJoe
MonitorInitialConditions(TS ts,PetscInt step,PetscReal t,Vec U,void * Ctx)591*2a8381b2SBarry Smith PetscErrorCode MonitorInitialConditions(TS ts, PetscInt step, PetscReal t, Vec U, void *Ctx)
5928214e71cSJoe {
593*2a8381b2SBarry Smith AppCtx *ctx = (AppCtx *)Ctx;
594b02f317dSMatthew G. Knepley DM sw;
595fd7102fcSMatthew G. Knepley PetscDraw drawic_x, drawic_v;
5968214e71cSJoe PetscReal *weight, *pos, *vel;
597b02f317dSMatthew G. Knepley PetscInt dim, Np;
5988214e71cSJoe
5998214e71cSJoe PetscFunctionBegin;
6008214e71cSJoe if (step < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates interpolated solution */
601b02f317dSMatthew G. Knepley if (step == 0) {
6028214e71cSJoe PetscCall(TSGetDM(ts, &sw));
6038214e71cSJoe PetscCall(DMGetDimension(sw, &dim));
6048214e71cSJoe PetscCall(DMSwarmGetLocalSize(sw, &Np));
6058214e71cSJoe
606*2a8381b2SBarry Smith PetscCall(PetscDrawHGReset(ctx->drawhgic_x));
607*2a8381b2SBarry Smith PetscCall(PetscDrawHGGetDraw(ctx->drawhgic_x, &drawic_x));
608fd7102fcSMatthew G. Knepley PetscCall(PetscDrawClear(drawic_x));
609fd7102fcSMatthew G. Knepley PetscCall(PetscDrawFlush(drawic_x));
6108214e71cSJoe
611*2a8381b2SBarry Smith PetscCall(PetscDrawHGReset(ctx->drawhgic_v));
612*2a8381b2SBarry Smith PetscCall(PetscDrawHGGetDraw(ctx->drawhgic_v, &drawic_v));
613fd7102fcSMatthew G. Knepley PetscCall(PetscDrawClear(drawic_v));
614fd7102fcSMatthew G. Knepley PetscCall(PetscDrawFlush(drawic_v));
6158214e71cSJoe
616b02f317dSMatthew G. Knepley PetscCall(DMSwarmGetField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&pos));
6178214e71cSJoe PetscCall(DMSwarmGetField(sw, "velocity", NULL, NULL, (void **)&vel));
6188214e71cSJoe PetscCall(DMSwarmGetField(sw, "w_q", NULL, NULL, (void **)&weight));
619b02f317dSMatthew G. Knepley for (PetscInt p = 0; p < Np; ++p) {
620*2a8381b2SBarry Smith PetscCall(PetscDrawHGAddWeightedValue(ctx->drawhgic_x, pos[p * dim], weight[p]));
621*2a8381b2SBarry Smith PetscCall(PetscDrawHGAddWeightedValue(ctx->drawhgic_v, vel[p * dim], weight[p]));
6228214e71cSJoe }
6238214e71cSJoe PetscCall(DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&pos));
6248214e71cSJoe PetscCall(DMSwarmRestoreField(sw, "velocity", NULL, NULL, (void **)&vel));
6258214e71cSJoe PetscCall(DMSwarmRestoreField(sw, "w_q", NULL, NULL, (void **)&weight));
626b02f317dSMatthew G. Knepley
627*2a8381b2SBarry Smith PetscCall(PetscDrawHGDraw(ctx->drawhgic_x));
628*2a8381b2SBarry Smith PetscCall(PetscDrawHGSave(ctx->drawhgic_x));
629*2a8381b2SBarry Smith PetscCall(PetscDrawHGDraw(ctx->drawhgic_v));
630*2a8381b2SBarry Smith PetscCall(PetscDrawHGSave(ctx->drawhgic_v));
6318214e71cSJoe }
6328214e71cSJoe PetscFunctionReturn(PETSC_SUCCESS);
6338214e71cSJoe }
6348214e71cSJoe
635bfe80ac4SPierre Jolivet // Right now, make the complete velocity histogram
MonitorVelocity(TS ts,PetscInt step,PetscReal t,Vec U,void * Ctx)636*2a8381b2SBarry Smith PetscErrorCode MonitorVelocity(TS ts, PetscInt step, PetscReal t, Vec U, void *Ctx)
637fd7102fcSMatthew G. Knepley {
638*2a8381b2SBarry Smith AppCtx *ctx = (AppCtx *)Ctx;
639fd7102fcSMatthew G. Knepley DM sw, dm;
640fd7102fcSMatthew G. Knepley Vec ks;
641f8662bd6SBarry Smith PetscProbFn *cdf;
642fd7102fcSMatthew G. Knepley PetscDraw drawcell_v;
643fd7102fcSMatthew G. Knepley PetscScalar *ksa;
644fd7102fcSMatthew G. Knepley PetscReal *weight, *vel;
645fd7102fcSMatthew G. Knepley PetscInt *pidx;
646*2a8381b2SBarry Smith PetscInt dim, Npc, cStart, cEnd, cell = ctx->velocity_monitor;
647fd7102fcSMatthew G. Knepley
648fd7102fcSMatthew G. Knepley PetscFunctionBegin;
649fd7102fcSMatthew G. Knepley PetscCall(TSGetDM(ts, &sw));
650fd7102fcSMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim));
651fd7102fcSMatthew G. Knepley
652fd7102fcSMatthew G. Knepley PetscCall(DMSwarmGetCellDM(sw, &dm));
653fd7102fcSMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
654fd7102fcSMatthew G. Knepley PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &ks));
655fd7102fcSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)ks, "KS Statistic by Cell"));
656fd7102fcSMatthew G. Knepley PetscCall(VecSetSizes(ks, cEnd - cStart, PETSC_DETERMINE));
657fd7102fcSMatthew G. Knepley PetscCall(VecSetFromOptions(ks));
658fd7102fcSMatthew G. Knepley switch (dim) {
659fd7102fcSMatthew G. Knepley case 1:
660fd7102fcSMatthew G. Knepley //cdf = PetscCDFMaxwellBoltzmann1D;
661fd7102fcSMatthew G. Knepley cdf = PetscCDFGaussian1D;
662fd7102fcSMatthew G. Knepley break;
663fd7102fcSMatthew G. Knepley case 2:
664fd7102fcSMatthew G. Knepley cdf = PetscCDFMaxwellBoltzmann2D;
665fd7102fcSMatthew G. Knepley break;
666fd7102fcSMatthew G. Knepley case 3:
667fd7102fcSMatthew G. Knepley cdf = PetscCDFMaxwellBoltzmann3D;
668fd7102fcSMatthew G. Knepley break;
669fd7102fcSMatthew G. Knepley default:
670fd7102fcSMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Dimension %" PetscInt_FMT " not supported", dim);
671fd7102fcSMatthew G. Knepley }
672fd7102fcSMatthew G. Knepley
673*2a8381b2SBarry Smith PetscCall(PetscDrawHGReset(ctx->drawhgcell_v));
674*2a8381b2SBarry Smith PetscCall(PetscDrawHGGetDraw(ctx->drawhgcell_v, &drawcell_v));
675fd7102fcSMatthew G. Knepley PetscCall(PetscDrawClear(drawcell_v));
676fd7102fcSMatthew G. Knepley PetscCall(PetscDrawFlush(drawcell_v));
677fd7102fcSMatthew G. Knepley
678fd7102fcSMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "velocity", NULL, NULL, (void **)&vel));
679fd7102fcSMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "w_q", NULL, NULL, (void **)&weight));
680fd7102fcSMatthew G. Knepley PetscCall(DMSwarmSortGetAccess(sw));
681fd7102fcSMatthew G. Knepley PetscCall(VecGetArrayWrite(ks, &ksa));
682fd7102fcSMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) {
683fd7102fcSMatthew G. Knepley Vec cellv, cellw;
684fd7102fcSMatthew G. Knepley PetscScalar *cella, *cellaw;
685fd7102fcSMatthew G. Knepley PetscReal totWgt = 0.;
686fd7102fcSMatthew G. Knepley
687fd7102fcSMatthew G. Knepley PetscCall(DMSwarmSortGetPointsPerCell(sw, c, &Npc, &pidx));
688fd7102fcSMatthew G. Knepley PetscCall(VecCreate(PETSC_COMM_SELF, &cellv));
689fd7102fcSMatthew G. Knepley PetscCall(VecSetBlockSize(cellv, dim));
690fd7102fcSMatthew G. Knepley PetscCall(VecSetSizes(cellv, Npc * dim, Npc));
691fd7102fcSMatthew G. Knepley PetscCall(VecSetFromOptions(cellv));
692fd7102fcSMatthew G. Knepley PetscCall(VecCreate(PETSC_COMM_SELF, &cellw));
693fd7102fcSMatthew G. Knepley PetscCall(VecSetSizes(cellw, Npc, Npc));
694fd7102fcSMatthew G. Knepley PetscCall(VecSetFromOptions(cellw));
695fd7102fcSMatthew G. Knepley PetscCall(VecGetArrayWrite(cellv, &cella));
696fd7102fcSMatthew G. Knepley PetscCall(VecGetArrayWrite(cellw, &cellaw));
697fd7102fcSMatthew G. Knepley for (PetscInt q = 0; q < Npc; ++q) {
698fd7102fcSMatthew G. Knepley const PetscInt p = pidx[q];
699*2a8381b2SBarry Smith if (c == cell) PetscCall(PetscDrawHGAddWeightedValue(ctx->drawhgcell_v, vel[p * dim], weight[p]));
700fd7102fcSMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) cella[q * dim + d] = vel[p * dim + d];
701fd7102fcSMatthew G. Knepley cellaw[q] = weight[p];
702fd7102fcSMatthew G. Knepley totWgt += weight[p];
703fd7102fcSMatthew G. Knepley }
704fd7102fcSMatthew G. Knepley PetscCall(VecRestoreArrayWrite(cellv, &cella));
705fd7102fcSMatthew G. Knepley PetscCall(VecRestoreArrayWrite(cellw, &cellaw));
706fd7102fcSMatthew G. Knepley PetscCall(VecScale(cellw, 1. / totWgt));
707fd7102fcSMatthew G. Knepley PetscCall(PetscProbComputeKSStatisticWeighted(cellv, cellw, cdf, &ksa[c - cStart]));
708fd7102fcSMatthew G. Knepley PetscCall(VecDestroy(&cellv));
709fd7102fcSMatthew G. Knepley PetscCall(VecDestroy(&cellw));
710fd7102fcSMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(sw, c, &Npc, &pidx));
711fd7102fcSMatthew G. Knepley }
712fd7102fcSMatthew G. Knepley PetscCall(VecRestoreArrayWrite(ks, &ksa));
713fd7102fcSMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "velocity", NULL, NULL, (void **)&vel));
714fd7102fcSMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "w_q", NULL, NULL, (void **)&weight));
715fd7102fcSMatthew G. Knepley PetscCall(DMSwarmSortRestoreAccess(sw));
716fd7102fcSMatthew G. Knepley
717fd7102fcSMatthew G. Knepley PetscReal minalpha, maxalpha;
718fd7102fcSMatthew G. Knepley PetscInt mincell, maxcell;
719fd7102fcSMatthew G. Knepley
720fd7102fcSMatthew G. Knepley PetscCall(VecFilter(ks, PETSC_SMALL));
721fd7102fcSMatthew G. Knepley PetscCall(VecMin(ks, &mincell, &minalpha));
722fd7102fcSMatthew G. Knepley PetscCall(VecMax(ks, &maxcell, &maxalpha));
723fd7102fcSMatthew G. Knepley PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), "Step %" PetscInt_FMT ": Min/Max KS statistic %g/%g in cell %" PetscInt_FMT "/%" PetscInt_FMT "\n", step, minalpha, maxalpha, mincell, maxcell));
724fd7102fcSMatthew G. Knepley PetscCall(VecViewFromOptions(ks, NULL, "-ks_view"));
725fd7102fcSMatthew G. Knepley PetscCall(VecDestroy(&ks));
726fd7102fcSMatthew G. Knepley
727*2a8381b2SBarry Smith PetscCall(PetscDrawHGDraw(ctx->drawhgcell_v));
728*2a8381b2SBarry Smith PetscCall(PetscDrawHGSave(ctx->drawhgcell_v));
729fd7102fcSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
730fd7102fcSMatthew G. Knepley }
731fd7102fcSMatthew G. Knepley
MonitorPositions_2D(TS ts,PetscInt step,PetscReal t,Vec U,void * Ctx)732*2a8381b2SBarry Smith static PetscErrorCode MonitorPositions_2D(TS ts, PetscInt step, PetscReal t, Vec U, void *Ctx)
7338214e71cSJoe {
734*2a8381b2SBarry Smith AppCtx *ctx = (AppCtx *)Ctx;
7358214e71cSJoe DM dm, sw;
736f940b0e3Sdanofinn PetscDrawAxis axis;
737f940b0e3Sdanofinn char title[1024];
7388214e71cSJoe PetscScalar *x, *v, *weight;
7398214e71cSJoe PetscReal lower[3], upper[3], speed;
7408214e71cSJoe const PetscInt *s;
7418214e71cSJoe PetscInt dim, cStart, cEnd, c;
7428214e71cSJoe
7438214e71cSJoe PetscFunctionBeginUser;
744*2a8381b2SBarry Smith if (step > 0 && step % ctx->ostep == 0) {
7458214e71cSJoe PetscCall(TSGetDM(ts, &sw));
7468214e71cSJoe PetscCall(DMSwarmGetCellDM(sw, &dm));
7478214e71cSJoe PetscCall(DMGetDimension(dm, &dim));
7488214e71cSJoe PetscCall(DMGetBoundingBox(dm, lower, upper));
7498214e71cSJoe PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
7508214e71cSJoe PetscCall(DMSwarmGetField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&x));
7518214e71cSJoe PetscCall(DMSwarmGetField(sw, "velocity", NULL, NULL, (void **)&v));
7528214e71cSJoe PetscCall(DMSwarmGetField(sw, "w_q", NULL, NULL, (void **)&weight));
7538214e71cSJoe PetscCall(DMSwarmGetField(sw, "species", NULL, NULL, (void **)&s));
7548214e71cSJoe PetscCall(DMSwarmSortGetAccess(sw));
755*2a8381b2SBarry Smith PetscCall(PetscDrawSPReset(ctx->drawspX));
756*2a8381b2SBarry Smith PetscCall(PetscDrawSPGetAxis(ctx->drawspX, &axis));
757f940b0e3Sdanofinn PetscCall(PetscSNPrintf(title, 1024, "Step %" PetscInt_FMT " Time: %g", step, (double)t));
758f940b0e3Sdanofinn PetscCall(PetscDrawAxisSetLabels(axis, title, "x", "v"));
759*2a8381b2SBarry Smith PetscCall(PetscDrawSPSetLimits(ctx->drawspX, lower[0], upper[0], lower[1], upper[1]));
760*2a8381b2SBarry Smith PetscCall(PetscDrawSPSetLimits(ctx->drawspX, lower[0], upper[0], -12, 12));
7618214e71cSJoe for (c = 0; c < cEnd - cStart; ++c) {
7628214e71cSJoe PetscInt *pidx, Npc, q;
7638214e71cSJoe PetscCall(DMSwarmSortGetPointsPerCell(sw, c, &Npc, &pidx));
7648214e71cSJoe for (q = 0; q < Npc; ++q) {
7658214e71cSJoe const PetscInt p = pidx[q];
7668214e71cSJoe if (s[p] == 0) {
7679072cb8bSMatthew G. Knepley speed = 0.;
7689072cb8bSMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) speed += PetscSqr(v[p * dim + d]);
7699072cb8bSMatthew G. Knepley speed = PetscSqrtReal(speed);
770045208b8SMatthew G. Knepley if (dim == 1) {
771*2a8381b2SBarry Smith PetscCall(PetscDrawSPAddPointColorized(ctx->drawspX, &x[p * dim], &v[p * dim], &speed));
7728214e71cSJoe } else {
773*2a8381b2SBarry Smith PetscCall(PetscDrawSPAddPointColorized(ctx->drawspX, &x[p * dim], &x[p * dim + 1], &speed));
7748214e71cSJoe }
7758214e71cSJoe } else if (s[p] == 1) {
776*2a8381b2SBarry Smith PetscCall(PetscDrawSPAddPoint(ctx->drawspX, &x[p * dim], &v[p * dim]));
7778214e71cSJoe }
7788214e71cSJoe }
77984467f86SMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(sw, c, &Npc, &pidx));
7808214e71cSJoe }
781*2a8381b2SBarry Smith PetscCall(PetscDrawSPDraw(ctx->drawspX, PETSC_TRUE));
78275155f48SMatthew G. Knepley PetscDraw draw;
783*2a8381b2SBarry Smith PetscCall(PetscDrawSPGetDraw(ctx->drawspX, &draw));
78475155f48SMatthew G. Knepley PetscCall(PetscDrawSave(draw));
7858214e71cSJoe PetscCall(DMSwarmSortRestoreAccess(sw));
7868214e71cSJoe PetscCall(DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&x));
7878214e71cSJoe PetscCall(DMSwarmRestoreField(sw, "w_q", NULL, NULL, (void **)&weight));
7888214e71cSJoe PetscCall(DMSwarmRestoreField(sw, "velocity", NULL, NULL, (void **)&v));
7898214e71cSJoe PetscCall(DMSwarmRestoreField(sw, "species", NULL, NULL, (void **)&s));
7908214e71cSJoe }
7918214e71cSJoe PetscFunctionReturn(PETSC_SUCCESS);
7928214e71cSJoe }
7938214e71cSJoe
MonitorPoisson(TS ts,PetscInt step,PetscReal t,Vec U,void * Ctx)794*2a8381b2SBarry Smith static PetscErrorCode MonitorPoisson(TS ts, PetscInt step, PetscReal t, Vec U, void *Ctx)
7958214e71cSJoe {
796*2a8381b2SBarry Smith AppCtx *ctx = (AppCtx *)Ctx;
7978214e71cSJoe DM dm, sw;
7988214e71cSJoe
7998214e71cSJoe PetscFunctionBeginUser;
800*2a8381b2SBarry Smith if (step > 0 && step % ctx->ostep == 0) {
8018214e71cSJoe PetscCall(TSGetDM(ts, &sw));
8028214e71cSJoe PetscCall(DMSwarmGetCellDM(sw, &dm));
8039072cb8bSMatthew G. Knepley
804*2a8381b2SBarry Smith if (ctx->validE) {
8059072cb8bSMatthew G. Knepley PetscScalar *x, *E, *weight;
8069072cb8bSMatthew G. Knepley PetscReal lower[3], upper[3], xval;
8079072cb8bSMatthew G. Knepley PetscDraw draw;
8089072cb8bSMatthew G. Knepley PetscInt dim, cStart, cEnd;
8099072cb8bSMatthew G. Knepley
8108214e71cSJoe PetscCall(DMGetDimension(dm, &dim));
8118214e71cSJoe PetscCall(DMGetBoundingBox(dm, lower, upper));
8128214e71cSJoe PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
8138214e71cSJoe
814*2a8381b2SBarry Smith PetscCall(PetscDrawSPReset(ctx->drawspE));
8158214e71cSJoe PetscCall(DMSwarmGetField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&x));
8168214e71cSJoe PetscCall(DMSwarmGetField(sw, "E_field", NULL, NULL, (void **)&E));
8178214e71cSJoe PetscCall(DMSwarmGetField(sw, "w_q", NULL, NULL, (void **)&weight));
8188214e71cSJoe
8198214e71cSJoe PetscCall(DMSwarmSortGetAccess(sw));
8209072cb8bSMatthew G. Knepley for (PetscInt c = 0; c < cEnd - cStart; ++c) {
82175155f48SMatthew G. Knepley PetscReal Eavg = 0.0;
8229072cb8bSMatthew G. Knepley PetscInt *pidx, Npc;
8239072cb8bSMatthew G. Knepley
8248214e71cSJoe PetscCall(DMSwarmSortGetPointsPerCell(sw, c, &Npc, &pidx));
8259072cb8bSMatthew G. Knepley for (PetscInt q = 0; q < Npc; ++q) {
8268214e71cSJoe const PetscInt p = pidx[q];
82775155f48SMatthew G. Knepley Eavg += E[p * dim];
8288214e71cSJoe }
82975155f48SMatthew G. Knepley Eavg /= Npc;
8308214e71cSJoe xval = (c + 0.5) * ((upper[0] - lower[0]) / (cEnd - cStart));
831*2a8381b2SBarry Smith PetscCall(PetscDrawSPAddPoint(ctx->drawspE, &xval, &Eavg));
83284467f86SMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(sw, c, &Npc, &pidx));
8338214e71cSJoe }
834*2a8381b2SBarry Smith PetscCall(PetscDrawSPDraw(ctx->drawspE, PETSC_TRUE));
835*2a8381b2SBarry Smith PetscCall(PetscDrawSPGetDraw(ctx->drawspE, &draw));
83675155f48SMatthew G. Knepley PetscCall(PetscDrawSave(draw));
8378214e71cSJoe PetscCall(DMSwarmSortRestoreAccess(sw));
8388214e71cSJoe PetscCall(DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&x));
8398214e71cSJoe PetscCall(DMSwarmRestoreField(sw, "w_q", NULL, NULL, (void **)&weight));
8408214e71cSJoe PetscCall(DMSwarmRestoreField(sw, "E_field", NULL, NULL, (void **)&E));
8419072cb8bSMatthew G. Knepley }
84275155f48SMatthew G. Knepley
843b02f317dSMatthew G. Knepley Vec rho, rhohat, phi;
84475155f48SMatthew G. Knepley
845*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmPot, "rho", &rho));
846*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmPot, "rhohat", &rhohat));
847*2a8381b2SBarry Smith PetscCall(VecView(rho, ctx->viewerRho));
848*2a8381b2SBarry Smith PetscCall(VecISCopy(ctx->fftX, ctx->fftReal, SCATTER_FORWARD, rho));
849*2a8381b2SBarry Smith PetscCall(MatMult(ctx->fftPot, ctx->fftX, ctx->fftY));
850*2a8381b2SBarry Smith PetscCall(VecFilter(ctx->fftY, PETSC_SMALL));
851*2a8381b2SBarry Smith PetscCall(VecViewFromOptions(ctx->fftX, NULL, "-real_view"));
852*2a8381b2SBarry Smith PetscCall(VecViewFromOptions(ctx->fftY, NULL, "-fft_view"));
853*2a8381b2SBarry Smith PetscCall(VecISCopy(ctx->fftY, ctx->fftReal, SCATTER_REVERSE, rhohat));
854fd7102fcSMatthew G. Knepley PetscCall(VecSetValue(rhohat, 0, 0., INSERT_VALUES)); // Remove large DC component
855*2a8381b2SBarry Smith PetscCall(VecView(rhohat, ctx->viewerRhoHat));
856*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmPot, "rho", &rho));
857*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmPot, "rhohat", &rhohat));
858b02f317dSMatthew G. Knepley
859*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmPot, "phi", &phi));
860*2a8381b2SBarry Smith PetscCall(VecView(phi, ctx->viewerPhi));
861*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmPot, "phi", &phi));
8628214e71cSJoe }
8638214e71cSJoe PetscFunctionReturn(PETSC_SUCCESS);
8648214e71cSJoe }
8658214e71cSJoe
SetupParameters(MPI_Comm comm,AppCtx * ctx)8668214e71cSJoe static PetscErrorCode SetupParameters(MPI_Comm comm, AppCtx *ctx)
8678214e71cSJoe {
8688214e71cSJoe PetscBag bag;
8698214e71cSJoe Parameter *p;
8708214e71cSJoe
8718214e71cSJoe PetscFunctionBeginUser;
8728214e71cSJoe /* setup PETSc parameter bag */
873*2a8381b2SBarry Smith PetscCall(PetscBagGetData(ctx->bag, &p));
8748214e71cSJoe PetscCall(PetscBagSetName(ctx->bag, "par", "Vlasov-Poisson Parameters"));
8758214e71cSJoe bag = ctx->bag;
8768214e71cSJoe PetscCall(PetscBagRegisterScalar(bag, &p->v0, 1.0, "v0", "Velocity scale, m/s"));
8778214e71cSJoe PetscCall(PetscBagRegisterScalar(bag, &p->t0, 1.0, "t0", "Time scale, s"));
8788214e71cSJoe PetscCall(PetscBagRegisterScalar(bag, &p->x0, 1.0, "x0", "Space scale, m"));
8798214e71cSJoe PetscCall(PetscBagRegisterScalar(bag, &p->v0, 1.0, "phi0", "Potential scale, kg*m^2/A*s^3"));
8808214e71cSJoe PetscCall(PetscBagRegisterScalar(bag, &p->q0, 1.0, "q0", "Charge Scale, A*s"));
8818214e71cSJoe PetscCall(PetscBagRegisterScalar(bag, &p->m0, 1.0, "m0", "Mass Scale, kg"));
8828214e71cSJoe PetscCall(PetscBagRegisterScalar(bag, &p->epsi0, 1.0, "epsi0", "Permittivity of Free Space, kg"));
8838214e71cSJoe PetscCall(PetscBagRegisterScalar(bag, &p->kb, 1.0, "kb", "Boltzmann Constant, m^2 kg/s^2 K^1"));
8848214e71cSJoe
8858214e71cSJoe PetscCall(PetscBagRegisterScalar(bag, &p->sigma, 1.0, "sigma", "Charge per unit area, C/m^3"));
8868214e71cSJoe PetscCall(PetscBagRegisterScalar(bag, &p->poissonNumber, 1.0, "poissonNumber", "Non-Dimensional Poisson Number"));
8878214e71cSJoe PetscCall(PetscBagRegisterScalar(bag, &p->vlasovNumber, 1.0, "vlasovNumber", "Non-Dimensional Vlasov Number"));
8888214e71cSJoe PetscCall(PetscBagSetFromOptions(bag));
8898214e71cSJoe {
8908214e71cSJoe PetscViewer viewer;
8918214e71cSJoe PetscViewerFormat format;
8928214e71cSJoe PetscBool flg;
8938214e71cSJoe
894648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(comm, NULL, NULL, "-param_view", &viewer, &format, &flg));
8958214e71cSJoe if (flg) {
8968214e71cSJoe PetscCall(PetscViewerPushFormat(viewer, format));
8978214e71cSJoe PetscCall(PetscBagView(bag, viewer));
8988214e71cSJoe PetscCall(PetscViewerFlush(viewer));
8998214e71cSJoe PetscCall(PetscViewerPopFormat(viewer));
9008214e71cSJoe PetscCall(PetscViewerDestroy(&viewer));
9018214e71cSJoe }
9028214e71cSJoe }
9038214e71cSJoe PetscFunctionReturn(PETSC_SUCCESS);
9048214e71cSJoe }
9058214e71cSJoe
CreateMesh(MPI_Comm comm,AppCtx * ctx,DM * dm)906*2a8381b2SBarry Smith static PetscErrorCode CreateMesh(MPI_Comm comm, AppCtx *ctx, DM *dm)
907d71ae5a4SJacob Faibussowitsch {
908b80bf5b1SJoe Pusztay PetscFunctionBeginUser;
9099566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm));
9109566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX));
9119566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(*dm));
9129072cb8bSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)*dm, "space"));
9139566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(*dm, NULL, "-dm_view"));
914f1e6e573SMatthew G. Knepley
915f1e6e573SMatthew G. Knepley // Cache the mesh geometry
916f1e6e573SMatthew G. Knepley DMField coordField;
917f1e6e573SMatthew G. Knepley IS cellIS;
918f1e6e573SMatthew G. Knepley PetscQuadrature quad;
919f1e6e573SMatthew G. Knepley PetscReal *wt, *pt;
920f1e6e573SMatthew G. Knepley PetscInt cdim, cStart, cEnd;
921f1e6e573SMatthew G. Knepley
922f1e6e573SMatthew G. Knepley PetscCall(DMGetCoordinateField(*dm, &coordField));
923f1e6e573SMatthew G. Knepley PetscCheck(coordField, comm, PETSC_ERR_USER, "DM must have a coordinate field");
924f1e6e573SMatthew G. Knepley PetscCall(DMGetCoordinateDim(*dm, &cdim));
925f1e6e573SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(*dm, 0, &cStart, &cEnd));
926f1e6e573SMatthew G. Knepley PetscCall(ISCreateStride(PETSC_COMM_SELF, cEnd - cStart, cStart, 1, &cellIS));
927f1e6e573SMatthew G. Knepley PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, &quad));
928f1e6e573SMatthew G. Knepley PetscCall(PetscMalloc1(1, &wt));
929f1e6e573SMatthew G. Knepley PetscCall(PetscMalloc1(2, &pt));
930f1e6e573SMatthew G. Knepley wt[0] = 1.;
931f1e6e573SMatthew G. Knepley pt[0] = -1.;
932f1e6e573SMatthew G. Knepley pt[1] = -1.;
933f1e6e573SMatthew G. Knepley PetscCall(PetscQuadratureSetData(quad, cdim, 1, 1, pt, wt));
934*2a8381b2SBarry Smith PetscCall(DMFieldCreateFEGeom(coordField, cellIS, quad, PETSC_FEGEOM_BASIC, &ctx->fegeom));
935f1e6e573SMatthew G. Knepley PetscCall(PetscQuadratureDestroy(&quad));
936f1e6e573SMatthew G. Knepley PetscCall(ISDestroy(&cellIS));
9373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
938b80bf5b1SJoe Pusztay }
939b80bf5b1SJoe Pusztay
ion_f0(PetscInt dim,PetscInt Nf,PetscInt NfAux,const PetscInt uOff[],const PetscInt uOff_x[],const PetscScalar u[],const PetscScalar u_t[],const PetscScalar u_x[],const PetscInt aOff[],const PetscInt aOff_x[],const PetscScalar a[],const PetscScalar a_t[],const PetscScalar a_x[],PetscReal t,const PetscReal x[],PetscInt numConstants,const PetscScalar constants[],PetscScalar f0[])9408214e71cSJoe static void ion_f0(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
9418214e71cSJoe {
9428214e71cSJoe f0[0] = -constants[SIGMA];
9438214e71cSJoe }
9448214e71cSJoe
laplacian_f1(PetscInt dim,PetscInt Nf,PetscInt NfAux,const PetscInt uOff[],const PetscInt uOff_x[],const PetscScalar u[],const PetscScalar u_t[],const PetscScalar u_x[],const PetscInt aOff[],const PetscInt aOff_x[],const PetscScalar a[],const PetscScalar a_t[],const PetscScalar a_x[],PetscReal t,const PetscReal x[],PetscInt numConstants,const PetscScalar constants[],PetscScalar f1[])945d71ae5a4SJacob Faibussowitsch static void laplacian_f1(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[])
946d71ae5a4SJacob Faibussowitsch {
947b80bf5b1SJoe Pusztay PetscInt d;
948ad540459SPierre Jolivet for (d = 0; d < dim; ++d) f1[d] = u_x[d];
949b80bf5b1SJoe Pusztay }
950b80bf5b1SJoe Pusztay
laplacian_g3(PetscInt dim,PetscInt Nf,PetscInt NfAux,const PetscInt uOff[],const PetscInt uOff_x[],const PetscScalar u[],const PetscScalar u_t[],const PetscScalar u_x[],const PetscInt aOff[],const PetscInt aOff_x[],const PetscScalar a[],const PetscScalar a_t[],const PetscScalar a_x[],PetscReal t,PetscReal u_tShift,const PetscReal x[],PetscInt numConstants,const PetscScalar constants[],PetscScalar g3[])9518214e71cSJoe static void laplacian_g3(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])
952d71ae5a4SJacob Faibussowitsch {
953b80bf5b1SJoe Pusztay PetscInt d;
954ad540459SPierre Jolivet for (d = 0; d < dim; ++d) g3[d * dim + d] = 1.0;
955b80bf5b1SJoe Pusztay }
956b80bf5b1SJoe Pusztay
zero(PetscInt dim,PetscReal time,const PetscReal x[],PetscInt Nc,PetscScalar * u,PetscCtx ctx)957*2a8381b2SBarry Smith static PetscErrorCode zero(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, PetscCtx ctx)
958d71ae5a4SJacob Faibussowitsch {
9598214e71cSJoe *u = 0.0;
9608214e71cSJoe return PETSC_SUCCESS;
961b80bf5b1SJoe Pusztay }
962b80bf5b1SJoe Pusztay
963b80bf5b1SJoe Pusztay /*
9648214e71cSJoe / I -grad\ / q \ = /0\
9658214e71cSJoe \-div 0 / \phi/ \f/
966b80bf5b1SJoe Pusztay */
f0_q(PetscInt dim,PetscInt Nf,PetscInt NfAux,const PetscInt uOff[],const PetscInt uOff_x[],const PetscScalar u[],const PetscScalar u_t[],const PetscScalar u_x[],const PetscInt aOff[],const PetscInt aOff_x[],const PetscScalar a[],const PetscScalar a_t[],const PetscScalar a_x[],PetscReal t,const PetscReal x[],PetscInt numConstants,const PetscScalar constants[],PetscScalar f0[])9678214e71cSJoe static void f0_q(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
968d71ae5a4SJacob Faibussowitsch {
9698214e71cSJoe for (PetscInt d = 0; d < dim; ++d) f0[d] += u[uOff[0] + d];
9708214e71cSJoe }
9718214e71cSJoe
f1_q(PetscInt dim,PetscInt Nf,PetscInt NfAux,const PetscInt uOff[],const PetscInt uOff_x[],const PetscScalar u[],const PetscScalar u_t[],const PetscScalar u_x[],const PetscInt aOff[],const PetscInt aOff_x[],const PetscScalar a[],const PetscScalar a_t[],const PetscScalar a_x[],PetscReal t,const PetscReal x[],PetscInt numConstants,const PetscScalar constants[],PetscScalar f1[])9728214e71cSJoe static void f1_q(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[])
9738214e71cSJoe {
9748214e71cSJoe for (PetscInt d = 0; d < dim; ++d) f1[d * dim + d] = u[uOff[1]];
9758214e71cSJoe }
9768214e71cSJoe
f0_phi_backgroundCharge(PetscInt dim,PetscInt Nf,PetscInt NfAux,const PetscInt uOff[],const PetscInt uOff_x[],const PetscScalar u[],const PetscScalar u_t[],const PetscScalar u_x[],const PetscInt aOff[],const PetscInt aOff_x[],const PetscScalar a[],const PetscScalar a_t[],const PetscScalar a_x[],PetscReal t,const PetscReal x[],PetscInt numConstants,const PetscScalar constants[],PetscScalar f0[])9778214e71cSJoe static void f0_phi_backgroundCharge(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
9788214e71cSJoe {
9798214e71cSJoe f0[0] += constants[SIGMA];
9808214e71cSJoe for (PetscInt d = 0; d < dim; ++d) f0[0] += u_x[uOff_x[0] + d * dim + d];
9818214e71cSJoe }
9828214e71cSJoe
9838214e71cSJoe /* Boundary residual. Dirichlet boundary for u means u_bdy=p*n */
g0_qq(PetscInt dim,PetscInt Nf,PetscInt NfAux,const PetscInt uOff[],const PetscInt uOff_x[],const PetscScalar u[],const PetscScalar u_t[],const PetscScalar u_x[],const PetscInt aOff[],const PetscInt aOff_x[],const PetscScalar a[],const PetscScalar a_t[],const PetscScalar a_x[],PetscReal t,PetscReal u_tShift,const PetscReal x[],PetscInt numConstants,const PetscScalar constants[],PetscScalar g0[])9848214e71cSJoe static void g0_qq(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])
9858214e71cSJoe {
9868214e71cSJoe for (PetscInt d = 0; d < dim; ++d) g0[d * dim + d] = 1.0;
9878214e71cSJoe }
9888214e71cSJoe
g2_qphi(PetscInt dim,PetscInt Nf,PetscInt NfAux,const PetscInt uOff[],const PetscInt uOff_x[],const PetscScalar u[],const PetscScalar u_t[],const PetscScalar u_x[],const PetscInt aOff[],const PetscInt aOff_x[],const PetscScalar a[],const PetscScalar a_t[],const PetscScalar a_x[],PetscReal t,PetscReal u_tShift,const PetscReal x[],PetscInt numConstants,const PetscScalar constants[],PetscScalar g2[])9898214e71cSJoe static void g2_qphi(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[])
9908214e71cSJoe {
9918214e71cSJoe for (PetscInt d = 0; d < dim; ++d) g2[d * dim + d] = 1.0;
9928214e71cSJoe }
9938214e71cSJoe
g1_phiq(PetscInt dim,PetscInt Nf,PetscInt NfAux,const PetscInt uOff[],const PetscInt uOff_x[],const PetscScalar u[],const PetscScalar u_t[],const PetscScalar u_x[],const PetscInt aOff[],const PetscInt aOff_x[],const PetscScalar a[],const PetscScalar a_t[],const PetscScalar a_x[],PetscReal t,PetscReal u_tShift,const PetscReal x[],PetscInt numConstants,const PetscScalar constants[],PetscScalar g1[])9948214e71cSJoe static void g1_phiq(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[])
9958214e71cSJoe {
9968214e71cSJoe for (PetscInt d = 0; d < dim; ++d) g1[d * dim + d] = 1.0;
9978214e71cSJoe }
9988214e71cSJoe
CreateFEM(DM dm,AppCtx * ctx)999*2a8381b2SBarry Smith static PetscErrorCode CreateFEM(DM dm, AppCtx *ctx)
10008214e71cSJoe {
10018214e71cSJoe PetscFE fephi, feq;
10028214e71cSJoe PetscDS ds;
10038214e71cSJoe PetscBool simplex;
10048214e71cSJoe PetscInt dim;
10058214e71cSJoe
10068214e71cSJoe PetscFunctionBeginUser;
10078214e71cSJoe PetscCall(DMGetDimension(dm, &dim));
10088214e71cSJoe PetscCall(DMPlexIsSimplex(dm, &simplex));
1009*2a8381b2SBarry Smith if (ctx->em == EM_MIXED) {
10108214e71cSJoe DMLabel label;
10118214e71cSJoe const PetscInt id = 1;
10128214e71cSJoe
10138214e71cSJoe PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, dim, simplex, "field_", PETSC_DETERMINE, &feq));
10148214e71cSJoe PetscCall(PetscObjectSetName((PetscObject)feq, "field"));
10158214e71cSJoe PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "potential_", PETSC_DETERMINE, &fephi));
10168214e71cSJoe PetscCall(PetscObjectSetName((PetscObject)fephi, "potential"));
10178214e71cSJoe PetscCall(PetscFECopyQuadrature(feq, fephi));
10188214e71cSJoe PetscCall(DMSetField(dm, 0, NULL, (PetscObject)feq));
10198214e71cSJoe PetscCall(DMSetField(dm, 1, NULL, (PetscObject)fephi));
10208214e71cSJoe PetscCall(DMCreateDS(dm));
10218214e71cSJoe PetscCall(PetscFEDestroy(&fephi));
10228214e71cSJoe PetscCall(PetscFEDestroy(&feq));
10238214e71cSJoe
10248214e71cSJoe PetscCall(DMGetLabel(dm, "marker", &label));
10258214e71cSJoe PetscCall(DMGetDS(dm, &ds));
10268214e71cSJoe
10278214e71cSJoe PetscCall(PetscDSSetResidual(ds, 0, f0_q, f1_q));
10288214e71cSJoe PetscCall(PetscDSSetResidual(ds, 1, f0_phi_backgroundCharge, NULL));
10298214e71cSJoe PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_qq, NULL, NULL, NULL));
10308214e71cSJoe PetscCall(PetscDSSetJacobian(ds, 0, 1, NULL, NULL, g2_qphi, NULL));
10318214e71cSJoe PetscCall(PetscDSSetJacobian(ds, 1, 0, NULL, g1_phiq, NULL, NULL));
10328214e71cSJoe
103357d50842SBarry Smith PetscCall(DMAddBoundary(dm, DM_BC_ESSENTIAL, "wall", label, 1, &id, 0, 0, NULL, (PetscVoidFn *)zero, NULL, NULL, NULL));
10348214e71cSJoe
1035f1e6e573SMatthew G. Knepley } else {
10368214e71cSJoe MatNullSpace nullsp;
10378214e71cSJoe PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, NULL, PETSC_DETERMINE, &fephi));
10388214e71cSJoe PetscCall(PetscObjectSetName((PetscObject)fephi, "potential"));
10398214e71cSJoe PetscCall(DMSetField(dm, 0, NULL, (PetscObject)fephi));
10408214e71cSJoe PetscCall(DMCreateDS(dm));
10418214e71cSJoe PetscCall(DMGetDS(dm, &ds));
10428214e71cSJoe PetscCall(PetscDSSetResidual(ds, 0, ion_f0, laplacian_f1));
10438214e71cSJoe PetscCall(PetscDSSetJacobian(ds, 0, 0, NULL, NULL, NULL, laplacian_g3));
10448214e71cSJoe PetscCall(MatNullSpaceCreate(PetscObjectComm((PetscObject)dm), PETSC_TRUE, 0, NULL, &nullsp));
10458214e71cSJoe PetscCall(PetscObjectCompose((PetscObject)fephi, "nullspace", (PetscObject)nullsp));
10468214e71cSJoe PetscCall(MatNullSpaceDestroy(&nullsp));
10478214e71cSJoe PetscCall(PetscFEDestroy(&fephi));
10488214e71cSJoe }
10498214e71cSJoe PetscFunctionReturn(PETSC_SUCCESS);
10508214e71cSJoe }
10518214e71cSJoe
CreatePoisson(DM dm,AppCtx * ctx)1052*2a8381b2SBarry Smith static PetscErrorCode CreatePoisson(DM dm, AppCtx *ctx)
10538214e71cSJoe {
10548214e71cSJoe SNES snes;
10558214e71cSJoe Mat J;
10568214e71cSJoe MatNullSpace nullSpace;
10578214e71cSJoe
10588214e71cSJoe PetscFunctionBeginUser;
1059*2a8381b2SBarry Smith PetscCall(CreateFEM(dm, ctx));
10608214e71cSJoe PetscCall(SNESCreate(PetscObjectComm((PetscObject)dm), &snes));
10618214e71cSJoe PetscCall(SNESSetOptionsPrefix(snes, "em_"));
10628214e71cSJoe PetscCall(SNESSetDM(snes, dm));
1063*2a8381b2SBarry Smith PetscCall(DMPlexSetSNESLocalFEM(dm, PETSC_FALSE, ctx));
10648214e71cSJoe PetscCall(SNESSetFromOptions(snes));
10658214e71cSJoe
10668214e71cSJoe PetscCall(DMCreateMatrix(dm, &J));
10678214e71cSJoe PetscCall(MatNullSpaceCreate(PetscObjectComm((PetscObject)dm), PETSC_TRUE, 0, NULL, &nullSpace));
10688214e71cSJoe PetscCall(MatSetNullSpace(J, nullSpace));
10698214e71cSJoe PetscCall(MatNullSpaceDestroy(&nullSpace));
10708214e71cSJoe PetscCall(SNESSetJacobian(snes, J, J, NULL, NULL));
10718214e71cSJoe PetscCall(MatDestroy(&J));
1072*2a8381b2SBarry Smith if (ctx->em == EM_MIXED) {
10734a0cbf56SMatthew G. Knepley const PetscInt potential = 1;
10744a0cbf56SMatthew G. Knepley
1075*2a8381b2SBarry Smith PetscCall(DMCreateSubDM(dm, 1, &potential, &ctx->isPot, &ctx->dmPot));
10764a0cbf56SMatthew G. Knepley } else {
1077*2a8381b2SBarry Smith ctx->dmPot = dm;
1078*2a8381b2SBarry Smith PetscCall(PetscObjectReference((PetscObject)ctx->dmPot));
10794a0cbf56SMatthew G. Knepley }
1080*2a8381b2SBarry Smith PetscCall(DMCreateMassMatrix(ctx->dmPot, ctx->dmPot, &ctx->M));
1081f1e6e573SMatthew G. Knepley PetscCall(DMPlexCreateClosureIndex(dm, NULL));
1082*2a8381b2SBarry Smith ctx->snes = snes;
10838214e71cSJoe PetscFunctionReturn(PETSC_SUCCESS);
10848214e71cSJoe }
10858214e71cSJoe
PetscPDFPertubedConstant2D(const PetscReal x[],const PetscReal dummy[],PetscReal p[])10868214e71cSJoe PetscErrorCode PetscPDFPertubedConstant2D(const PetscReal x[], const PetscReal dummy[], PetscReal p[])
10878214e71cSJoe {
10888214e71cSJoe p[0] = (1 + 0.01 * PetscCosReal(0.5 * x[0])) / (2 * PETSC_PI);
10898214e71cSJoe p[1] = (1 + 0.01 * PetscCosReal(0.5 * x[1])) / (2 * PETSC_PI);
10908214e71cSJoe return PETSC_SUCCESS;
10918214e71cSJoe }
PetscPDFPertubedConstant1D(const PetscReal x[],const PetscReal dummy[],PetscReal p[])10928214e71cSJoe PetscErrorCode PetscPDFPertubedConstant1D(const PetscReal x[], const PetscReal dummy[], PetscReal p[])
10938214e71cSJoe {
10948214e71cSJoe p[0] = (1. + 0.01 * PetscCosReal(0.5 * x[0])) / (2 * PETSC_PI);
10958214e71cSJoe return PETSC_SUCCESS;
10968214e71cSJoe }
10978214e71cSJoe
PetscPDFCosine1D(const PetscReal x[],const PetscReal scale[],PetscReal p[])10988214e71cSJoe PetscErrorCode PetscPDFCosine1D(const PetscReal x[], const PetscReal scale[], PetscReal p[])
10998214e71cSJoe {
11008214e71cSJoe const PetscReal alpha = scale ? scale[0] : 0.0;
11018214e71cSJoe const PetscReal k = scale ? scale[1] : 1.;
11028214e71cSJoe p[0] = (1 + alpha * PetscCosReal(k * x[0]));
11038214e71cSJoe return PETSC_SUCCESS;
11048214e71cSJoe }
11058214e71cSJoe
PetscPDFCosine2D(const PetscReal x[],const PetscReal scale[],PetscReal p[])11068214e71cSJoe PetscErrorCode PetscPDFCosine2D(const PetscReal x[], const PetscReal scale[], PetscReal p[])
11078214e71cSJoe {
11088214e71cSJoe const PetscReal alpha = scale ? scale[0] : 0.;
11098214e71cSJoe const PetscReal k = scale ? scale[0] : 1.;
11108214e71cSJoe p[0] = (1 + alpha * PetscCosReal(k * (x[0] + x[1])));
11118214e71cSJoe return PETSC_SUCCESS;
11128214e71cSJoe }
11138214e71cSJoe
CreateVelocityDM(DM sw,DM * vdm)111484467f86SMatthew G. Knepley static PetscErrorCode CreateVelocityDM(DM sw, DM *vdm)
11158214e71cSJoe {
1116f1e6e573SMatthew G. Knepley PetscFE fe;
1117f1e6e573SMatthew G. Knepley DMPolytopeType ct;
1118f1e6e573SMatthew G. Knepley PetscInt dim, cStart;
1119f1e6e573SMatthew G. Knepley const char *prefix = "v";
1120f1e6e573SMatthew G. Knepley
112184467f86SMatthew G. Knepley PetscFunctionBegin;
112284467f86SMatthew G. Knepley PetscCall(DMCreate(PETSC_COMM_SELF, vdm));
112384467f86SMatthew G. Knepley PetscCall(DMSetType(*vdm, DMPLEX));
1124f1e6e573SMatthew G. Knepley PetscCall(DMPlexSetOptionsPrefix(*vdm, prefix));
112584467f86SMatthew G. Knepley PetscCall(DMSetFromOptions(*vdm));
11269072cb8bSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)*vdm, "velocity"));
112784467f86SMatthew G. Knepley PetscCall(DMViewFromOptions(*vdm, NULL, "-dm_view"));
1128f1e6e573SMatthew G. Knepley
1129f1e6e573SMatthew G. Knepley PetscCall(DMGetDimension(*vdm, &dim));
1130f1e6e573SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(*vdm, 0, &cStart, NULL));
1131f1e6e573SMatthew G. Knepley PetscCall(DMPlexGetCellType(*vdm, cStart, &ct));
1132f1e6e573SMatthew G. Knepley PetscCall(PetscFECreateByCell(PETSC_COMM_SELF, dim, 1, ct, prefix, PETSC_DETERMINE, &fe));
1133f1e6e573SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)fe, "distribution"));
1134f1e6e573SMatthew G. Knepley PetscCall(DMSetField(*vdm, 0, NULL, (PetscObject)fe));
1135f1e6e573SMatthew G. Knepley PetscCall(DMCreateDS(*vdm));
1136f1e6e573SMatthew G. Knepley PetscCall(PetscFEDestroy(&fe));
113784467f86SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
11388214e71cSJoe }
11398214e71cSJoe
11409072cb8bSMatthew G. Knepley /*
11419072cb8bSMatthew G. Knepley InitializeParticles_Centroid - Initialize a regular grid of particles.
11429072cb8bSMatthew G. Knepley
11439072cb8bSMatthew G. Knepley Input Parameters:
11449072cb8bSMatthew G. Knepley + sw - The `DMSWARM`
11459072cb8bSMatthew G. Knepley - force1D - Treat the spatial domain as 1D
11469072cb8bSMatthew G. Knepley
11479072cb8bSMatthew G. Knepley Notes:
11489072cb8bSMatthew G. Knepley This functions sets the species, cellid, spatial coordinate, and velocity fields for all particles.
11499072cb8bSMatthew G. Knepley
11509072cb8bSMatthew G. Knepley It places one particle in the centroid of each cell in the implicit tensor product of the spatial
11519072cb8bSMatthew G. Knepley and velocity meshes.
11529072cb8bSMatthew G. Knepley */
InitializeParticles_Centroid(DM sw)1153045208b8SMatthew G. Knepley static PetscErrorCode InitializeParticles_Centroid(DM sw)
11548214e71cSJoe {
115584467f86SMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)sw->data;
11569072cb8bSMatthew G. Knepley DMSwarmCellDM celldm;
115784467f86SMatthew G. Knepley DM xdm, vdm;
115884467f86SMatthew G. Knepley PetscReal vmin[3], vmax[3];
115984467f86SMatthew G. Knepley PetscReal *x, *v;
116084467f86SMatthew G. Knepley PetscInt *species, *cellid;
116184467f86SMatthew G. Knepley PetscInt dim, xcStart, xcEnd, vcStart, vcEnd, Ns, Np, Npc, debug;
11628214e71cSJoe PetscBool flg;
116384467f86SMatthew G. Knepley MPI_Comm comm;
11649072cb8bSMatthew G. Knepley const char *cellidname;
11658214e71cSJoe
11668214e71cSJoe PetscFunctionBegin;
116784467f86SMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)sw, &comm));
116884467f86SMatthew G. Knepley
116984467f86SMatthew G. Knepley PetscOptionsBegin(comm, "", "DMSwarm Options", "DMSWARM");
11708214e71cSJoe PetscCall(DMSwarmGetNumSpecies(sw, &Ns));
11718214e71cSJoe PetscCall(PetscOptionsInt("-dm_swarm_num_species", "The number of species", "DMSwarmSetNumSpecies", Ns, &Ns, &flg));
11728214e71cSJoe if (flg) PetscCall(DMSwarmSetNumSpecies(sw, Ns));
117384467f86SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_swarm_print_coords", "Debug output level for particle coordinate computations", "InitializeParticles", 0, &swarm->printCoords, NULL, 0));
117484467f86SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_swarm_print_weights", "Debug output level for particle weight computations", "InitializeWeights", 0, &swarm->printWeights, NULL, 0));
11758214e71cSJoe PetscOptionsEnd();
117684467f86SMatthew G. Knepley debug = swarm->printCoords;
11778214e71cSJoe
11788214e71cSJoe PetscCall(DMGetDimension(sw, &dim));
117984467f86SMatthew G. Knepley PetscCall(DMSwarmGetCellDM(sw, &xdm));
118084467f86SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(xdm, 0, &xcStart, &xcEnd));
11818214e71cSJoe
1182045208b8SMatthew G. Knepley PetscCall(DMSwarmGetCellDMByName(sw, "velocity", &celldm));
1183045208b8SMatthew G. Knepley PetscCall(DMSwarmCellDMGetDM(celldm, &vdm));
118484467f86SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(vdm, 0, &vcStart, &vcEnd));
11858214e71cSJoe
118684467f86SMatthew G. Knepley // One particle per centroid on the tensor product grid
118784467f86SMatthew G. Knepley Npc = (vcEnd - vcStart) * Ns;
118884467f86SMatthew G. Knepley Np = (xcEnd - xcStart) * Npc;
11898214e71cSJoe PetscCall(DMSwarmSetLocalSizes(sw, Np, 0));
119084467f86SMatthew G. Knepley if (debug) {
1191fd7102fcSMatthew G. Knepley PetscInt gNp, gNc, Nc = xcEnd - xcStart;
119284467f86SMatthew G. Knepley PetscCallMPI(MPIU_Allreduce(&Np, &gNp, 1, MPIU_INT, MPIU_SUM, comm));
119384467f86SMatthew G. Knepley PetscCall(PetscPrintf(comm, "Global Np = %" PetscInt_FMT "\n", gNp));
1194fd7102fcSMatthew G. Knepley PetscCallMPI(MPIU_Allreduce(&Nc, &gNc, 1, MPIU_INT, MPIU_SUM, comm));
1195fd7102fcSMatthew G. Knepley PetscCall(PetscPrintf(comm, "Global X-cells = %" PetscInt_FMT "\n", gNc));
1196fd7102fcSMatthew G. Knepley PetscCall(PetscPrintf(comm, "Global V-cells = %" PetscInt_FMT "\n", vcEnd - vcStart));
11978214e71cSJoe }
11988214e71cSJoe
119984467f86SMatthew G. Knepley // Set species and cellid
12009072cb8bSMatthew G. Knepley PetscCall(DMSwarmGetCellDMActive(sw, &celldm));
12019072cb8bSMatthew G. Knepley PetscCall(DMSwarmCellDMGetCellID(celldm, &cellidname));
120284467f86SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "species", NULL, NULL, (void **)&species));
12039072cb8bSMatthew G. Knepley PetscCall(DMSwarmGetField(sw, cellidname, NULL, NULL, (void **)&cellid));
120484467f86SMatthew G. Knepley for (PetscInt c = 0, p = 0; c < xcEnd - xcStart; ++c) {
120584467f86SMatthew G. Knepley for (PetscInt s = 0; s < Ns; ++s) {
120684467f86SMatthew G. Knepley for (PetscInt q = 0; q < Npc / Ns; ++q, ++p) {
120784467f86SMatthew G. Knepley species[p] = s;
120884467f86SMatthew G. Knepley cellid[p] = c;
120984467f86SMatthew G. Knepley }
121084467f86SMatthew G. Knepley }
121184467f86SMatthew G. Knepley }
121284467f86SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "species", NULL, NULL, (void **)&species));
12139072cb8bSMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, cellidname, NULL, NULL, (void **)&cellid));
121484467f86SMatthew G. Knepley
121584467f86SMatthew G. Knepley // Set particle coordinates
12168214e71cSJoe PetscCall(DMSwarmGetField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&x));
12178214e71cSJoe PetscCall(DMSwarmGetField(sw, "velocity", NULL, NULL, (void **)&v));
12188214e71cSJoe PetscCall(DMSwarmSortGetAccess(sw));
121984467f86SMatthew G. Knepley PetscCall(DMGetBoundingBox(vdm, vmin, vmax));
122084467f86SMatthew G. Knepley PetscCall(DMGetCoordinatesLocalSetUp(xdm));
122184467f86SMatthew G. Knepley for (PetscInt c = 0; c < xcEnd - xcStart; ++c) {
122284467f86SMatthew G. Knepley const PetscInt cell = c + xcStart;
12238214e71cSJoe PetscInt *pidx, Npc;
12248214e71cSJoe PetscReal centroid[3], volume;
12258214e71cSJoe
12268214e71cSJoe PetscCall(DMSwarmSortGetPointsPerCell(sw, c, &Npc, &pidx));
122784467f86SMatthew G. Knepley PetscCall(DMPlexComputeCellGeometryFVM(xdm, cell, &volume, centroid, NULL));
122884467f86SMatthew G. Knepley for (PetscInt s = 0; s < Ns; ++s) {
122984467f86SMatthew G. Knepley for (PetscInt q = 0; q < Npc / Ns; ++q) {
123084467f86SMatthew G. Knepley const PetscInt p = pidx[q * Ns + s];
12318214e71cSJoe
123284467f86SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) {
12338214e71cSJoe x[p * dim + d] = centroid[d];
123484467f86SMatthew G. Knepley v[p * dim + d] = vmin[0] + (q + 0.5) * ((vmax[0] - vmin[0]) / (Npc / Ns));
12358214e71cSJoe }
12369072cb8bSMatthew G. Knepley if (debug > 1) {
12379072cb8bSMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, "Particle %4" PetscInt_FMT " ", p));
12389072cb8bSMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, " x: ("));
12399072cb8bSMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) {
12409072cb8bSMatthew G. Knepley if (d > 0) PetscCall(PetscPrintf(PETSC_COMM_SELF, ", "));
12419072cb8bSMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, "%g", x[p * dim + d]));
12429072cb8bSMatthew G. Knepley }
12439072cb8bSMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, ") v:("));
12449072cb8bSMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) {
12459072cb8bSMatthew G. Knepley if (d > 0) PetscCall(PetscPrintf(PETSC_COMM_SELF, ", "));
12469072cb8bSMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, "%g", v[p * dim + d]));
12479072cb8bSMatthew G. Knepley }
12489072cb8bSMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, ")\n"));
12499072cb8bSMatthew G. Knepley }
12508214e71cSJoe }
12518214e71cSJoe }
125284467f86SMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(sw, c, &Npc, &pidx));
12538214e71cSJoe }
12548214e71cSJoe PetscCall(DMSwarmSortRestoreAccess(sw));
12558214e71cSJoe PetscCall(DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&x));
12568214e71cSJoe PetscCall(DMSwarmRestoreField(sw, "velocity", NULL, NULL, (void **)&v));
125784467f86SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
125884467f86SMatthew G. Knepley }
125984467f86SMatthew G. Knepley
126084467f86SMatthew G. Knepley /*
126184467f86SMatthew G. Knepley InitializeWeights - Compute weight for each local particle
126284467f86SMatthew G. Knepley
126384467f86SMatthew G. Knepley Input Parameters:
126484467f86SMatthew G. Knepley + sw - The `DMSwarm`
126584467f86SMatthew G. Knepley . totalWeight - The sum of all particle weights
126684467f86SMatthew G. Knepley . func - The PDF for the particle spatial distribution
126784467f86SMatthew G. Knepley - param - The PDF parameters
126884467f86SMatthew G. Knepley
126984467f86SMatthew G. Knepley Notes:
127084467f86SMatthew G. Knepley The PDF for velocity is assumed to be a Gaussian
127184467f86SMatthew G. Knepley
127284467f86SMatthew G. Knepley The particle weights are returned in the `w_q` field of `sw`.
127384467f86SMatthew G. Knepley */
InitializeWeights(DM sw,PetscReal totalWeight,PetscProbFn * func,const PetscReal param[])1274f8662bd6SBarry Smith static PetscErrorCode InitializeWeights(DM sw, PetscReal totalWeight, PetscProbFn *func, const PetscReal param[])
127584467f86SMatthew G. Knepley {
127684467f86SMatthew G. Knepley DM xdm, vdm;
1277045208b8SMatthew G. Knepley DMSwarmCellDM celldm;
127884467f86SMatthew G. Knepley PetscScalar *weight;
127984467f86SMatthew G. Knepley PetscQuadrature xquad;
128084467f86SMatthew G. Knepley const PetscReal *xq, *xwq;
128184467f86SMatthew G. Knepley const PetscInt order = 5;
1282045208b8SMatthew G. Knepley PetscReal xi0[3];
128384467f86SMatthew G. Knepley PetscReal xwtot = 0., pwtot = 0.;
128484467f86SMatthew G. Knepley PetscInt xNq;
128584467f86SMatthew G. Knepley PetscInt dim, Ns, xcStart, xcEnd, vcStart, vcEnd, debug = ((DM_Swarm *)sw->data)->printWeights;
128684467f86SMatthew G. Knepley MPI_Comm comm;
128784467f86SMatthew G. Knepley PetscMPIInt rank;
128884467f86SMatthew G. Knepley
128984467f86SMatthew G. Knepley PetscFunctionBegin;
129084467f86SMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)sw, &comm));
129184467f86SMatthew G. Knepley PetscCallMPI(MPI_Comm_rank(comm, &rank));
129284467f86SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim));
129384467f86SMatthew G. Knepley PetscCall(DMSwarmGetCellDM(sw, &xdm));
129484467f86SMatthew G. Knepley PetscCall(DMSwarmGetNumSpecies(sw, &Ns));
129584467f86SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(xdm, 0, &xcStart, &xcEnd));
1296045208b8SMatthew G. Knepley PetscCall(DMSwarmGetCellDMByName(sw, "velocity", &celldm));
1297045208b8SMatthew G. Knepley PetscCall(DMSwarmCellDMGetDM(celldm, &vdm));
129884467f86SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(vdm, 0, &vcStart, &vcEnd));
129984467f86SMatthew G. Knepley
130084467f86SMatthew G. Knepley // Setup Quadrature for spatial and velocity weight calculations
1301045208b8SMatthew G. Knepley PetscCall(PetscDTGaussTensorQuadrature(dim, 1, order, -1.0, 1.0, &xquad));
130284467f86SMatthew G. Knepley PetscCall(PetscQuadratureGetData(xquad, NULL, NULL, &xNq, &xq, &xwq));
130384467f86SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) xi0[d] = -1.0;
130484467f86SMatthew G. Knepley
130584467f86SMatthew G. Knepley // Integrate the density function to get the weights of particles in each cell
130684467f86SMatthew G. Knepley PetscCall(DMGetCoordinatesLocalSetUp(vdm));
130784467f86SMatthew G. Knepley PetscCall(DMSwarmSortGetAccess(sw));
130884467f86SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "w_q", NULL, NULL, (void **)&weight));
130984467f86SMatthew G. Knepley for (PetscInt c = xcStart; c < xcEnd; ++c) {
131084467f86SMatthew G. Knepley PetscReal xv0[3], xJ[9], xinvJ[9], xdetJ, xqr[3], xden, xw = 0.;
131184467f86SMatthew G. Knepley PetscInt *pidx, Npc;
131284467f86SMatthew G. Knepley PetscInt xNc;
131384467f86SMatthew G. Knepley const PetscScalar *xarray;
131484467f86SMatthew G. Knepley PetscScalar *xcoords = NULL;
131584467f86SMatthew G. Knepley PetscBool xisDG;
131684467f86SMatthew G. Knepley
131784467f86SMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(xdm, c, &xisDG, &xNc, &xarray, &xcoords));
131884467f86SMatthew G. Knepley PetscCall(DMSwarmSortGetPointsPerCell(sw, c, &Npc, &pidx));
131984467f86SMatthew G. Knepley PetscCheck(Npc == (vcEnd - vcStart) * Ns, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of particles %" PetscInt_FMT " in cell (rank %d) != %" PetscInt_FMT " number of velocity vertices", Npc, rank, (vcEnd - vcStart) * Ns);
132084467f86SMatthew G. Knepley PetscCall(DMPlexComputeCellGeometryFEM(xdm, c, NULL, xv0, xJ, xinvJ, &xdetJ));
132184467f86SMatthew G. Knepley for (PetscInt q = 0; q < xNq; ++q) {
132284467f86SMatthew G. Knepley // Transform quadrature points from ref space to real space
1323045208b8SMatthew G. Knepley CoordinatesRefToReal(dim, dim, xi0, xv0, xJ, &xq[q * dim], xqr);
132484467f86SMatthew G. Knepley // Get probability density at quad point
132584467f86SMatthew G. Knepley // No need to scale xqr since PDF will be periodic
132684467f86SMatthew G. Knepley PetscCall((*func)(xqr, param, &xden));
132784467f86SMatthew G. Knepley xw += xden * (xwq[q] * xdetJ);
132884467f86SMatthew G. Knepley }
132984467f86SMatthew G. Knepley xwtot += xw;
133084467f86SMatthew G. Knepley if (debug) {
133184467f86SMatthew G. Knepley IS globalOrdering;
133284467f86SMatthew G. Knepley const PetscInt *ordering;
133384467f86SMatthew G. Knepley
133484467f86SMatthew G. Knepley PetscCall(DMPlexGetCellNumbering(xdm, &globalOrdering));
133584467f86SMatthew G. Knepley PetscCall(ISGetIndices(globalOrdering, &ordering));
133675155f48SMatthew G. Knepley PetscCall(PetscSynchronizedPrintf(comm, "c:%" PetscInt_FMT " [x_a,x_b] = %1.15f,%1.15f -> cell weight = %1.15f\n", ordering[c], (double)PetscRealPart(xcoords[0]), (double)PetscRealPart(xcoords[0 + dim]), (double)xw));
133784467f86SMatthew G. Knepley PetscCall(ISRestoreIndices(globalOrdering, &ordering));
133884467f86SMatthew G. Knepley }
133984467f86SMatthew G. Knepley // Set weights to be Gaussian in velocity cells
134084467f86SMatthew G. Knepley for (PetscInt vc = vcStart; vc < vcEnd; ++vc) {
134184467f86SMatthew G. Knepley const PetscInt p = pidx[vc * Ns + 0];
134284467f86SMatthew G. Knepley PetscReal vw = 0.;
134384467f86SMatthew G. Knepley PetscInt vNc;
134484467f86SMatthew G. Knepley const PetscScalar *varray;
134584467f86SMatthew G. Knepley PetscScalar *vcoords = NULL;
134684467f86SMatthew G. Knepley PetscBool visDG;
134784467f86SMatthew G. Knepley
134884467f86SMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(vdm, vc, &visDG, &vNc, &varray, &vcoords));
134984467f86SMatthew G. Knepley // TODO: Fix 2 stream Ask Joe
135084467f86SMatthew G. Knepley // Two stream function from 1/2pi v^2 e^(-v^2/2)
135184467f86SMatthew G. Knepley // vw = 1. / (PetscSqrtReal(2 * PETSC_PI)) * (((coords_v[0] * PetscExpReal(-PetscSqr(coords_v[0]) / 2.)) - (coords_v[1] * PetscExpReal(-PetscSqr(coords_v[1]) / 2.)))) - 0.5 * PetscErfReal(coords_v[0] / PetscSqrtReal(2.)) + 0.5 * (PetscErfReal(coords_v[1] / PetscSqrtReal(2.)));
135284467f86SMatthew G. Knepley vw = 0.5 * (PetscErfReal(vcoords[1] / PetscSqrtReal(2.)) - PetscErfReal(vcoords[0] / PetscSqrtReal(2.)));
135384467f86SMatthew G. Knepley
135484467f86SMatthew G. Knepley weight[p] = totalWeight * vw * xw;
135584467f86SMatthew G. Knepley pwtot += weight[p];
1356bfe80ac4SPierre Jolivet PetscCheck(weight[p] <= 10., PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Particle %" PetscInt_FMT " weight exceeded 1: %g, %g, %g", p, xw, vw, totalWeight);
135784467f86SMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(vdm, vc, &visDG, &vNc, &varray, &vcoords));
135884467f86SMatthew G. Knepley if (debug > 1) PetscCall(PetscPrintf(comm, "particle %" PetscInt_FMT ": %g, vw: %g xw: %g\n", p, weight[p], vw, xw));
135984467f86SMatthew G. Knepley }
136084467f86SMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(xdm, c, &xisDG, &xNc, &xarray, &xcoords));
136184467f86SMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(sw, c, &Npc, &pidx));
136284467f86SMatthew G. Knepley }
136384467f86SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "w_q", NULL, NULL, (void **)&weight));
136484467f86SMatthew G. Knepley PetscCall(DMSwarmSortRestoreAccess(sw));
136584467f86SMatthew G. Knepley PetscCall(PetscQuadratureDestroy(&xquad));
136684467f86SMatthew G. Knepley
136784467f86SMatthew G. Knepley if (debug) {
136884467f86SMatthew G. Knepley PetscReal wtot[2] = {pwtot, xwtot}, gwtot[2];
136984467f86SMatthew G. Knepley
137084467f86SMatthew G. Knepley PetscCall(PetscSynchronizedFlush(comm, NULL));
137184467f86SMatthew G. Knepley PetscCallMPI(MPIU_Allreduce(wtot, gwtot, 2, MPIU_REAL, MPIU_SUM, PETSC_COMM_WORLD));
137284467f86SMatthew G. Knepley PetscCall(PetscPrintf(comm, "particle weight sum = %1.10f cell weight sum = %1.10f\n", (double)gwtot[0], (double)gwtot[1]));
137384467f86SMatthew G. Knepley }
137484467f86SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
137584467f86SMatthew G. Knepley }
137684467f86SMatthew G. Knepley
InitializeParticles_PerturbedWeights(DM sw,AppCtx * ctx)1377*2a8381b2SBarry Smith static PetscErrorCode InitializeParticles_PerturbedWeights(DM sw, AppCtx *ctx)
137884467f86SMatthew G. Knepley {
1379*2a8381b2SBarry Smith PetscReal scale[2] = {ctx->cosine_coefficients[0], ctx->cosine_coefficients[1]};
138075155f48SMatthew G. Knepley PetscInt dim;
138184467f86SMatthew G. Knepley
138284467f86SMatthew G. Knepley PetscFunctionBegin;
138375155f48SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim));
1384045208b8SMatthew G. Knepley PetscCall(InitializeParticles_Centroid(sw));
1385*2a8381b2SBarry Smith PetscCall(InitializeWeights(sw, ctx->totalWeight, dim == 1 ? PetscPDFCosine1D : PetscPDFCosine2D, scale));
13868214e71cSJoe PetscFunctionReturn(PETSC_SUCCESS);
13878214e71cSJoe }
13888214e71cSJoe
InitializeConstants(DM sw,AppCtx * ctx)1389*2a8381b2SBarry Smith static PetscErrorCode InitializeConstants(DM sw, AppCtx *ctx)
13908214e71cSJoe {
13918214e71cSJoe DM dm;
13928214e71cSJoe PetscInt *species;
13938214e71cSJoe PetscReal *weight, totalCharge = 0., totalWeight = 0., gmin[3], gmax[3], global_charge, global_weight;
13948214e71cSJoe PetscInt Np, dim;
13958214e71cSJoe
13968214e71cSJoe PetscFunctionBegin;
13978214e71cSJoe PetscCall(DMSwarmGetCellDM(sw, &dm));
13988214e71cSJoe PetscCall(DMGetDimension(sw, &dim));
13998214e71cSJoe PetscCall(DMSwarmGetLocalSize(sw, &Np));
14008214e71cSJoe PetscCall(DMGetBoundingBox(dm, gmin, gmax));
14018214e71cSJoe PetscCall(DMSwarmGetField(sw, "w_q", NULL, NULL, (void **)&weight));
14028214e71cSJoe PetscCall(DMSwarmGetField(sw, "species", NULL, NULL, (void **)&species));
14038214e71cSJoe for (PetscInt p = 0; p < Np; ++p) {
14048214e71cSJoe totalWeight += weight[p];
1405*2a8381b2SBarry Smith totalCharge += ctx->charges[species[p]] * weight[p];
14068214e71cSJoe }
14078214e71cSJoe PetscCall(DMSwarmRestoreField(sw, "w_q", NULL, NULL, (void **)&weight));
14088214e71cSJoe PetscCall(DMSwarmRestoreField(sw, "species", NULL, NULL, (void **)&species));
14098214e71cSJoe {
14108214e71cSJoe Parameter *param;
14118214e71cSJoe PetscReal Area;
14128214e71cSJoe
1413*2a8381b2SBarry Smith PetscCall(PetscBagGetData(ctx->bag, ¶m));
14148214e71cSJoe switch (dim) {
14158214e71cSJoe case 1:
14168214e71cSJoe Area = (gmax[0] - gmin[0]);
14178214e71cSJoe break;
14188214e71cSJoe case 2:
14198214e71cSJoe Area = (gmax[0] - gmin[0]) * (gmax[1] - gmin[1]);
14208214e71cSJoe break;
14218214e71cSJoe case 3:
14228214e71cSJoe Area = (gmax[0] - gmin[0]) * (gmax[1] - gmin[1]) * (gmax[2] - gmin[2]);
14238214e71cSJoe break;
14248214e71cSJoe default:
14258214e71cSJoe SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Dimension %" PetscInt_FMT " not supported", dim);
14268214e71cSJoe }
1427462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&totalWeight, &global_weight, 1, MPIU_REAL, MPIU_SUM, PETSC_COMM_WORLD));
1428462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&totalCharge, &global_charge, 1, MPIU_REAL, MPIU_SUM, PETSC_COMM_WORLD));
1429*2a8381b2SBarry Smith PetscCall(PetscPrintf(PETSC_COMM_WORLD, "dim = %" PetscInt_FMT "\ttotalWeight = %f, ctx->charges[species[0]] = %f\ttotalCharge = %f, Total Area = %f\n", dim, (double)global_weight, (double)ctx->charges[0], (double)global_charge, (double)Area));
14308214e71cSJoe param->sigma = PetscAbsReal(global_charge / (Area));
14318214e71cSJoe
14328214e71cSJoe PetscCall(PetscPrintf(PETSC_COMM_WORLD, "sigma: %g\n", (double)param->sigma));
14338214e71cSJoe PetscCall(PetscPrintf(PETSC_COMM_WORLD, "(x0,v0,t0,m0,q0,phi0): (%e, %e, %e, %e, %e, %e) - (P, V) = (%e, %e)\n", (double)param->x0, (double)param->v0, (double)param->t0, (double)param->m0, (double)param->q0, (double)param->phi0, (double)param->poissonNumber,
14348214e71cSJoe (double)param->vlasovNumber));
14358214e71cSJoe }
14368214e71cSJoe /* Setup Constants */
14378214e71cSJoe {
14388214e71cSJoe PetscDS ds;
14398214e71cSJoe Parameter *param;
1440*2a8381b2SBarry Smith PetscCall(PetscBagGetData(ctx->bag, ¶m));
14418214e71cSJoe PetscScalar constants[NUM_CONSTANTS];
14428214e71cSJoe constants[SIGMA] = param->sigma;
14438214e71cSJoe constants[V0] = param->v0;
14448214e71cSJoe constants[T0] = param->t0;
14458214e71cSJoe constants[X0] = param->x0;
14468214e71cSJoe constants[M0] = param->m0;
14478214e71cSJoe constants[Q0] = param->q0;
14488214e71cSJoe constants[PHI0] = param->phi0;
14498214e71cSJoe constants[POISSON] = param->poissonNumber;
14508214e71cSJoe constants[VLASOV] = param->vlasovNumber;
14518214e71cSJoe PetscCall(DMGetDS(dm, &ds));
14528214e71cSJoe PetscCall(PetscDSSetConstants(ds, NUM_CONSTANTS, constants));
14538214e71cSJoe }
14548214e71cSJoe PetscFunctionReturn(PETSC_SUCCESS);
14558214e71cSJoe }
14568214e71cSJoe
CreateSwarm(DM dm,AppCtx * ctx,DM * sw)1457*2a8381b2SBarry Smith static PetscErrorCode CreateSwarm(DM dm, AppCtx *ctx, DM *sw)
14588214e71cSJoe {
14599072cb8bSMatthew G. Knepley DMSwarmCellDM celldm;
14609072cb8bSMatthew G. Knepley DM vdm;
14618214e71cSJoe PetscReal v0[2] = {1., 0.};
14628214e71cSJoe PetscInt dim;
1463b80bf5b1SJoe Pusztay
1464b80bf5b1SJoe Pusztay PetscFunctionBeginUser;
14659566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
14669566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), sw));
14679566063dSJacob Faibussowitsch PetscCall(DMSetType(*sw, DMSWARM));
14689566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*sw, dim));
14699566063dSJacob Faibussowitsch PetscCall(DMSwarmSetType(*sw, DMSWARM_PIC));
1470*2a8381b2SBarry Smith PetscCall(DMSetApplicationContext(*sw, ctx));
14719072cb8bSMatthew G. Knepley
14729566063dSJacob Faibussowitsch PetscCall(DMSwarmRegisterPetscDatatypeField(*sw, "w_q", 1, PETSC_SCALAR));
14738214e71cSJoe PetscCall(DMSwarmRegisterPetscDatatypeField(*sw, "velocity", dim, PETSC_REAL));
14748214e71cSJoe PetscCall(DMSwarmRegisterPetscDatatypeField(*sw, "species", 1, PETSC_INT));
14758214e71cSJoe PetscCall(DMSwarmRegisterPetscDatatypeField(*sw, "E_field", dim, PETSC_REAL));
14769072cb8bSMatthew G. Knepley
14779072cb8bSMatthew G. Knepley const char *fieldnames[2] = {DMSwarmPICField_coor, "velocity"};
14789072cb8bSMatthew G. Knepley
14799072cb8bSMatthew G. Knepley PetscCall(DMSwarmCellDMCreate(dm, 2, fieldnames, 1, fieldnames, &celldm));
14809072cb8bSMatthew G. Knepley PetscCall(DMSwarmAddCellDM(*sw, celldm));
14819072cb8bSMatthew G. Knepley PetscCall(DMSwarmCellDMDestroy(&celldm));
14829072cb8bSMatthew G. Knepley
14839072cb8bSMatthew G. Knepley const char *vfieldnames[1] = {"w_q"};
14849072cb8bSMatthew G. Knepley
14859072cb8bSMatthew G. Knepley PetscCall(CreateVelocityDM(*sw, &vdm));
14869072cb8bSMatthew G. Knepley PetscCall(DMSwarmCellDMCreate(vdm, 1, vfieldnames, 1, &fieldnames[1], &celldm));
14879072cb8bSMatthew G. Knepley PetscCall(DMSwarmAddCellDM(*sw, celldm));
14889072cb8bSMatthew G. Knepley PetscCall(DMSwarmCellDMDestroy(&celldm));
14899072cb8bSMatthew G. Knepley PetscCall(DMDestroy(&vdm));
14909072cb8bSMatthew G. Knepley
14914a0cbf56SMatthew G. Knepley DM mdm;
14924a0cbf56SMatthew G. Knepley
14934a0cbf56SMatthew G. Knepley PetscCall(DMClone(dm, &mdm));
14944a0cbf56SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)mdm, "moments"));
14954a0cbf56SMatthew G. Knepley PetscCall(DMCopyDisc(dm, mdm));
14964a0cbf56SMatthew G. Knepley PetscCall(DMSwarmCellDMCreate(mdm, 1, vfieldnames, 1, fieldnames, &celldm));
14974a0cbf56SMatthew G. Knepley PetscCall(DMDestroy(&mdm));
14984a0cbf56SMatthew G. Knepley PetscCall(DMSwarmAddCellDM(*sw, celldm));
14994a0cbf56SMatthew G. Knepley PetscCall(DMSwarmCellDMDestroy(&celldm));
15004a0cbf56SMatthew G. Knepley
15019566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(*sw));
1502045208b8SMatthew G. Knepley PetscCall(DMSetUp(*sw));
1503045208b8SMatthew G. Knepley
15049072cb8bSMatthew G. Knepley PetscCall(DMSwarmSetCellDMActive(*sw, "space"));
1505*2a8381b2SBarry Smith ctx->swarm = *sw;
1506045208b8SMatthew G. Knepley // TODO: This is redundant init since it is done in InitializeSolveAndSwarm, however DMSetUp() requires the local size be set
1507*2a8381b2SBarry Smith if (ctx->perturbed_weights) {
1508*2a8381b2SBarry Smith PetscCall(InitializeParticles_PerturbedWeights(*sw, ctx));
1509b80bf5b1SJoe Pusztay } else {
15108214e71cSJoe PetscCall(DMSwarmComputeLocalSizeFromOptions(*sw));
15118214e71cSJoe PetscCall(DMSwarmInitializeCoordinates(*sw));
15128214e71cSJoe PetscCall(DMSwarmInitializeVelocitiesFromOptions(*sw, v0));
1513b80bf5b1SJoe Pusztay }
15149566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*sw, "Particles"));
15159566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(*sw, NULL, "-sw_view"));
15163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1517b80bf5b1SJoe Pusztay }
1518b80bf5b1SJoe Pusztay
ComputeFieldAtParticles_Coulomb(SNES snes,DM sw,PetscReal E[])15198214e71cSJoe static PetscErrorCode ComputeFieldAtParticles_Coulomb(SNES snes, DM sw, PetscReal E[])
1520d71ae5a4SJacob Faibussowitsch {
1521*2a8381b2SBarry Smith AppCtx *ctx;
15228214e71cSJoe PetscReal *coords;
15238214e71cSJoe PetscInt *species, dim, Np, Ns;
15248214e71cSJoe PetscMPIInt size;
15258214e71cSJoe
15268214e71cSJoe PetscFunctionBegin;
15278214e71cSJoe PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)snes), &size));
15288214e71cSJoe PetscCheck(size == 1, PetscObjectComm((PetscObject)snes), PETSC_ERR_SUP, "Coulomb code only works in serial");
15298214e71cSJoe PetscCall(DMGetDimension(sw, &dim));
15308214e71cSJoe PetscCall(DMSwarmGetLocalSize(sw, &Np));
15318214e71cSJoe PetscCall(DMSwarmGetNumSpecies(sw, &Ns));
1532*2a8381b2SBarry Smith PetscCall(DMGetApplicationContext(sw, &ctx));
15338214e71cSJoe
15348214e71cSJoe PetscCall(DMSwarmGetField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
15358214e71cSJoe PetscCall(DMSwarmGetField(sw, "species", NULL, NULL, (void **)&species));
15368214e71cSJoe for (PetscInt p = 0; p < Np; ++p) {
15378214e71cSJoe PetscReal *pcoord = &coords[p * dim];
15388214e71cSJoe PetscReal pE[3] = {0., 0., 0.};
15398214e71cSJoe
15408214e71cSJoe /* Calculate field at particle p due to particle q */
15418214e71cSJoe for (PetscInt q = 0; q < Np; ++q) {
15428214e71cSJoe PetscReal *qcoord = &coords[q * dim];
15438214e71cSJoe PetscReal rpq[3], r, r3, q_q;
15448214e71cSJoe
15458214e71cSJoe if (p == q) continue;
1546*2a8381b2SBarry Smith q_q = ctx->charges[species[q]] * 1.;
15478214e71cSJoe for (PetscInt d = 0; d < dim; ++d) rpq[d] = pcoord[d] - qcoord[d];
15488214e71cSJoe r = DMPlex_NormD_Internal(dim, rpq);
15498214e71cSJoe if (r < PETSC_SQRT_MACHINE_EPSILON) continue;
15508214e71cSJoe r3 = PetscPowRealInt(r, 3);
15518214e71cSJoe for (PetscInt d = 0; d < dim; ++d) pE[d] += q_q * rpq[d] / r3;
15528214e71cSJoe }
15538214e71cSJoe for (PetscInt d = 0; d < dim; ++d) E[p * dim + d] = pE[d];
15548214e71cSJoe }
15558214e71cSJoe PetscCall(DMSwarmRestoreField(sw, "species", NULL, NULL, (void **)&species));
15568214e71cSJoe PetscCall(DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
15578214e71cSJoe PetscFunctionReturn(PETSC_SUCCESS);
15588214e71cSJoe }
15598214e71cSJoe
ComputeFieldAtParticles_Primal(SNES snes,DM sw,Mat M_p,PetscReal E[])15604a0cbf56SMatthew G. Knepley static PetscErrorCode ComputeFieldAtParticles_Primal(SNES snes, DM sw, Mat M_p, PetscReal E[])
15618214e71cSJoe {
1562b80bf5b1SJoe Pusztay DM dm;
1563*2a8381b2SBarry Smith AppCtx *ctx;
15648214e71cSJoe PetscDS ds;
15658214e71cSJoe PetscFE fe;
15664a0cbf56SMatthew G. Knepley KSP ksp;
156775155f48SMatthew G. Knepley Vec rhoRhs; // Weak charge density, \int phi_i rho
156875155f48SMatthew G. Knepley Vec rho; // Charge density, M^{-1} rhoRhs
156975155f48SMatthew G. Knepley Vec phi, locPhi; // Potential
157075155f48SMatthew G. Knepley Vec f; // Particle weights
15718214e71cSJoe PetscReal *coords;
15728214e71cSJoe PetscInt dim, cStart, cEnd, Np;
15738214e71cSJoe
15748214e71cSJoe PetscFunctionBegin;
1575*2a8381b2SBarry Smith PetscCall(DMGetApplicationContext(sw, &ctx));
1576*2a8381b2SBarry Smith PetscCall(PetscLogEventBegin(ctx->ESolveEvent, snes, sw, 0, 0));
15778214e71cSJoe PetscCall(DMGetDimension(sw, &dim));
15788214e71cSJoe PetscCall(DMSwarmGetLocalSize(sw, &Np));
15798214e71cSJoe
15808214e71cSJoe PetscCall(SNESGetDM(snes, &dm));
158175155f48SMatthew G. Knepley PetscCall(DMGetGlobalVector(dm, &rhoRhs));
158275155f48SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)rhoRhs, "Weak charge density"));
1583*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmPot, "rho", &rho));
15848214e71cSJoe PetscCall(DMSwarmCreateGlobalVectorFromField(sw, "w_q", &f));
15858214e71cSJoe PetscCall(PetscObjectSetName((PetscObject)f, "particle weight"));
158675155f48SMatthew G. Knepley
15878214e71cSJoe PetscCall(MatViewFromOptions(M_p, NULL, "-mp_view"));
1588*2a8381b2SBarry Smith PetscCall(MatViewFromOptions(ctx->M, NULL, "-m_view"));
15898214e71cSJoe PetscCall(VecViewFromOptions(f, NULL, "-weights_view"));
159075155f48SMatthew G. Knepley
159175155f48SMatthew G. Knepley PetscCall(MatMultTranspose(M_p, f, rhoRhs));
15928214e71cSJoe PetscCall(DMSwarmDestroyGlobalVectorFromField(sw, "w_q", &f));
15938214e71cSJoe
1594fd7102fcSMatthew G. Knepley // Low-pass filter rhoRhs
1595fd7102fcSMatthew G. Knepley PetscInt window = 0;
1596fd7102fcSMatthew G. Knepley PetscCall(PetscOptionsGetInt(NULL, NULL, "-rho_average", &window, NULL));
1597fd7102fcSMatthew G. Knepley if (window) {
1598fd7102fcSMatthew G. Knepley PetscScalar *a;
1599fd7102fcSMatthew G. Knepley PetscInt n;
1600fd7102fcSMatthew G. Knepley PetscReal width = 2. * window + 1.;
1601fd7102fcSMatthew G. Knepley
1602fd7102fcSMatthew G. Knepley // This will only work for P_1
1603fd7102fcSMatthew G. Knepley // This works because integration against a test function is linear
1604fd7102fcSMatthew G. Knepley // This only works in serial since I need the periodic values (maybe use FFT)
1605fd7102fcSMatthew G. Knepley // Do a real integral against weight function for higher order
1606fd7102fcSMatthew G. Knepley PetscCall(VecGetLocalSize(rhoRhs, &n));
1607fd7102fcSMatthew G. Knepley PetscCall(VecGetArrayWrite(rhoRhs, &a));
1608fd7102fcSMatthew G. Knepley for (PetscInt i = 0; i < n; ++i) {
1609fd7102fcSMatthew G. Knepley PetscScalar avg = a[i];
1610fd7102fcSMatthew G. Knepley for (PetscInt j = 1; j <= window; ++j) avg += a[(i - j + n) % n] + a[(i + j) % n];
1611fd7102fcSMatthew G. Knepley a[i] = avg / width;
1612fd7102fcSMatthew G. Knepley //a[i] = (a[(i - 1 + n) % n] + a[i] + a[(i + 1) % n]) / 3.;
1613fd7102fcSMatthew G. Knepley }
1614fd7102fcSMatthew G. Knepley PetscCall(VecRestoreArrayWrite(rhoRhs, &a));
1615fd7102fcSMatthew G. Knepley }
1616fd7102fcSMatthew G. Knepley
16178214e71cSJoe PetscCall(KSPCreate(PetscObjectComm((PetscObject)dm), &ksp));
16188214e71cSJoe PetscCall(KSPSetOptionsPrefix(ksp, "em_proj_"));
1619*2a8381b2SBarry Smith PetscCall(KSPSetOperators(ksp, ctx->M, ctx->M));
16208214e71cSJoe PetscCall(KSPSetFromOptions(ksp));
162175155f48SMatthew G. Knepley PetscCall(KSPSolve(ksp, rhoRhs, rho));
16228214e71cSJoe
162375155f48SMatthew G. Knepley PetscCall(VecScale(rhoRhs, -1.0));
16248214e71cSJoe
162575155f48SMatthew G. Knepley PetscCall(VecViewFromOptions(rhoRhs, NULL, "-rho_view"));
1626*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmPot, "rho", &rho));
16278214e71cSJoe PetscCall(KSPDestroy(&ksp));
16288214e71cSJoe
1629*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmPot, "phi", &phi));
16308214e71cSJoe PetscCall(VecSet(phi, 0.0));
163175155f48SMatthew G. Knepley PetscCall(SNESSolve(snes, rhoRhs, phi));
163275155f48SMatthew G. Knepley PetscCall(DMRestoreGlobalVector(dm, &rhoRhs));
16338214e71cSJoe PetscCall(VecViewFromOptions(phi, NULL, "-phi_view"));
16348214e71cSJoe
16358214e71cSJoe PetscCall(DMGetLocalVector(dm, &locPhi));
16368214e71cSJoe PetscCall(DMGlobalToLocalBegin(dm, phi, INSERT_VALUES, locPhi));
16378214e71cSJoe PetscCall(DMGlobalToLocalEnd(dm, phi, INSERT_VALUES, locPhi));
1638*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmPot, "phi", &phi));
1639*2a8381b2SBarry Smith PetscCall(PetscLogEventEnd(ctx->ESolveEvent, snes, sw, 0, 0));
16408214e71cSJoe
16418214e71cSJoe PetscCall(DMGetDS(dm, &ds));
16428214e71cSJoe PetscCall(PetscDSGetDiscretization(ds, 0, (PetscObject *)&fe));
16438214e71cSJoe PetscCall(DMSwarmSortGetAccess(sw));
16448214e71cSJoe PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
16458214e71cSJoe PetscCall(DMSwarmGetField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
16468214e71cSJoe
1647*2a8381b2SBarry Smith PetscCall(PetscLogEventBegin(ctx->ETabEvent, snes, sw, 0, 0));
16488214e71cSJoe PetscTabulation tab;
16498214e71cSJoe PetscReal *pcoord, *refcoord;
1650045208b8SMatthew G. Knepley PetscFEGeom *chunkgeom = NULL;
1651045208b8SMatthew G. Knepley PetscInt maxNcp = 0;
1652045208b8SMatthew G. Knepley
1653045208b8SMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) {
1654045208b8SMatthew G. Knepley PetscInt Ncp;
1655045208b8SMatthew G. Knepley
1656045208b8SMatthew G. Knepley PetscCall(DMSwarmSortGetNumberOfPointsPerCell(sw, c, &Ncp));
1657045208b8SMatthew G. Knepley maxNcp = PetscMax(maxNcp, Ncp);
1658045208b8SMatthew G. Knepley }
1659045208b8SMatthew G. Knepley PetscCall(DMGetWorkArray(dm, maxNcp * dim, MPIU_REAL, &refcoord));
1660045208b8SMatthew G. Knepley PetscCall(DMGetWorkArray(dm, maxNcp * dim, MPIU_REAL, &pcoord));
1661045208b8SMatthew G. Knepley PetscCall(PetscFECreateTabulation(fe, 1, maxNcp, refcoord, 1, &tab));
1662045208b8SMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) {
1663045208b8SMatthew G. Knepley PetscScalar *clPhi = NULL;
16648214e71cSJoe PetscInt *points;
16658214e71cSJoe PetscInt Ncp;
16668214e71cSJoe
16678214e71cSJoe PetscCall(DMSwarmSortGetPointsPerCell(sw, c, &Ncp, &points));
16688214e71cSJoe for (PetscInt cp = 0; cp < Ncp; ++cp)
16698214e71cSJoe for (PetscInt d = 0; d < dim; ++d) pcoord[cp * dim + d] = coords[points[cp] * dim + d];
1670f1e6e573SMatthew G. Knepley {
1671*2a8381b2SBarry Smith PetscCall(PetscFEGeomGetChunk(ctx->fegeom, c - cStart, c - cStart + 1, &chunkgeom));
1672f1e6e573SMatthew G. Knepley for (PetscInt i = 0; i < Ncp; ++i) {
1673f1e6e573SMatthew G. Knepley const PetscReal x0[3] = {-1., -1., -1.};
1674f1e6e573SMatthew G. Knepley CoordinatesRealToRef(dim, dim, x0, chunkgeom->v, chunkgeom->invJ, &pcoord[dim * i], &refcoord[dim * i]);
1675f1e6e573SMatthew G. Knepley }
1676f1e6e573SMatthew G. Knepley }
1677045208b8SMatthew G. Knepley PetscCall(PetscFEComputeTabulation(fe, Ncp, refcoord, 1, tab));
16788214e71cSJoe PetscCall(DMPlexVecGetClosure(dm, NULL, locPhi, c, NULL, &clPhi));
16798214e71cSJoe for (PetscInt cp = 0; cp < Ncp; ++cp) {
16808214e71cSJoe const PetscReal *basisDer = tab->T[1];
16818214e71cSJoe const PetscInt p = points[cp];
16828214e71cSJoe
16838214e71cSJoe for (PetscInt d = 0; d < dim; ++d) E[p * dim + d] = 0.;
1684f1e6e573SMatthew G. Knepley PetscCall(PetscFEFreeInterpolateGradient_Static(fe, basisDer, clPhi, dim, chunkgeom->invJ, NULL, cp, &E[p * dim]));
1685045208b8SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) E[p * dim + d] *= -1.0;
16868214e71cSJoe }
16878214e71cSJoe PetscCall(DMPlexVecRestoreClosure(dm, NULL, locPhi, c, NULL, &clPhi));
168884467f86SMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(sw, c, &Ncp, &points));
16898214e71cSJoe }
1690045208b8SMatthew G. Knepley PetscCall(DMRestoreWorkArray(dm, maxNcp * dim, MPIU_REAL, &pcoord));
1691045208b8SMatthew G. Knepley PetscCall(DMRestoreWorkArray(dm, maxNcp * dim, MPIU_REAL, &refcoord));
1692045208b8SMatthew G. Knepley PetscCall(PetscTabulationDestroy(&tab));
16938214e71cSJoe PetscCall(DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
16948214e71cSJoe PetscCall(DMSwarmSortRestoreAccess(sw));
16958214e71cSJoe PetscCall(DMRestoreLocalVector(dm, &locPhi));
1696*2a8381b2SBarry Smith PetscCall(PetscFEGeomRestoreChunk(ctx->fegeom, 0, 1, &chunkgeom));
1697*2a8381b2SBarry Smith PetscCall(PetscLogEventEnd(ctx->ETabEvent, snes, sw, 0, 0));
16988214e71cSJoe PetscFunctionReturn(PETSC_SUCCESS);
16998214e71cSJoe }
17008214e71cSJoe
ComputeFieldAtParticles_Mixed(SNES snes,DM sw,Mat M_p,PetscReal E[])17014a0cbf56SMatthew G. Knepley static PetscErrorCode ComputeFieldAtParticles_Mixed(SNES snes, DM sw, Mat M_p, PetscReal E[])
17028214e71cSJoe {
17034a0cbf56SMatthew G. Knepley DM dm;
1704*2a8381b2SBarry Smith AppCtx *ctx;
17058214e71cSJoe PetscDS ds;
17068214e71cSJoe PetscFE fe;
17074a0cbf56SMatthew G. Knepley KSP ksp;
17084a0cbf56SMatthew G. Knepley Vec rhoRhs, rhoRhsFull; // Weak charge density, \int phi_i rho, and embedding in mixed problem
17094a0cbf56SMatthew G. Knepley Vec rho; // Charge density, M^{-1} rhoRhs
17104a0cbf56SMatthew G. Knepley Vec phi, locPhi, phiFull; // Potential and embedding in mixed problem
17114a0cbf56SMatthew G. Knepley Vec f; // Particle weights
171275155f48SMatthew G. Knepley PetscReal *coords;
17134a0cbf56SMatthew G. Knepley PetscInt dim, cStart, cEnd, Np;
17148214e71cSJoe
17158214e71cSJoe PetscFunctionBegin;
1716*2a8381b2SBarry Smith PetscCall(DMGetApplicationContext(sw, &ctx));
1717*2a8381b2SBarry Smith PetscCall(PetscLogEventBegin(ctx->ESolveEvent, snes, sw, 0, 0));
17188214e71cSJoe PetscCall(DMGetDimension(sw, &dim));
17198214e71cSJoe PetscCall(DMSwarmGetLocalSize(sw, &Np));
17208214e71cSJoe PetscCall(SNESGetDM(snes, &dm));
1721*2a8381b2SBarry Smith PetscCall(DMGetGlobalVector(ctx->dmPot, &rhoRhs));
17224a0cbf56SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)rhoRhs, "Weak charge density"));
17234a0cbf56SMatthew G. Knepley PetscCall(DMGetGlobalVector(dm, &rhoRhsFull));
17244a0cbf56SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)rhoRhsFull, "Weak charge density"));
1725*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmPot, "rho", &rho));
17268214e71cSJoe PetscCall(DMSwarmCreateGlobalVectorFromField(sw, "w_q", &f));
17278214e71cSJoe PetscCall(PetscObjectSetName((PetscObject)f, "particle weight"));
17284a0cbf56SMatthew G. Knepley
17294a0cbf56SMatthew G. Knepley PetscCall(MatViewFromOptions(M_p, NULL, "-mp_view"));
1730*2a8381b2SBarry Smith PetscCall(MatViewFromOptions(ctx->M, NULL, "-m_view"));
17318214e71cSJoe PetscCall(VecViewFromOptions(f, NULL, "-weights_view"));
17324a0cbf56SMatthew G. Knepley
17334a0cbf56SMatthew G. Knepley PetscCall(MatMultTranspose(M_p, f, rhoRhs));
17348214e71cSJoe PetscCall(DMSwarmDestroyGlobalVectorFromField(sw, "w_q", &f));
17358214e71cSJoe
17368214e71cSJoe PetscCall(KSPCreate(PetscObjectComm((PetscObject)dm), &ksp));
17378214e71cSJoe PetscCall(KSPSetOptionsPrefix(ksp, "em_proj"));
1738*2a8381b2SBarry Smith PetscCall(KSPSetOperators(ksp, ctx->M, ctx->M));
17398214e71cSJoe PetscCall(KSPSetFromOptions(ksp));
17404a0cbf56SMatthew G. Knepley PetscCall(KSPSolve(ksp, rhoRhs, rho));
17418214e71cSJoe
1742*2a8381b2SBarry Smith PetscCall(VecISCopy(rhoRhsFull, ctx->isPot, SCATTER_FORWARD, rhoRhs));
17434a0cbf56SMatthew G. Knepley //PetscCall(VecScale(rhoRhsFull, -1.0));
17448214e71cSJoe
17454a0cbf56SMatthew G. Knepley PetscCall(VecViewFromOptions(rhoRhs, NULL, "-rho_view"));
17464a0cbf56SMatthew G. Knepley PetscCall(VecViewFromOptions(rhoRhsFull, NULL, "-rho_full_view"));
1747*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmPot, "rho", &rho));
1748*2a8381b2SBarry Smith PetscCall(DMRestoreGlobalVector(ctx->dmPot, &rhoRhs));
17498214e71cSJoe PetscCall(KSPDestroy(&ksp));
17508214e71cSJoe
17514a0cbf56SMatthew G. Knepley PetscCall(DMGetGlobalVector(dm, &phiFull));
1752*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmPot, "phi", &phi));
17534a0cbf56SMatthew G. Knepley PetscCall(VecSet(phiFull, 0.0));
17544a0cbf56SMatthew G. Knepley PetscCall(SNESSolve(snes, rhoRhsFull, phiFull));
17554a0cbf56SMatthew G. Knepley PetscCall(DMRestoreGlobalVector(dm, &rhoRhsFull));
17568214e71cSJoe PetscCall(VecViewFromOptions(phi, NULL, "-phi_view"));
17578214e71cSJoe
1758*2a8381b2SBarry Smith PetscCall(VecISCopy(phiFull, ctx->isPot, SCATTER_REVERSE, phi));
1759*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmPot, "phi", &phi));
17604a0cbf56SMatthew G. Knepley
17618214e71cSJoe PetscCall(DMGetLocalVector(dm, &locPhi));
17624a0cbf56SMatthew G. Knepley PetscCall(DMGlobalToLocalBegin(dm, phiFull, INSERT_VALUES, locPhi));
17634a0cbf56SMatthew G. Knepley PetscCall(DMGlobalToLocalEnd(dm, phiFull, INSERT_VALUES, locPhi));
17644a0cbf56SMatthew G. Knepley PetscCall(DMRestoreGlobalVector(dm, &phiFull));
1765*2a8381b2SBarry Smith PetscCall(PetscLogEventEnd(ctx->ESolveEvent, snes, sw, 0, 0));
17668214e71cSJoe
17678214e71cSJoe PetscCall(DMGetDS(dm, &ds));
17688214e71cSJoe PetscCall(PetscDSGetDiscretization(ds, 0, (PetscObject *)&fe));
17698214e71cSJoe PetscCall(DMSwarmSortGetAccess(sw));
17708214e71cSJoe PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
17718214e71cSJoe PetscCall(DMSwarmGetField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
17724a0cbf56SMatthew G. Knepley
1773*2a8381b2SBarry Smith PetscCall(PetscLogEventBegin(ctx->ETabEvent, snes, sw, 0, 0));
17748214e71cSJoe PetscTabulation tab;
17758214e71cSJoe PetscReal *pcoord, *refcoord;
17764a0cbf56SMatthew G. Knepley PetscFEGeom *chunkgeom = NULL;
17774a0cbf56SMatthew G. Knepley PetscInt maxNcp = 0;
17784a0cbf56SMatthew G. Knepley
17794a0cbf56SMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) {
17804a0cbf56SMatthew G. Knepley PetscInt Ncp;
17814a0cbf56SMatthew G. Knepley
17824a0cbf56SMatthew G. Knepley PetscCall(DMSwarmSortGetNumberOfPointsPerCell(sw, c, &Ncp));
17834a0cbf56SMatthew G. Knepley maxNcp = PetscMax(maxNcp, Ncp);
17844a0cbf56SMatthew G. Knepley }
17854a0cbf56SMatthew G. Knepley PetscCall(DMGetWorkArray(dm, maxNcp * dim, MPIU_REAL, &refcoord));
17864a0cbf56SMatthew G. Knepley PetscCall(DMGetWorkArray(dm, maxNcp * dim, MPIU_REAL, &pcoord));
17874a0cbf56SMatthew G. Knepley PetscCall(PetscFECreateTabulation(fe, 1, maxNcp, refcoord, 1, &tab));
17884a0cbf56SMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) {
17894a0cbf56SMatthew G. Knepley PetscScalar *clPhi = NULL;
17908214e71cSJoe PetscInt *points;
17918214e71cSJoe PetscInt Ncp;
17928214e71cSJoe
17938214e71cSJoe PetscCall(DMSwarmSortGetPointsPerCell(sw, c, &Ncp, &points));
17948214e71cSJoe for (PetscInt cp = 0; cp < Ncp; ++cp)
17958214e71cSJoe for (PetscInt d = 0; d < dim; ++d) pcoord[cp * dim + d] = coords[points[cp] * dim + d];
1796f1e6e573SMatthew G. Knepley {
1797*2a8381b2SBarry Smith PetscCall(PetscFEGeomGetChunk(ctx->fegeom, c - cStart, c - cStart + 1, &chunkgeom));
1798f1e6e573SMatthew G. Knepley for (PetscInt i = 0; i < Ncp; ++i) {
1799f1e6e573SMatthew G. Knepley const PetscReal x0[3] = {-1., -1., -1.};
1800f1e6e573SMatthew G. Knepley CoordinatesRealToRef(dim, dim, x0, chunkgeom->v, chunkgeom->invJ, &pcoord[dim * i], &refcoord[dim * i]);
1801f1e6e573SMatthew G. Knepley }
1802f1e6e573SMatthew G. Knepley }
18034a0cbf56SMatthew G. Knepley PetscCall(PetscFEComputeTabulation(fe, Ncp, refcoord, 1, tab));
18048214e71cSJoe PetscCall(DMPlexVecGetClosure(dm, NULL, locPhi, c, NULL, &clPhi));
18058214e71cSJoe for (PetscInt cp = 0; cp < Ncp; ++cp) {
18068214e71cSJoe const PetscInt p = points[cp];
18078214e71cSJoe
18088214e71cSJoe for (PetscInt d = 0; d < dim; ++d) E[p * dim + d] = 0.;
1809f1e6e573SMatthew G. Knepley PetscCall(PetscFEInterpolateAtPoints_Static(fe, tab, clPhi, chunkgeom, cp, &E[p * dim]));
1810f1e6e573SMatthew G. Knepley PetscCall(PetscFEPushforward(fe, chunkgeom, 1, &E[p * dim]));
18114a0cbf56SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) E[p * dim + d] *= -1.0;
18128214e71cSJoe }
18138214e71cSJoe PetscCall(DMPlexVecRestoreClosure(dm, NULL, locPhi, c, NULL, &clPhi));
181484467f86SMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(sw, c, &Ncp, &points));
18158214e71cSJoe }
18164a0cbf56SMatthew G. Knepley PetscCall(DMRestoreWorkArray(dm, maxNcp * dim, MPIU_REAL, &pcoord));
18174a0cbf56SMatthew G. Knepley PetscCall(DMRestoreWorkArray(dm, maxNcp * dim, MPIU_REAL, &refcoord));
18184a0cbf56SMatthew G. Knepley PetscCall(PetscTabulationDestroy(&tab));
18198214e71cSJoe PetscCall(DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
18208214e71cSJoe PetscCall(DMSwarmSortRestoreAccess(sw));
18218214e71cSJoe PetscCall(DMRestoreLocalVector(dm, &locPhi));
1822*2a8381b2SBarry Smith PetscCall(PetscFEGeomRestoreChunk(ctx->fegeom, 0, 1, &chunkgeom));
1823*2a8381b2SBarry Smith PetscCall(PetscLogEventEnd(ctx->ETabEvent, snes, sw, 0, 0));
18248214e71cSJoe PetscFunctionReturn(PETSC_SUCCESS);
18258214e71cSJoe }
18268214e71cSJoe
ComputeFieldAtParticles(SNES snes,DM sw)18274a0cbf56SMatthew G. Knepley static PetscErrorCode ComputeFieldAtParticles(SNES snes, DM sw)
18288214e71cSJoe {
1829*2a8381b2SBarry Smith AppCtx *ctx;
18304a0cbf56SMatthew G. Knepley Mat M_p;
18314a0cbf56SMatthew G. Knepley PetscReal *E;
18328214e71cSJoe PetscInt dim, Np;
18338214e71cSJoe
18348214e71cSJoe PetscFunctionBegin;
18358214e71cSJoe PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
18368214e71cSJoe PetscValidHeaderSpecific(sw, DM_CLASSID, 2);
18378214e71cSJoe PetscCall(DMGetDimension(sw, &dim));
18388214e71cSJoe PetscCall(DMSwarmGetLocalSize(sw, &Np));
1839*2a8381b2SBarry Smith PetscCall(DMGetApplicationContext(sw, &ctx));
18408214e71cSJoe
18414a0cbf56SMatthew G. Knepley PetscCall(DMSwarmSetCellDMActive(sw, "moments"));
18424a0cbf56SMatthew G. Knepley // TODO: Could share sort context with space cellDM
18434a0cbf56SMatthew G. Knepley PetscCall(DMSwarmMigrate(sw, PETSC_FALSE));
1844*2a8381b2SBarry Smith PetscCall(DMCreateMassMatrix(sw, ctx->dmPot, &M_p));
18454a0cbf56SMatthew G. Knepley PetscCall(DMSwarmSetCellDMActive(sw, "space"));
18464a0cbf56SMatthew G. Knepley
18474a0cbf56SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "E_field", NULL, NULL, (void **)&E));
18484a0cbf56SMatthew G. Knepley PetscCall(PetscArrayzero(E, Np * dim));
1849*2a8381b2SBarry Smith ctx->validE = PETSC_TRUE;
18504a0cbf56SMatthew G. Knepley
1851*2a8381b2SBarry Smith switch (ctx->em) {
18528214e71cSJoe case EM_COULOMB:
18538214e71cSJoe PetscCall(ComputeFieldAtParticles_Coulomb(snes, sw, E));
18548214e71cSJoe break;
18554a0cbf56SMatthew G. Knepley case EM_PRIMAL:
18564a0cbf56SMatthew G. Knepley PetscCall(ComputeFieldAtParticles_Primal(snes, sw, M_p, E));
18574a0cbf56SMatthew G. Knepley break;
18588214e71cSJoe case EM_MIXED:
18594a0cbf56SMatthew G. Knepley PetscCall(ComputeFieldAtParticles_Mixed(snes, sw, M_p, E));
18608214e71cSJoe break;
18618214e71cSJoe case EM_NONE:
18628214e71cSJoe break;
18638214e71cSJoe default:
1864*2a8381b2SBarry Smith SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No solver for electrostatic model %s", EMTypes[ctx->em]);
18658214e71cSJoe }
18664a0cbf56SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "E_field", NULL, NULL, (void **)&E));
18674a0cbf56SMatthew G. Knepley PetscCall(MatDestroy(&M_p));
18688214e71cSJoe PetscFunctionReturn(PETSC_SUCCESS);
18698214e71cSJoe }
18708214e71cSJoe
RHSFunction(TS ts,PetscReal t,Vec U,Vec G,PetscCtx ctx)1871*2a8381b2SBarry Smith static PetscErrorCode RHSFunction(TS ts, PetscReal t, Vec U, Vec G, PetscCtx ctx)
18728214e71cSJoe {
18738214e71cSJoe DM sw;
18748214e71cSJoe SNES snes = ((AppCtx *)ctx)->snes;
18758214e71cSJoe const PetscScalar *u;
18768214e71cSJoe PetscScalar *g;
18778214e71cSJoe PetscReal *E, m_p = 1., q_p = -1.;
18788214e71cSJoe PetscInt dim, d, Np, p;
1879b80bf5b1SJoe Pusztay
1880b80bf5b1SJoe Pusztay PetscFunctionBeginUser;
18818214e71cSJoe PetscCall(TSGetDM(ts, &sw));
18824a0cbf56SMatthew G. Knepley PetscCall(ComputeFieldAtParticles(snes, sw));
18834a0cbf56SMatthew G. Knepley
18848214e71cSJoe PetscCall(DMGetDimension(sw, &dim));
18858214e71cSJoe PetscCall(DMSwarmGetLocalSize(sw, &Np));
18864a0cbf56SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "E_field", NULL, NULL, (void **)&E));
18878214e71cSJoe PetscCall(VecGetArrayRead(U, &u));
18888214e71cSJoe PetscCall(VecGetArray(G, &g));
18898214e71cSJoe Np /= 2 * dim;
18908214e71cSJoe for (p = 0; p < Np; ++p) {
18918214e71cSJoe for (d = 0; d < dim; ++d) {
18928214e71cSJoe g[(p * 2 + 0) * dim + d] = u[(p * 2 + 1) * dim + d];
18938214e71cSJoe g[(p * 2 + 1) * dim + d] = q_p * E[p * dim + d] / m_p;
18948214e71cSJoe }
18958214e71cSJoe }
18968214e71cSJoe PetscCall(DMSwarmRestoreField(sw, "E_field", NULL, NULL, (void **)&E));
18978214e71cSJoe PetscCall(VecRestoreArrayRead(U, &u));
18988214e71cSJoe PetscCall(VecRestoreArray(G, &g));
18998214e71cSJoe PetscFunctionReturn(PETSC_SUCCESS);
19008214e71cSJoe }
19018214e71cSJoe
19028214e71cSJoe /* J_{ij} = dF_i/dx_j
19038214e71cSJoe J_p = ( 0 1)
19048214e71cSJoe (-w^2 0)
19058214e71cSJoe TODO Now there is another term with w^2 from the electric field. I think we will need to invert the operator.
19068214e71cSJoe Perhaps we can approximate the Jacobian using only the cellwise P-P gradient from Coulomb
19078214e71cSJoe */
RHSJacobian(TS ts,PetscReal t,Vec U,Mat J,Mat P,PetscCtx ctx)1908*2a8381b2SBarry Smith static PetscErrorCode RHSJacobian(TS ts, PetscReal t, Vec U, Mat J, Mat P, PetscCtx ctx)
19098214e71cSJoe {
19108214e71cSJoe DM sw;
19118214e71cSJoe const PetscReal *coords, *vel;
19128214e71cSJoe PetscInt dim, d, Np, p, rStart;
19138214e71cSJoe
19148214e71cSJoe PetscFunctionBeginUser;
19158214e71cSJoe PetscCall(TSGetDM(ts, &sw));
19168214e71cSJoe PetscCall(DMGetDimension(sw, &dim));
19178214e71cSJoe PetscCall(DMSwarmGetLocalSize(sw, &Np));
19188214e71cSJoe PetscCall(MatGetOwnershipRange(J, &rStart, NULL));
1919045208b8SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
1920045208b8SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "velocity", NULL, NULL, (void **)&vel));
19218214e71cSJoe Np /= 2 * dim;
19228214e71cSJoe for (p = 0; p < Np; ++p) {
1923f940b0e3Sdanofinn // TODO This is not right because dv/dx has the electric field in it
1924f940b0e3Sdanofinn PetscScalar vals[4] = {0., 1., -1, 0.};
19258214e71cSJoe
19268214e71cSJoe for (d = 0; d < dim; ++d) {
19278214e71cSJoe const PetscInt rows[2] = {(p * 2 + 0) * dim + d + rStart, (p * 2 + 1) * dim + d + rStart};
19288214e71cSJoe PetscCall(MatSetValues(J, 2, rows, 2, rows, vals, INSERT_VALUES));
19298214e71cSJoe }
19308214e71cSJoe }
1931045208b8SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
1932045208b8SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "velocity", NULL, NULL, (void **)&vel));
19338214e71cSJoe PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
19348214e71cSJoe PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
19358214e71cSJoe PetscFunctionReturn(PETSC_SUCCESS);
19368214e71cSJoe }
19378214e71cSJoe
RHSFunctionX(TS ts,PetscReal t,Vec V,Vec Xres,void * Ctx)1938*2a8381b2SBarry Smith static PetscErrorCode RHSFunctionX(TS ts, PetscReal t, Vec V, Vec Xres, void *Ctx)
19398214e71cSJoe {
1940*2a8381b2SBarry Smith AppCtx *ctx = (AppCtx *)Ctx;
19418214e71cSJoe DM sw;
19428214e71cSJoe const PetscScalar *v;
19438214e71cSJoe PetscScalar *xres;
19448214e71cSJoe PetscInt Np, p, d, dim;
19458214e71cSJoe
19468214e71cSJoe PetscFunctionBeginUser;
1947*2a8381b2SBarry Smith PetscCall(PetscLogEventBegin(ctx->RhsXEvent, ts, 0, 0, 0));
19488214e71cSJoe PetscCall(TSGetDM(ts, &sw));
19498214e71cSJoe PetscCall(DMGetDimension(sw, &dim));
19508214e71cSJoe PetscCall(VecGetLocalSize(Xres, &Np));
19519566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(V, &v));
19528214e71cSJoe PetscCall(VecGetArray(Xres, &xres));
1953b80bf5b1SJoe Pusztay Np /= dim;
1954b80bf5b1SJoe Pusztay for (p = 0; p < Np; ++p) {
1955045208b8SMatthew G. Knepley for (d = 0; d < dim; ++d) xres[p * dim + d] = v[p * dim + d];
1956b80bf5b1SJoe Pusztay }
19579566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(V, &v));
19588214e71cSJoe PetscCall(VecRestoreArray(Xres, &xres));
1959*2a8381b2SBarry Smith PetscCall(PetscLogEventEnd(ctx->RhsXEvent, ts, 0, 0, 0));
19603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1961b80bf5b1SJoe Pusztay }
1962b80bf5b1SJoe Pusztay
RHSFunctionV(TS ts,PetscReal t,Vec X,Vec Vres,void * Ctx)1963*2a8381b2SBarry Smith static PetscErrorCode RHSFunctionV(TS ts, PetscReal t, Vec X, Vec Vres, void *Ctx)
19648214e71cSJoe {
19658214e71cSJoe DM sw;
1966*2a8381b2SBarry Smith AppCtx *ctx = (AppCtx *)Ctx;
19678214e71cSJoe SNES snes = ((AppCtx *)ctx)->snes;
19688214e71cSJoe const PetscScalar *x;
19698214e71cSJoe PetscScalar *vres;
19704a0cbf56SMatthew G. Knepley PetscReal *E, m_p, q_p;
19718214e71cSJoe PetscInt Np, p, dim, d;
19728214e71cSJoe Parameter *param;
19738214e71cSJoe
19748214e71cSJoe PetscFunctionBeginUser;
1975*2a8381b2SBarry Smith PetscCall(PetscLogEventBegin(ctx->RhsVEvent, ts, 0, 0, 0));
19768214e71cSJoe PetscCall(TSGetDM(ts, &sw));
19774a0cbf56SMatthew G. Knepley PetscCall(ComputeFieldAtParticles(snes, sw));
19784a0cbf56SMatthew G. Knepley
19798214e71cSJoe PetscCall(DMGetDimension(sw, &dim));
19808214e71cSJoe PetscCall(DMSwarmGetField(sw, "E_field", NULL, NULL, (void **)&E));
1981*2a8381b2SBarry Smith PetscCall(PetscBagGetData(ctx->bag, (void **)¶m));
1982*2a8381b2SBarry Smith m_p = ctx->masses[0] * param->m0;
1983*2a8381b2SBarry Smith q_p = ctx->charges[0] * param->q0;
19848214e71cSJoe PetscCall(VecGetLocalSize(Vres, &Np));
19858214e71cSJoe PetscCall(VecGetArrayRead(X, &x));
19868214e71cSJoe PetscCall(VecGetArray(Vres, &vres));
19878214e71cSJoe Np /= dim;
19888214e71cSJoe for (p = 0; p < Np; ++p) {
1989045208b8SMatthew G. Knepley for (d = 0; d < dim; ++d) vres[p * dim + d] = q_p * E[p * dim + d] / m_p;
19908214e71cSJoe }
19918214e71cSJoe PetscCall(VecRestoreArrayRead(X, &x));
19928214e71cSJoe /*
1993d7c1f440SPierre Jolivet Synchronized, ordered output for parallel/sequential test cases.
19948214e71cSJoe In the 1D (on the 2D mesh) case, every y component should be zero.
19958214e71cSJoe */
1996*2a8381b2SBarry Smith if (ctx->checkVRes) {
1997*2a8381b2SBarry Smith PetscBool pr = ctx->checkVRes > 1 ? PETSC_TRUE : PETSC_FALSE;
19988214e71cSJoe PetscInt step;
19998214e71cSJoe
20008214e71cSJoe PetscCall(TSGetStepNumber(ts, &step));
20018214e71cSJoe if (pr) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "step: %" PetscInt_FMT "\n", step));
20028214e71cSJoe for (PetscInt p = 0; p < Np; ++p) {
20038214e71cSJoe if (pr) PetscCall(PetscSynchronizedPrintf(PETSC_COMM_WORLD, "Residual: %.12g %.12g\n", (double)PetscRealPart(vres[p * dim + 0]), (double)PetscRealPart(vres[p * dim + 1])));
20048214e71cSJoe PetscCheck(PetscAbsScalar(vres[p * dim + 1]) < PETSC_SMALL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Y velocity should be 0., not %g", (double)PetscRealPart(vres[p * dim + 1]));
20058214e71cSJoe }
20068214e71cSJoe if (pr) PetscCall(PetscSynchronizedFlush(PETSC_COMM_WORLD, PETSC_STDOUT));
20078214e71cSJoe }
20088214e71cSJoe PetscCall(VecRestoreArray(Vres, &vres));
20098214e71cSJoe PetscCall(DMSwarmRestoreField(sw, "E_field", NULL, NULL, (void **)&E));
2010*2a8381b2SBarry Smith PetscCall(PetscLogEventEnd(ctx->RhsVEvent, ts, 0, 0, 0));
20118214e71cSJoe PetscFunctionReturn(PETSC_SUCCESS);
20128214e71cSJoe }
20138214e71cSJoe
2014f940b0e3Sdanofinn /* Discrete Gradients Formulation: S, F, gradF (G) */
RHSJacobianS(TS ts,PetscReal t,Vec U,Mat S,PetscCtx ctx)2015*2a8381b2SBarry Smith PetscErrorCode RHSJacobianS(TS ts, PetscReal t, Vec U, Mat S, PetscCtx ctx)
2016f940b0e3Sdanofinn {
2017f940b0e3Sdanofinn PetscScalar vals[4] = {0., 1., -1., 0.};
2018f940b0e3Sdanofinn DM sw;
2019f940b0e3Sdanofinn PetscInt dim, d, Np, p, rStart;
2020f940b0e3Sdanofinn
2021f940b0e3Sdanofinn PetscFunctionBeginUser;
2022f940b0e3Sdanofinn PetscCall(TSGetDM(ts, &sw));
2023f940b0e3Sdanofinn PetscCall(DMGetDimension(sw, &dim));
2024f940b0e3Sdanofinn PetscCall(VecGetLocalSize(U, &Np));
2025f940b0e3Sdanofinn PetscCall(MatGetOwnershipRange(S, &rStart, NULL));
2026f940b0e3Sdanofinn Np /= 2 * dim;
2027f940b0e3Sdanofinn for (p = 0; p < Np; ++p) {
2028f940b0e3Sdanofinn for (d = 0; d < dim; ++d) {
2029f940b0e3Sdanofinn const PetscInt rows[2] = {(p * 2 + 0) * dim + d + rStart, (p * 2 + 1) * dim + d + rStart};
2030f940b0e3Sdanofinn PetscCall(MatSetValues(S, 2, rows, 2, rows, vals, INSERT_VALUES));
2031f940b0e3Sdanofinn }
2032f940b0e3Sdanofinn }
2033f940b0e3Sdanofinn PetscCall(MatAssemblyBegin(S, MAT_FINAL_ASSEMBLY));
2034f940b0e3Sdanofinn PetscCall(MatAssemblyEnd(S, MAT_FINAL_ASSEMBLY));
2035f940b0e3Sdanofinn PetscFunctionReturn(PETSC_SUCCESS);
2036f940b0e3Sdanofinn }
2037f940b0e3Sdanofinn
RHSObjectiveF(TS ts,PetscReal t,Vec U,PetscScalar * F,void * Ctx)2038*2a8381b2SBarry Smith PetscErrorCode RHSObjectiveF(TS ts, PetscReal t, Vec U, PetscScalar *F, void *Ctx)
2039f940b0e3Sdanofinn {
2040*2a8381b2SBarry Smith AppCtx *ctx = (AppCtx *)Ctx;
2041f940b0e3Sdanofinn DM sw;
2042f940b0e3Sdanofinn Vec phi;
2043f940b0e3Sdanofinn const PetscScalar *u;
2044f940b0e3Sdanofinn PetscInt dim, Np, cStart, cEnd;
2045f940b0e3Sdanofinn PetscReal *vel, *coords, m_p = 1.;
2046f940b0e3Sdanofinn
2047f940b0e3Sdanofinn PetscFunctionBeginUser;
2048f940b0e3Sdanofinn PetscCall(TSGetDM(ts, &sw));
2049f940b0e3Sdanofinn PetscCall(DMGetDimension(sw, &dim));
2050*2a8381b2SBarry Smith PetscCall(DMPlexGetHeightStratum(ctx->dmPot, 0, &cStart, &cEnd));
2051f940b0e3Sdanofinn
2052*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmPot, "phi", &phi));
2053f940b0e3Sdanofinn PetscCall(VecViewFromOptions(phi, NULL, "-phi_view_dg"));
2054*2a8381b2SBarry Smith PetscCall(computeFieldEnergy(ctx->dmPot, phi, F));
2055*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmPot, "phi", &phi));
2056f940b0e3Sdanofinn
2057f940b0e3Sdanofinn PetscCall(DMSwarmGetField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
2058f940b0e3Sdanofinn PetscCall(DMSwarmGetField(sw, "velocity", NULL, NULL, (void **)&vel));
2059f940b0e3Sdanofinn PetscCall(DMSwarmSortGetAccess(sw));
2060f940b0e3Sdanofinn PetscCall(VecGetArrayRead(U, &u));
2061f940b0e3Sdanofinn PetscCall(VecGetLocalSize(U, &Np));
2062f940b0e3Sdanofinn Np /= 2 * dim;
2063f940b0e3Sdanofinn for (PetscInt c = cStart; c < cEnd; ++c) {
2064f940b0e3Sdanofinn PetscInt *points;
2065f940b0e3Sdanofinn PetscInt Ncp;
2066f940b0e3Sdanofinn
2067f940b0e3Sdanofinn PetscCall(DMSwarmSortGetPointsPerCell(sw, c, &Ncp, &points));
2068f940b0e3Sdanofinn for (PetscInt cp = 0; cp < Ncp; ++cp) {
2069f940b0e3Sdanofinn const PetscInt p = points[cp];
2070f940b0e3Sdanofinn const PetscReal v2 = DMPlex_DotRealD_Internal(dim, &u[(p * 2 + 1) * dim], &u[(p * 2 + 1) * dim]);
2071f940b0e3Sdanofinn
2072f940b0e3Sdanofinn *F += 0.5 * m_p * v2;
2073f940b0e3Sdanofinn }
2074f940b0e3Sdanofinn PetscCall(DMSwarmSortRestorePointsPerCell(sw, c, &Ncp, &points));
2075f940b0e3Sdanofinn }
2076f940b0e3Sdanofinn PetscCall(VecRestoreArrayRead(U, &u));
2077f940b0e3Sdanofinn PetscCall(DMSwarmSortRestoreAccess(sw));
2078f940b0e3Sdanofinn PetscCall(DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
2079f940b0e3Sdanofinn PetscCall(DMSwarmRestoreField(sw, "velocity", NULL, NULL, (void **)&vel));
2080f940b0e3Sdanofinn PetscFunctionReturn(PETSC_SUCCESS);
2081f940b0e3Sdanofinn }
2082f940b0e3Sdanofinn
2083f940b0e3Sdanofinn /* dF/dx = q E dF/dv = v */
RHSFunctionG(TS ts,PetscReal t,Vec U,Vec G,PetscCtx ctx)2084*2a8381b2SBarry Smith PetscErrorCode RHSFunctionG(TS ts, PetscReal t, Vec U, Vec G, PetscCtx ctx)
2085f940b0e3Sdanofinn {
2086f940b0e3Sdanofinn DM sw;
2087f940b0e3Sdanofinn SNES snes = ((AppCtx *)ctx)->snes;
2088f940b0e3Sdanofinn const PetscReal *coords, *vel, *E;
2089f940b0e3Sdanofinn const PetscScalar *u;
2090f940b0e3Sdanofinn PetscScalar *g;
2091f940b0e3Sdanofinn PetscReal m_p = 1., q_p = -1.;
2092f940b0e3Sdanofinn PetscInt dim, d, Np, p;
2093f940b0e3Sdanofinn
2094f940b0e3Sdanofinn PetscFunctionBeginUser;
2095f940b0e3Sdanofinn PetscCall(TSGetDM(ts, &sw));
2096f940b0e3Sdanofinn PetscCall(DMGetDimension(sw, &dim));
2097f940b0e3Sdanofinn PetscCall(DMSwarmGetLocalSize(sw, &Np));
2098f940b0e3Sdanofinn PetscCall(VecGetArrayRead(U, &u));
2099f940b0e3Sdanofinn PetscCall(VecGetArray(G, &g));
2100f940b0e3Sdanofinn
2101f940b0e3Sdanofinn PetscLogEvent COMPUTEFIELD;
2102f940b0e3Sdanofinn PetscCall(PetscLogEventRegister("COMPFIELDATPART", TS_CLASSID, &COMPUTEFIELD));
2103f940b0e3Sdanofinn PetscCall(PetscLogEventBegin(COMPUTEFIELD, 0, 0, 0, 0));
2104f940b0e3Sdanofinn PetscCall(ComputeFieldAtParticles(snes, sw));
2105f940b0e3Sdanofinn PetscCall(PetscLogEventEnd(COMPUTEFIELD, 0, 0, 0, 0));
2106f940b0e3Sdanofinn PetscCall(DMSwarmGetField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
2107f940b0e3Sdanofinn PetscCall(DMSwarmGetField(sw, "velocity", NULL, NULL, (void **)&vel));
2108f940b0e3Sdanofinn PetscCall(DMSwarmGetField(sw, "E_field", NULL, NULL, (void **)&E));
2109f940b0e3Sdanofinn for (p = 0; p < Np; ++p) {
2110f940b0e3Sdanofinn for (d = 0; d < dim; ++d) {
2111f940b0e3Sdanofinn g[(p * 2 + 0) * dim + d] = -(q_p / m_p) * E[p * dim + d];
2112f940b0e3Sdanofinn g[(p * 2 + 1) * dim + d] = u[(p * 2 + 1) * dim + d];
2113f940b0e3Sdanofinn }
2114f940b0e3Sdanofinn }
2115f940b0e3Sdanofinn PetscCall(DMSwarmRestoreField(sw, "E_field", NULL, NULL, (void **)&E));
2116f940b0e3Sdanofinn PetscCall(DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
2117f940b0e3Sdanofinn PetscCall(DMSwarmRestoreField(sw, "velocity", NULL, NULL, (void **)&vel));
2118f940b0e3Sdanofinn PetscCall(VecRestoreArrayRead(U, &u));
2119f940b0e3Sdanofinn PetscCall(VecRestoreArray(G, &g));
2120f940b0e3Sdanofinn PetscFunctionReturn(PETSC_SUCCESS);
2121f940b0e3Sdanofinn }
2122f940b0e3Sdanofinn
CreateSolution(TS ts)21238214e71cSJoe static PetscErrorCode CreateSolution(TS ts)
21248214e71cSJoe {
21258214e71cSJoe DM sw;
21268214e71cSJoe Vec u;
21278214e71cSJoe PetscInt dim, Np;
21288214e71cSJoe
21298214e71cSJoe PetscFunctionBegin;
21308214e71cSJoe PetscCall(TSGetDM(ts, &sw));
21318214e71cSJoe PetscCall(DMGetDimension(sw, &dim));
21328214e71cSJoe PetscCall(DMSwarmGetLocalSize(sw, &Np));
21338214e71cSJoe PetscCall(VecCreate(PETSC_COMM_WORLD, &u));
21348214e71cSJoe PetscCall(VecSetBlockSize(u, dim));
21358214e71cSJoe PetscCall(VecSetSizes(u, 2 * Np * dim, PETSC_DECIDE));
21368214e71cSJoe PetscCall(VecSetUp(u));
21378214e71cSJoe PetscCall(TSSetSolution(ts, u));
21388214e71cSJoe PetscCall(VecDestroy(&u));
21398214e71cSJoe PetscFunctionReturn(PETSC_SUCCESS);
21408214e71cSJoe }
21418214e71cSJoe
SetProblem(TS ts)21428214e71cSJoe static PetscErrorCode SetProblem(TS ts)
21438214e71cSJoe {
2144*2a8381b2SBarry Smith AppCtx *ctx;
21458214e71cSJoe DM sw;
21468214e71cSJoe
21478214e71cSJoe PetscFunctionBegin;
21488214e71cSJoe PetscCall(TSGetDM(ts, &sw));
2149*2a8381b2SBarry Smith PetscCall(DMGetApplicationContext(sw, &ctx));
21508214e71cSJoe // Define unified system for (X, V)
21518214e71cSJoe {
21528214e71cSJoe Mat J;
21538214e71cSJoe PetscInt dim, Np;
21548214e71cSJoe
21558214e71cSJoe PetscCall(DMGetDimension(sw, &dim));
21568214e71cSJoe PetscCall(DMSwarmGetLocalSize(sw, &Np));
21578214e71cSJoe PetscCall(MatCreate(PETSC_COMM_WORLD, &J));
21588214e71cSJoe PetscCall(MatSetSizes(J, 2 * Np * dim, 2 * Np * dim, PETSC_DECIDE, PETSC_DECIDE));
21598214e71cSJoe PetscCall(MatSetBlockSize(J, 2 * dim));
21608214e71cSJoe PetscCall(MatSetFromOptions(J));
21618214e71cSJoe PetscCall(MatSetUp(J));
2162*2a8381b2SBarry Smith PetscCall(TSSetRHSFunction(ts, NULL, RHSFunction, ctx));
2163*2a8381b2SBarry Smith PetscCall(TSSetRHSJacobian(ts, J, J, RHSJacobian, ctx));
21648214e71cSJoe PetscCall(MatDestroy(&J));
21658214e71cSJoe }
21668214e71cSJoe /* Define split system for X and V */
21678214e71cSJoe {
21688214e71cSJoe Vec u;
21698214e71cSJoe IS isx, isv, istmp;
21708214e71cSJoe const PetscInt *idx;
21718214e71cSJoe PetscInt dim, Np, rstart;
21728214e71cSJoe
21738214e71cSJoe PetscCall(TSGetSolution(ts, &u));
21748214e71cSJoe PetscCall(DMGetDimension(sw, &dim));
21758214e71cSJoe PetscCall(DMSwarmGetLocalSize(sw, &Np));
21768214e71cSJoe PetscCall(VecGetOwnershipRange(u, &rstart, NULL));
21778214e71cSJoe PetscCall(ISCreateStride(PETSC_COMM_WORLD, Np, (rstart / dim) + 0, 2, &istmp));
21788214e71cSJoe PetscCall(ISGetIndices(istmp, &idx));
21798214e71cSJoe PetscCall(ISCreateBlock(PETSC_COMM_WORLD, dim, Np, idx, PETSC_COPY_VALUES, &isx));
21808214e71cSJoe PetscCall(ISRestoreIndices(istmp, &idx));
21818214e71cSJoe PetscCall(ISDestroy(&istmp));
21828214e71cSJoe PetscCall(ISCreateStride(PETSC_COMM_WORLD, Np, (rstart / dim) + 1, 2, &istmp));
21838214e71cSJoe PetscCall(ISGetIndices(istmp, &idx));
21848214e71cSJoe PetscCall(ISCreateBlock(PETSC_COMM_WORLD, dim, Np, idx, PETSC_COPY_VALUES, &isv));
21858214e71cSJoe PetscCall(ISRestoreIndices(istmp, &idx));
21868214e71cSJoe PetscCall(ISDestroy(&istmp));
21878214e71cSJoe PetscCall(TSRHSSplitSetIS(ts, "position", isx));
21888214e71cSJoe PetscCall(TSRHSSplitSetIS(ts, "momentum", isv));
21898214e71cSJoe PetscCall(ISDestroy(&isx));
21908214e71cSJoe PetscCall(ISDestroy(&isv));
2191*2a8381b2SBarry Smith PetscCall(TSRHSSplitSetRHSFunction(ts, "position", NULL, RHSFunctionX, ctx));
2192*2a8381b2SBarry Smith PetscCall(TSRHSSplitSetRHSFunction(ts, "momentum", NULL, RHSFunctionV, ctx));
21938214e71cSJoe }
2194f940b0e3Sdanofinn // Define symplectic formulation U_t = S . G, where G = grad F
2195f940b0e3Sdanofinn {
2196*2a8381b2SBarry Smith PetscCall(TSDiscGradSetFormulation(ts, RHSJacobianS, RHSObjectiveF, RHSFunctionG, ctx));
2197f940b0e3Sdanofinn }
21988214e71cSJoe PetscFunctionReturn(PETSC_SUCCESS);
21998214e71cSJoe }
22008214e71cSJoe
DMSwarmTSRedistribute(TS ts)22018214e71cSJoe static PetscErrorCode DMSwarmTSRedistribute(TS ts)
22028214e71cSJoe {
22038214e71cSJoe DM sw;
22048214e71cSJoe Vec u;
22058214e71cSJoe PetscReal t, maxt, dt;
22068214e71cSJoe PetscInt n, maxn;
22078214e71cSJoe
22088214e71cSJoe PetscFunctionBegin;
22098214e71cSJoe PetscCall(TSGetDM(ts, &sw));
22108214e71cSJoe PetscCall(TSGetTime(ts, &t));
22118214e71cSJoe PetscCall(TSGetMaxTime(ts, &maxt));
22128214e71cSJoe PetscCall(TSGetTimeStep(ts, &dt));
22138214e71cSJoe PetscCall(TSGetStepNumber(ts, &n));
22148214e71cSJoe PetscCall(TSGetMaxSteps(ts, &maxn));
22158214e71cSJoe
22168214e71cSJoe PetscCall(TSReset(ts));
22178214e71cSJoe PetscCall(TSSetDM(ts, sw));
22188214e71cSJoe PetscCall(TSSetFromOptions(ts));
22198214e71cSJoe PetscCall(TSSetTime(ts, t));
22208214e71cSJoe PetscCall(TSSetMaxTime(ts, maxt));
22218214e71cSJoe PetscCall(TSSetTimeStep(ts, dt));
22228214e71cSJoe PetscCall(TSSetStepNumber(ts, n));
22238214e71cSJoe PetscCall(TSSetMaxSteps(ts, maxn));
22248214e71cSJoe
22258214e71cSJoe PetscCall(CreateSolution(ts));
22268214e71cSJoe PetscCall(SetProblem(ts));
22278214e71cSJoe PetscCall(TSGetSolution(ts, &u));
22288214e71cSJoe PetscFunctionReturn(PETSC_SUCCESS);
22298214e71cSJoe }
22308214e71cSJoe
line(PetscInt dim,PetscReal time,const PetscReal dummy[],PetscInt p,PetscScalar x[],void * Ctx)2231*2a8381b2SBarry Smith PetscErrorCode line(PetscInt dim, PetscReal time, const PetscReal dummy[], PetscInt p, PetscScalar x[], void *Ctx)
22328214e71cSJoe {
22338214e71cSJoe DM sw, cdm;
22348214e71cSJoe PetscInt Np;
22358214e71cSJoe PetscReal low[2], high[2];
2236*2a8381b2SBarry Smith AppCtx *ctx = (AppCtx *)Ctx;
22378214e71cSJoe
2238*2a8381b2SBarry Smith sw = ctx->swarm;
22398214e71cSJoe PetscCall(DMSwarmGetCellDM(sw, &cdm));
22408214e71cSJoe // Get the bounding box so we can equally space the particles
22418214e71cSJoe PetscCall(DMGetLocalBoundingBox(cdm, low, high));
22428214e71cSJoe PetscCall(DMSwarmGetLocalSize(sw, &Np));
22438214e71cSJoe // shift it by h/2 so nothing is initialized directly on a boundary
22448214e71cSJoe x[0] = ((high[0] - low[0]) / Np) * (p + 0.5);
22458214e71cSJoe x[1] = 0.;
22468214e71cSJoe return PETSC_SUCCESS;
22478214e71cSJoe }
22488214e71cSJoe
2249b80bf5b1SJoe Pusztay /*
22508214e71cSJoe InitializeSolveAndSwarm - Set the solution values to the swarm coordinates and velocities, and also possibly set the initial values.
22518214e71cSJoe
22528214e71cSJoe Input Parameters:
22538214e71cSJoe + ts - The TS
2254d7c1f440SPierre Jolivet - useInitial - Flag to also set the initial conditions to the current coordinates and velocities and setup the problem
22558214e71cSJoe
22568214e71cSJoe Output Parameters:
22578214e71cSJoe . u - The initialized solution vector
22588214e71cSJoe
22598214e71cSJoe Level: advanced
22608214e71cSJoe
22618214e71cSJoe .seealso: InitializeSolve()
2262b80bf5b1SJoe Pusztay */
InitializeSolveAndSwarm(TS ts,PetscBool useInitial)22638214e71cSJoe static PetscErrorCode InitializeSolveAndSwarm(TS ts, PetscBool useInitial)
2264d71ae5a4SJacob Faibussowitsch {
22658214e71cSJoe DM sw;
2266045208b8SMatthew G. Knepley Vec u, gc, gv;
22678214e71cSJoe IS isx, isv;
22688214e71cSJoe PetscInt dim;
2269*2a8381b2SBarry Smith AppCtx *ctx;
2270b80bf5b1SJoe Pusztay
2271b80bf5b1SJoe Pusztay PetscFunctionBeginUser;
22728214e71cSJoe PetscCall(TSGetDM(ts, &sw));
2273*2a8381b2SBarry Smith PetscCall(DMGetApplicationContext(sw, &ctx));
22748214e71cSJoe PetscCall(DMGetDimension(sw, &dim));
22758214e71cSJoe if (useInitial) {
22768214e71cSJoe PetscReal v0[2] = {1., 0.};
2277*2a8381b2SBarry Smith if (ctx->perturbed_weights) {
2278*2a8381b2SBarry Smith PetscCall(InitializeParticles_PerturbedWeights(sw, ctx));
22798214e71cSJoe } else {
22808214e71cSJoe PetscCall(DMSwarmComputeLocalSizeFromOptions(sw));
22818214e71cSJoe PetscCall(DMSwarmInitializeCoordinates(sw));
22828214e71cSJoe PetscCall(DMSwarmInitializeVelocitiesFromOptions(sw, v0));
22838214e71cSJoe }
22848214e71cSJoe PetscCall(DMSwarmMigrate(sw, PETSC_TRUE));
22858214e71cSJoe PetscCall(DMSwarmTSRedistribute(ts));
22868214e71cSJoe }
2287045208b8SMatthew G. Knepley PetscCall(DMSetUp(sw));
22888214e71cSJoe PetscCall(TSGetSolution(ts, &u));
22898214e71cSJoe PetscCall(TSRHSSplitGetIS(ts, "position", &isx));
22908214e71cSJoe PetscCall(TSRHSSplitGetIS(ts, "momentum", &isv));
22918214e71cSJoe PetscCall(DMSwarmCreateGlobalVectorFromField(sw, DMSwarmPICField_coor, &gc));
22928214e71cSJoe PetscCall(DMSwarmCreateGlobalVectorFromField(sw, "velocity", &gv));
22938214e71cSJoe PetscCall(VecISCopy(u, isx, SCATTER_FORWARD, gc));
22948214e71cSJoe PetscCall(VecISCopy(u, isv, SCATTER_FORWARD, gv));
22958214e71cSJoe PetscCall(DMSwarmDestroyGlobalVectorFromField(sw, DMSwarmPICField_coor, &gc));
22968214e71cSJoe PetscCall(DMSwarmDestroyGlobalVectorFromField(sw, "velocity", &gv));
22978214e71cSJoe PetscFunctionReturn(PETSC_SUCCESS);
22988214e71cSJoe }
22998214e71cSJoe
InitializeSolve(TS ts,Vec u)23008214e71cSJoe static PetscErrorCode InitializeSolve(TS ts, Vec u)
2301b80bf5b1SJoe Pusztay {
23028214e71cSJoe PetscFunctionBegin;
23038214e71cSJoe PetscCall(TSSetSolution(ts, u));
23048214e71cSJoe PetscCall(InitializeSolveAndSwarm(ts, PETSC_TRUE));
23058214e71cSJoe PetscFunctionReturn(PETSC_SUCCESS);
2306b80bf5b1SJoe Pusztay }
2307b80bf5b1SJoe Pusztay
MigrateParticles(TS ts)23088214e71cSJoe static PetscErrorCode MigrateParticles(TS ts)
23098214e71cSJoe {
23108214e71cSJoe DM sw, cdm;
23118214e71cSJoe const PetscReal *L;
23129072cb8bSMatthew G. Knepley AppCtx *ctx;
23138214e71cSJoe
23148214e71cSJoe PetscFunctionBeginUser;
23158214e71cSJoe PetscCall(TSGetDM(ts, &sw));
23169072cb8bSMatthew G. Knepley PetscCall(DMGetApplicationContext(sw, &ctx));
23178214e71cSJoe PetscCall(DMViewFromOptions(sw, NULL, "-migrate_view_pre"));
23188214e71cSJoe {
23198214e71cSJoe Vec u, gc, gv, position, momentum;
23208214e71cSJoe IS isx, isv;
23218214e71cSJoe PetscReal *pos, *mom;
23228214e71cSJoe
23238214e71cSJoe PetscCall(TSGetSolution(ts, &u));
23248214e71cSJoe PetscCall(TSRHSSplitGetIS(ts, "position", &isx));
23258214e71cSJoe PetscCall(TSRHSSplitGetIS(ts, "momentum", &isv));
23268214e71cSJoe PetscCall(VecGetSubVector(u, isx, &position));
23278214e71cSJoe PetscCall(VecGetSubVector(u, isv, &momentum));
23288214e71cSJoe PetscCall(VecGetArray(position, &pos));
23298214e71cSJoe PetscCall(VecGetArray(momentum, &mom));
23308214e71cSJoe PetscCall(DMSwarmCreateGlobalVectorFromField(sw, DMSwarmPICField_coor, &gc));
23318214e71cSJoe PetscCall(DMSwarmCreateGlobalVectorFromField(sw, "velocity", &gv));
23328214e71cSJoe PetscCall(VecISCopy(u, isx, SCATTER_REVERSE, gc));
23338214e71cSJoe PetscCall(VecISCopy(u, isv, SCATTER_REVERSE, gv));
23348214e71cSJoe
23358214e71cSJoe PetscCall(DMSwarmGetCellDM(sw, &cdm));
23368214e71cSJoe PetscCall(DMGetPeriodicity(cdm, NULL, NULL, &L));
23378214e71cSJoe if ((L[0] || L[1]) >= 0.) {
23388214e71cSJoe PetscReal *x, *v, upper[3], lower[3];
23398214e71cSJoe PetscInt Np, dim;
23408214e71cSJoe
23418214e71cSJoe PetscCall(DMSwarmGetLocalSize(sw, &Np));
23428214e71cSJoe PetscCall(DMGetDimension(cdm, &dim));
23438214e71cSJoe PetscCall(DMGetBoundingBox(cdm, lower, upper));
23448214e71cSJoe PetscCall(VecGetArray(gc, &x));
23458214e71cSJoe PetscCall(VecGetArray(gv, &v));
23468214e71cSJoe for (PetscInt p = 0; p < Np; ++p) {
23478214e71cSJoe for (PetscInt d = 0; d < dim; ++d) {
23488214e71cSJoe if (pos[p * dim + d] < lower[d]) {
23498214e71cSJoe x[p * dim + d] = pos[p * dim + d] + (upper[d] - lower[d]);
23508214e71cSJoe } else if (pos[p * dim + d] > upper[d]) {
23518214e71cSJoe x[p * dim + d] = pos[p * dim + d] - (upper[d] - lower[d]);
23528214e71cSJoe } else {
23538214e71cSJoe x[p * dim + d] = pos[p * dim + d];
23548214e71cSJoe }
23558214e71cSJoe PetscCheck(x[p * dim + d] >= lower[d] && x[p * dim + d] <= upper[d], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "p: %" PetscInt_FMT "x[%" PetscInt_FMT "] %g", p, d, (double)x[p * dim + d]);
23568214e71cSJoe v[p * dim + d] = mom[p * dim + d];
23578214e71cSJoe }
23588214e71cSJoe }
23598214e71cSJoe PetscCall(VecRestoreArray(gc, &x));
23608214e71cSJoe PetscCall(VecRestoreArray(gv, &v));
23618214e71cSJoe }
23628214e71cSJoe PetscCall(VecRestoreArray(position, &pos));
23638214e71cSJoe PetscCall(VecRestoreArray(momentum, &mom));
23648214e71cSJoe PetscCall(VecRestoreSubVector(u, isx, &position));
23658214e71cSJoe PetscCall(VecRestoreSubVector(u, isv, &momentum));
23668214e71cSJoe PetscCall(DMSwarmDestroyGlobalVectorFromField(sw, "velocity", &gv));
23678214e71cSJoe PetscCall(DMSwarmDestroyGlobalVectorFromField(sw, DMSwarmPICField_coor, &gc));
23688214e71cSJoe }
23698214e71cSJoe PetscCall(DMSwarmMigrate(sw, PETSC_TRUE));
23709072cb8bSMatthew G. Knepley PetscInt step;
23719072cb8bSMatthew G. Knepley
23729072cb8bSMatthew G. Knepley PetscCall(TSGetStepNumber(ts, &step));
2373045208b8SMatthew G. Knepley if (!(step % ctx->remapFreq)) {
23749072cb8bSMatthew G. Knepley // Monitor electric field before we destroy it
23759072cb8bSMatthew G. Knepley PetscReal ptime;
23769072cb8bSMatthew G. Knepley PetscInt step;
23779072cb8bSMatthew G. Knepley
23789072cb8bSMatthew G. Knepley PetscCall(TSGetStepNumber(ts, &step));
23799072cb8bSMatthew G. Knepley PetscCall(TSGetTime(ts, &ptime));
23809072cb8bSMatthew G. Knepley if (ctx->efield_monitor) PetscCall(MonitorEField(ts, step, ptime, NULL, ctx));
23819072cb8bSMatthew G. Knepley if (ctx->poisson_monitor) PetscCall(MonitorPoisson(ts, step, ptime, NULL, ctx));
23829072cb8bSMatthew G. Knepley PetscCall(DMSwarmRemap(sw));
23839072cb8bSMatthew G. Knepley ctx->validE = PETSC_FALSE;
23849072cb8bSMatthew G. Knepley }
23859072cb8bSMatthew G. Knepley // This MUST come last, since it recreates the subswarms and they must DMClone() the new swarm
23868214e71cSJoe PetscCall(DMSwarmTSRedistribute(ts));
23878214e71cSJoe PetscCall(InitializeSolveAndSwarm(ts, PETSC_FALSE));
2388f940b0e3Sdanofinn {
2389f940b0e3Sdanofinn const char *fieldnames[2] = {DMSwarmPICField_coor, "velocity"};
2390f940b0e3Sdanofinn PetscCall(DMSwarmVectorDefineFields(sw, 2, fieldnames));
2391f940b0e3Sdanofinn }
23923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2393b80bf5b1SJoe Pusztay }
2394b80bf5b1SJoe Pusztay
main(int argc,char ** argv)2395d71ae5a4SJacob Faibussowitsch int main(int argc, char **argv)
2396d71ae5a4SJacob Faibussowitsch {
2397b80bf5b1SJoe Pusztay DM dm, sw;
23988214e71cSJoe TS ts;
23998214e71cSJoe Vec u;
24008214e71cSJoe PetscReal dt;
24018214e71cSJoe PetscInt maxn;
2402*2a8381b2SBarry Smith AppCtx ctx;
2403b80bf5b1SJoe Pusztay
24049566063dSJacob Faibussowitsch PetscCall(PetscInitialize(&argc, &argv, NULL, help));
2405*2a8381b2SBarry Smith PetscCall(ProcessOptions(PETSC_COMM_WORLD, &ctx));
2406*2a8381b2SBarry Smith PetscCall(PetscBagCreate(PETSC_COMM_SELF, sizeof(Parameter), &ctx.bag));
2407*2a8381b2SBarry Smith PetscCall(CreateMesh(PETSC_COMM_WORLD, &ctx, &dm));
2408*2a8381b2SBarry Smith PetscCall(CreatePoisson(dm, &ctx));
2409*2a8381b2SBarry Smith PetscCall(CreateSwarm(dm, &ctx, &sw));
2410*2a8381b2SBarry Smith PetscCall(SetupParameters(PETSC_COMM_WORLD, &ctx));
2411*2a8381b2SBarry Smith PetscCall(InitializeConstants(sw, &ctx));
2412*2a8381b2SBarry Smith PetscCall(DMSetApplicationContext(sw, &ctx));
2413b80bf5b1SJoe Pusztay
24148214e71cSJoe PetscCall(TSCreate(PETSC_COMM_WORLD, &ts));
24158214e71cSJoe PetscCall(TSSetProblemType(ts, TS_NONLINEAR));
24169566063dSJacob Faibussowitsch PetscCall(TSSetDM(ts, sw));
24178214e71cSJoe PetscCall(TSSetMaxTime(ts, 0.1));
24188214e71cSJoe PetscCall(TSSetTimeStep(ts, 0.00001));
24198214e71cSJoe PetscCall(TSSetMaxSteps(ts, 100));
24208214e71cSJoe PetscCall(TSSetExactFinalTime(ts, TS_EXACTFINALTIME_MATCHSTEP));
24218214e71cSJoe
2422*2a8381b2SBarry Smith if (ctx.efield_monitor) PetscCall(TSMonitorSet(ts, MonitorEField, &ctx, NULL));
2423*2a8381b2SBarry Smith if (ctx.moment_monitor) PetscCall(TSMonitorSet(ts, MonitorMoments, &ctx, NULL));
2424*2a8381b2SBarry Smith if (ctx.initial_monitor) PetscCall(TSMonitorSet(ts, MonitorInitialConditions, &ctx, NULL));
2425*2a8381b2SBarry Smith if (ctx.positions_monitor) PetscCall(TSMonitorSet(ts, MonitorPositions_2D, &ctx, NULL));
2426*2a8381b2SBarry Smith if (ctx.poisson_monitor) PetscCall(TSMonitorSet(ts, MonitorPoisson, &ctx, NULL));
2427*2a8381b2SBarry Smith if (ctx.velocity_monitor >= 0) PetscCall(TSMonitorSet(ts, MonitorVelocity, &ctx, NULL));
24288214e71cSJoe
24298214e71cSJoe PetscCall(TSSetFromOptions(ts));
24308214e71cSJoe PetscCall(TSGetTimeStep(ts, &dt));
24318214e71cSJoe PetscCall(TSGetMaxSteps(ts, &maxn));
2432*2a8381b2SBarry Smith ctx.steps = maxn;
2433*2a8381b2SBarry Smith ctx.stepSize = dt;
2434*2a8381b2SBarry Smith PetscCall(SetupContext(dm, sw, &ctx));
24358214e71cSJoe PetscCall(TSSetComputeInitialCondition(ts, InitializeSolve));
24368214e71cSJoe PetscCall(TSSetPostStep(ts, MigrateParticles));
24378214e71cSJoe PetscCall(CreateSolution(ts));
24388214e71cSJoe PetscCall(TSGetSolution(ts, &u));
24398214e71cSJoe PetscCall(TSComputeInitialCondition(ts, u));
2440*2a8381b2SBarry Smith PetscCall(CheckNonNegativeWeights(sw, &ctx));
24418214e71cSJoe PetscCall(TSSolve(ts, NULL));
24428214e71cSJoe
2443*2a8381b2SBarry Smith PetscCall(SNESDestroy(&ctx.snes));
2444*2a8381b2SBarry Smith PetscCall(DMDestroy(&ctx.dmPot));
2445*2a8381b2SBarry Smith PetscCall(ISDestroy(&ctx.isPot));
2446*2a8381b2SBarry Smith PetscCall(MatDestroy(&ctx.M));
2447*2a8381b2SBarry Smith PetscCall(PetscFEGeomDestroy(&ctx.fegeom));
24489566063dSJacob Faibussowitsch PetscCall(TSDestroy(&ts));
24499566063dSJacob Faibussowitsch PetscCall(DMDestroy(&sw));
24509566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dm));
2451*2a8381b2SBarry Smith PetscCall(DestroyContext(&ctx));
24529566063dSJacob Faibussowitsch PetscCall(PetscFinalize());
2453b122ec5aSJacob Faibussowitsch return 0;
2454b80bf5b1SJoe Pusztay }
2455b80bf5b1SJoe Pusztay
2456b80bf5b1SJoe Pusztay /*TEST
2457b80bf5b1SJoe Pusztay
2458b80bf5b1SJoe Pusztay build:
24598214e71cSJoe requires: !complex double
24608214e71cSJoe
24618214e71cSJoe # This tests that we can put particles in a box and compute the Coulomb force
24628214e71cSJoe # Recommend -draw_size 500,500
24638214e71cSJoe testset:
24648214e71cSJoe requires: defined(PETSC_HAVE_EXECUTABLE_EXPORT)
2465045208b8SMatthew G. Knepley args: -dm_plex_dim 1 -dm_plex_simplex 0 -dm_plex_box_faces 20 \
2466045208b8SMatthew G. Knepley -dm_plex_box_lower 0 -dm_plex_box_upper 12.5664 -dm_plex_box_bd periodic \
24679072cb8bSMatthew G. Knepley -vdm_plex_simplex 0 \
24688214e71cSJoe -dm_swarm_coordinate_density constant -dm_swarm_num_particles 100 \
24698214e71cSJoe -sigma 1.0e-8 -timeScale 2.0e-14 \
24708214e71cSJoe -ts_type basicsymplectic -ts_basicsymplectic_type 1 \
24718214e71cSJoe -output_step 50 -check_vel_res
24728214e71cSJoe test:
24738214e71cSJoe suffix: none_1d
24749072cb8bSMatthew G. Knepley requires:
24758214e71cSJoe args: -em_type none -error
24768214e71cSJoe test:
24778214e71cSJoe suffix: coulomb_1d
24788214e71cSJoe args: -em_type coulomb
24798214e71cSJoe
24808214e71cSJoe # for viewers
24818214e71cSJoe #-ts_monitor_sp_swarm_phase -ts_monitor_sp_swarm -em_snes_monitor -ts_monitor_sp_swarm_multi_species 0 -ts_monitor_sp_swarm_retain 0
24828214e71cSJoe testset:
24838214e71cSJoe nsize: {{1 2}}
24848214e71cSJoe requires: defined(PETSC_HAVE_EXECUTABLE_EXPORT)
2485045208b8SMatthew G. Knepley args: -dm_plex_dim 1 -dm_plex_simplex 0 -dm_plex_box_faces 36 \
2486045208b8SMatthew G. Knepley -dm_plex_box_lower 0. -dm_plex_box_upper 12.5664 -dm_plex_box_bd periodic \
24878214e71cSJoe -vdm_plex_dim 1 -vdm_plex_simplex 0 -vdm_plex_box_faces 10 \
24888214e71cSJoe -vdm_plex_box_lower -3 -vdm_plex_box_upper 3 \
248984467f86SMatthew G. Knepley -dm_swarm_num_species 1 -twostream -charges -1.,1. -sigma 1.0e-8 \
24908214e71cSJoe -cosine_coefficients 0.01,0.5 -perturbed_weights -total_weight 1. \
24918214e71cSJoe -ts_type basicsymplectic -ts_basicsymplectic_type 2 \
2492188af4bfSBarry Smith -ts_time_step 0.01 -ts_max_time 5 -ts_max_steps 10 \
24938214e71cSJoe -em_snes_atol 1.e-15 -em_snes_error_if_not_converged -em_ksp_error_if_not_converged \
249484467f86SMatthew G. Knepley -output_step 1 -check_vel_res -dm_swarm_print_coords 1 -dm_swarm_print_weights 1
24958214e71cSJoe test:
24968214e71cSJoe suffix: two_stream_c0
24978214e71cSJoe args: -em_type primal -petscfe_default_quadrature_order 2 -petscspace_degree 2 -em_pc_type svd
24988214e71cSJoe test:
24998214e71cSJoe suffix: two_stream_rt
25008214e71cSJoe requires: superlu_dist
25018214e71cSJoe args: -em_type mixed \
25028214e71cSJoe -potential_petscspace_degree 0 \
25038214e71cSJoe -potential_petscdualspace_lagrange_use_moments \
25048214e71cSJoe -potential_petscdualspace_lagrange_moment_order 2 \
2505045208b8SMatthew G. Knepley -field_petscspace_degree 1 -field_petscfe_default_quadrature_order 1 \
25068214e71cSJoe -em_snes_error_if_not_converged \
25078214e71cSJoe -em_ksp_type preonly -em_ksp_error_if_not_converged \
25088214e71cSJoe -em_pc_type fieldsplit -em_pc_fieldsplit_type schur \
25098214e71cSJoe -em_pc_fieldsplit_schur_fact_type full -em_pc_fieldsplit_schur_precondition full \
25108214e71cSJoe -em_fieldsplit_field_pc_type lu \
25118214e71cSJoe -em_fieldsplit_field_pc_factor_mat_solver_type superlu_dist \
25128214e71cSJoe -em_fieldsplit_potential_pc_type svd
25138214e71cSJoe
251484467f86SMatthew G. Knepley # For an eyeball check, we use
25159072cb8bSMatthew G. Knepley # -ts_max_steps 1000 -dm_plex_box_faces 10,1 -vdm_plex_box_faces 2000 -efield_monitor
25168214e71cSJoe # For verification, we use
251784467f86SMatthew G. Knepley # -ts_max_steps 1000 -dm_plex_box_faces 100,1 -vdm_plex_box_faces 8000 -dm_swarm_num_particles 800000 -monitor_efield
25188214e71cSJoe # -ts_monitor_sp_swarm_multi_species 0 -ts_monitor_sp_swarm_retain 0 -ts_monitor_sp_swarm_phase 1 -draw_size 500,500
25198214e71cSJoe testset:
25208214e71cSJoe nsize: {{1 2}}
2521045208b8SMatthew G. Knepley args: -dm_plex_dim 1 -dm_plex_simplex 0 -dm_plex_box_faces 10 \
2522045208b8SMatthew G. Knepley -dm_plex_box_lower 0. -dm_plex_box_upper 12.5664 -dm_plex_box_bd periodic \
25238214e71cSJoe -vdm_plex_dim 1 -vdm_plex_simplex 0 -vdm_plex_box_faces 10 \
25248214e71cSJoe -vdm_plex_box_lower -10 -vdm_plex_box_upper 10 \
2525f1e6e573SMatthew G. Knepley -vpetscspace_degree 2 -vdm_plex_hash_location \
252684467f86SMatthew G. Knepley -dm_swarm_num_species 1 -charges -1.,1. \
25278214e71cSJoe -cosine_coefficients 0.01,0.5 -perturbed_weights -total_weight 1. \
25288214e71cSJoe -ts_type basicsymplectic -ts_basicsymplectic_type 1 \
2529188af4bfSBarry Smith -ts_time_step 0.03 -ts_max_time 500 -ts_max_steps 1 \
25308214e71cSJoe -em_snes_atol 1.e-12 -em_snes_error_if_not_converged -em_ksp_error_if_not_converged \
253184467f86SMatthew G. Knepley -output_step 1 -check_vel_res -dm_swarm_print_coords 1 -dm_swarm_print_weights 1
25328214e71cSJoe
25338214e71cSJoe test:
25348214e71cSJoe suffix: uniform_equilibrium_1d
25358214e71cSJoe args: -cosine_coefficients 0.0,0.5 -em_type primal -petscspace_degree 1 -em_pc_type svd
25368214e71cSJoe test:
253775155f48SMatthew G. Knepley suffix: uniform_equilibrium_1d_real
2538045208b8SMatthew G. Knepley args: -dm_plex_dim 1 -dm_plex_simplex 1 -dm_plex_box_faces 10 \
253975155f48SMatthew G. Knepley -dm_plex_box_lower 0. -dm_plex_box_upper 12.5664 -dm_plex_box_bd periodic \
254075155f48SMatthew G. Knepley -cosine_coefficients 0.0 -em_type primal -petscspace_degree 1 -em_pc_type svd
254175155f48SMatthew G. Knepley test:
2542f940b0e3Sdanofinn suffix: landau_damping_1d_c0
25438214e71cSJoe args: -em_type primal -petscspace_degree 1 -em_pc_type svd
25448214e71cSJoe test:
254575155f48SMatthew G. Knepley suffix: uniform_primal_1d_real
2546045208b8SMatthew G. Knepley args: -dm_plex_dim 1 -dm_plex_simplex 1 -dm_plex_box_faces 10 \
254775155f48SMatthew G. Knepley -dm_plex_box_lower 0. -dm_plex_box_upper 12.5664 -dm_plex_box_bd periodic \
254875155f48SMatthew G. Knepley -cosine_coefficients 0.01 -em_type primal -petscspace_degree 1 -em_pc_type svd
25499072cb8bSMatthew G. Knepley # NOT WORKING -ftop_pc_type bjacobi -ftop_sub_pc_type lu -ftop_sub_pc_factor_shift_type nonzero
25509072cb8bSMatthew G. Knepley test:
25519072cb8bSMatthew G. Knepley suffix: uniform_primal_1d_real_pfak
25529072cb8bSMatthew G. Knepley nsize: 1
2553045208b8SMatthew G. Knepley args: -dm_plex_dim 1 -dm_plex_simplex 1 -dm_plex_box_faces 10 \
25549072cb8bSMatthew G. Knepley -dm_plex_box_lower 0. -dm_plex_box_upper 12.5664 -dm_plex_box_bd periodic \
25559072cb8bSMatthew G. Knepley -remap_dm_plex_dim 2 -remap_dm_plex_simplex 0 -remap_dm_plex_box_faces 10,10 -remap_dm_plex_box_bd periodic,none \
25569072cb8bSMatthew G. Knepley -remap_dm_plex_box_lower 0.,-10. -remap_dm_plex_box_upper 12.5664,10. \
25579072cb8bSMatthew G. Knepley -remap_petscspace_degree 2 -remap_dm_plex_hash_location \
2558045208b8SMatthew G. Knepley -remap_freq 1 -dm_swarm_remap_type pfak \
25599072cb8bSMatthew G. Knepley -ftop_ksp_type lsqr -ftop_pc_type none -ftop_ksp_rtol 1.e-14 \
25609072cb8bSMatthew G. Knepley -ptof_pc_type lu \
25619072cb8bSMatthew G. Knepley -cosine_coefficients 0.01 -em_type primal -petscspace_degree 1 -em_pc_type svd -em_proj_pc_type lu
256275155f48SMatthew G. Knepley test:
25638214e71cSJoe requires: superlu_dist
2564f940b0e3Sdanofinn suffix: landau_damping_1d_mixed
25658214e71cSJoe args: -em_type mixed \
25668214e71cSJoe -potential_petscspace_degree 0 \
25678214e71cSJoe -potential_petscdualspace_lagrange_use_moments \
25688214e71cSJoe -potential_petscdualspace_lagrange_moment_order 2 \
2569045208b8SMatthew G. Knepley -field_petscspace_degree 1 \
25708214e71cSJoe -em_snes_error_if_not_converged \
25718214e71cSJoe -em_ksp_type preonly -em_ksp_error_if_not_converged \
25728214e71cSJoe -em_pc_type fieldsplit -em_pc_fieldsplit_type schur \
25738214e71cSJoe -em_pc_fieldsplit_schur_fact_type full -em_pc_fieldsplit_schur_precondition full \
25748214e71cSJoe -em_fieldsplit_field_pc_type lu \
25758214e71cSJoe -em_fieldsplit_field_pc_factor_mat_solver_type superlu_dist \
25768214e71cSJoe -em_fieldsplit_potential_pc_type svd
25778214e71cSJoe
2578f940b0e3Sdanofinn # Same as above, with different timestepping
2579f940b0e3Sdanofinn testset:
2580f940b0e3Sdanofinn nsize: {{1 2}}
2581f940b0e3Sdanofinn args: -dm_plex_dim 1 -dm_plex_simplex 0 -dm_plex_box_faces 10 \
2582f940b0e3Sdanofinn -dm_plex_box_lower 0. -dm_plex_box_upper 12.5664 -dm_plex_box_bd periodic \
2583f940b0e3Sdanofinn -vdm_plex_dim 1 -vdm_plex_simplex 0 -vdm_plex_box_faces 10 \
2584f940b0e3Sdanofinn -vdm_plex_box_lower -10 -vdm_plex_box_upper 10 \
2585f940b0e3Sdanofinn -vpetscspace_degree 2 -vdm_plex_hash_location \
2586f940b0e3Sdanofinn -dm_swarm_num_species 1 -charges -1.,1. \
2587f940b0e3Sdanofinn -cosine_coefficients 0.01,0.5 -perturbed_weights -total_weight 1. \
2588f940b0e3Sdanofinn -ts_type discgrad -ts_discgrad_type average \
2589188af4bfSBarry Smith -ts_time_step 0.03 -ts_max_time 500 -ts_max_steps 1 \
2590f940b0e3Sdanofinn -snes_type qn \
2591f940b0e3Sdanofinn -em_snes_atol 1.e-12 -em_snes_error_if_not_converged -em_ksp_error_if_not_converged \
2592f940b0e3Sdanofinn -output_step 1 -check_vel_res -dm_swarm_print_coords 1 -dm_swarm_print_weights 1
2593f940b0e3Sdanofinn
2594f940b0e3Sdanofinn test:
2595f940b0e3Sdanofinn suffix: landau_damping_1d_dg
2596f940b0e3Sdanofinn args: -em_type primal -petscspace_degree 1 -em_pc_type svd
2597f940b0e3Sdanofinn
2598b80bf5b1SJoe Pusztay TEST*/
2599