1918dfc20SMatthew G. Knepley static char help[] = "Two-level system for Landau Damping using Vlasov-Poisson equations\n";
2918dfc20SMatthew G. Knepley
3918dfc20SMatthew G. Knepley /*
4918dfc20SMatthew G. Knepley Moment Equations:
5918dfc20SMatthew G. Knepley
6918dfc20SMatthew G. Knepley We will discretize the moment equations using finite elements, and we will project the moments into the finite element space We will use the PFAK method, which guarantees that our FE approximation is weakly equivalent to the true moment. The first moment, number density, is given by
7918dfc20SMatthew G. Knepley
8918dfc20SMatthew G. Knepley \int dx \phi_i n_f = \int dx \phi_i n_p
9918dfc20SMatthew G. Knepley \int dx \phi_i n_f = \int dx \phi_i \int dv f
10918dfc20SMatthew G. Knepley \int dx \phi_i n_f = \int dx \phi_i \int dv \sum_p w_p \delta(x - x_p) \delta(v - v_p)
11918dfc20SMatthew G. Knepley \int dx \phi_i n_f = \int dx \phi_i \sum_p w_p \delta(x - x_p)
12918dfc20SMatthew G. Knepley M n_F = M_p w_p
13918dfc20SMatthew G. Knepley
14918dfc20SMatthew G. Knepley where
15918dfc20SMatthew G. Knepley
16918dfc20SMatthew G. Knepley (M_p){ip} = \phi_i(x_p)
17918dfc20SMatthew G. Knepley
18918dfc20SMatthew G. Knepley which is just a scaled version of the charge density. The second moment, momentum density, is given by
19918dfc20SMatthew G. Knepley
20918dfc20SMatthew G. Knepley \int dx \phi_i p_f = m \int dx \phi_i \int dv v f
21918dfc20SMatthew G. Knepley \int dx \phi_i p_f = m \int dx \phi_i \sum_p w_p \delta(x - x_p) v_p
22918dfc20SMatthew G. Knepley M p_F = M_p v_p w_p
23918dfc20SMatthew G. Knepley
24918dfc20SMatthew G. Knepley And finally the third moment, pressure, is given by
25918dfc20SMatthew G. Knepley
26918dfc20SMatthew G. Knepley \int dx \phi_i pr_f = m \int dx \phi_i \int dv (v - u)^2 f
27918dfc20SMatthew G. Knepley \int dx \phi_i pr_f = m \int dx \phi_i \sum_p w_p \delta(x - x_p) (v_p - u)^2
28918dfc20SMatthew G. Knepley M pr_F = M_p (v_p - u)^2 w_p
29918dfc20SMatthew G. Knepley = M_p (v_p - p_F(x_p) / m n_F(x_p))^2 w_p
30918dfc20SMatthew G. Knepley = M_p (v_p - (\sum_j p_F \phi_j(x_p)) / m (\sum_k n_F \phi_k(x_p)))^2 w_p
31918dfc20SMatthew G. Knepley
32918dfc20SMatthew G. Knepley Here we need all FEM basis functions \phi_i that see that particle p.
33918dfc20SMatthew G. Knepley
34918dfc20SMatthew G. Knepley 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"
35918dfc20SMatthew G. Knepley According to Lukas, good damping results come at ~16k particles per cell
36918dfc20SMatthew G. Knepley
37918dfc20SMatthew G. Knepley Swarm CellDMs
38918dfc20SMatthew G. Knepley =============
39918dfc20SMatthew G. Knepley Name: "space"
40918dfc20SMatthew G. Knepley Fields: DMSwarmPICField_coor, "velocity"
41918dfc20SMatthew G. Knepley Coordinates: DMSwarmPICField_coor
42918dfc20SMatthew G. Knepley
43918dfc20SMatthew G. Knepley Name: "velocity"
44918dfc20SMatthew G. Knepley Fields: "w_q"
45918dfc20SMatthew G. Knepley Coordinates: "velocity"
46918dfc20SMatthew G. Knepley
47918dfc20SMatthew G. Knepley Name: "moments"
48918dfc20SMatthew G. Knepley Fields: "w_q"
49918dfc20SMatthew G. Knepley Coordinates: DMSwarmPICField_coor
50918dfc20SMatthew G. Knepley
51918dfc20SMatthew G. Knepley Name: "moment fields"
52918dfc20SMatthew G. Knepley Fields: "velocity"
53918dfc20SMatthew G. Knepley Coordinates: DMSwarmPICField_coor
54918dfc20SMatthew G. Knepley
55918dfc20SMatthew G. Knepley To visualize the maximum electric field use
56918dfc20SMatthew G. Knepley
57918dfc20SMatthew G. Knepley -efield_monitor
58918dfc20SMatthew G. Knepley
59918dfc20SMatthew G. Knepley To monitor velocity moments of the distribution use
60918dfc20SMatthew G. Knepley
61918dfc20SMatthew G. Knepley -ptof_pc_type lu -moments_monitor
62918dfc20SMatthew G. Knepley
63918dfc20SMatthew G. Knepley To monitor the particle positions in phase space use
64918dfc20SMatthew G. Knepley
65918dfc20SMatthew G. Knepley -positions_monitor
66918dfc20SMatthew G. Knepley
67918dfc20SMatthew G. Knepley To monitor the charge density, E field, and potential use
68918dfc20SMatthew G. Knepley
69918dfc20SMatthew G. Knepley -poisson_monitor
70918dfc20SMatthew G. Knepley
71918dfc20SMatthew G. Knepley To monitor the remapping field use
72918dfc20SMatthew G. Knepley
73918dfc20SMatthew G. Knepley -remap_uf_view draw
74918dfc20SMatthew G. Knepley
75918dfc20SMatthew G. Knepley To visualize the swarm distribution use
76918dfc20SMatthew G. Knepley
77918dfc20SMatthew G. Knepley -ts_monitor_hg_swarm
78918dfc20SMatthew G. Knepley
79918dfc20SMatthew G. Knepley To visualize the particles, we can use
80918dfc20SMatthew G. Knepley
81918dfc20SMatthew G. Knepley -ts_monitor_sp_swarm -ts_monitor_sp_swarm_retain 0 -ts_monitor_sp_swarm_phase 1 -draw_size 500,500
82918dfc20SMatthew G. Knepley */
83918dfc20SMatthew G. Knepley #include <petsctao.h>
84918dfc20SMatthew G. Knepley #include <petscts.h>
85918dfc20SMatthew G. Knepley #include <petscdmplex.h>
86918dfc20SMatthew G. Knepley #include <petscdmswarm.h>
87918dfc20SMatthew G. Knepley #include <petscfe.h>
88918dfc20SMatthew G. Knepley #include <petscds.h>
89918dfc20SMatthew G. Knepley #include <petscbag.h>
90918dfc20SMatthew G. Knepley #include <petscdraw.h>
91918dfc20SMatthew G. Knepley #include <petsc/private/petscfeimpl.h> /* For interpolation */
92918dfc20SMatthew G. Knepley #include <petsc/private/dmswarmimpl.h> /* For swarm debugging */
93918dfc20SMatthew G. Knepley #include "petscdm.h"
94918dfc20SMatthew G. Knepley #include "petscdmlabel.h"
95918dfc20SMatthew G. Knepley
96918dfc20SMatthew G. Knepley PETSC_EXTERN PetscErrorCode stream(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
97918dfc20SMatthew G. Knepley PETSC_EXTERN PetscErrorCode line(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
98918dfc20SMatthew G. Knepley
99918dfc20SMatthew G. Knepley const char *EMTypes[] = {"primal", "mixed", "coulomb", "none", "EMType", "EM_", NULL};
100918dfc20SMatthew G. Knepley typedef enum {
101f14fce1bSMatthew G. Knepley EM_PRIMAL,
102918dfc20SMatthew G. Knepley EM_MIXED,
103918dfc20SMatthew G. Knepley EM_COULOMB,
104f14fce1bSMatthew G. Knepley EM_NONE
105918dfc20SMatthew G. Knepley } EMType;
106918dfc20SMatthew G. Knepley
107918dfc20SMatthew G. Knepley typedef enum {
108918dfc20SMatthew G. Knepley V0,
109918dfc20SMatthew G. Knepley X0,
110918dfc20SMatthew G. Knepley T0,
111918dfc20SMatthew G. Knepley M0,
112918dfc20SMatthew G. Knepley Q0,
113918dfc20SMatthew G. Knepley PHI0,
114918dfc20SMatthew G. Knepley POISSON,
115918dfc20SMatthew G. Knepley VLASOV,
116918dfc20SMatthew G. Knepley SIGMA,
117918dfc20SMatthew G. Knepley NUM_CONSTANTS
118918dfc20SMatthew G. Knepley } ConstantType;
119918dfc20SMatthew G. Knepley
120918dfc20SMatthew G. Knepley typedef enum {
121918dfc20SMatthew G. Knepley E_MONITOR_NONE,
122918dfc20SMatthew G. Knepley E_MONITOR_FULL,
123918dfc20SMatthew G. Knepley E_MONITOR_QUIET
124918dfc20SMatthew G. Knepley } EMonitorType;
125918dfc20SMatthew G. Knepley const char *const EMonitorTypes[] = {"NONE", "FULL", "QUIET", "EMonitorType", "E_MONITOR_", NULL};
126918dfc20SMatthew G. Knepley
127918dfc20SMatthew G. Knepley typedef struct {
128918dfc20SMatthew G. Knepley PetscScalar v0; /* Velocity scale, often the thermal velocity */
129918dfc20SMatthew G. Knepley PetscScalar t0; /* Time scale */
130918dfc20SMatthew G. Knepley PetscScalar x0; /* Space scale */
131918dfc20SMatthew G. Knepley PetscScalar m0; /* Mass scale */
132918dfc20SMatthew G. Knepley PetscScalar q0; /* Charge scale */
133918dfc20SMatthew G. Knepley PetscScalar kb;
134918dfc20SMatthew G. Knepley PetscScalar epsi0;
135918dfc20SMatthew G. Knepley PetscScalar phi0; /* Potential scale */
136918dfc20SMatthew G. Knepley PetscScalar poissonNumber; /* Non-Dimensional Poisson Number */
137918dfc20SMatthew G. Knepley PetscScalar vlasovNumber; /* Non-Dimensional Vlasov Number */
138918dfc20SMatthew G. Knepley PetscReal sigma; /* Nondimensional charge per length in x */
139918dfc20SMatthew G. Knepley } Parameter;
140918dfc20SMatthew G. Knepley
141918dfc20SMatthew G. Knepley typedef struct {
142f940b0e3Sdanofinn PetscInt s; // Starting sample (we ignore some in the beginning)
143f940b0e3Sdanofinn PetscInt e; // Ending sample
144f940b0e3Sdanofinn PetscInt per; // Period of fitting
145f940b0e3Sdanofinn const PetscReal *t; // Time for each sample
146f940b0e3Sdanofinn const PetscReal *Emax; // Emax for each sample
147f940b0e3Sdanofinn } EmaxCtx;
148f940b0e3Sdanofinn
149f940b0e3Sdanofinn typedef struct {
150918dfc20SMatthew G. Knepley PetscBag bag; // Problem parameters
151918dfc20SMatthew G. Knepley PetscBool error; // Flag for printing the error
152918dfc20SMatthew G. Knepley PetscInt remapFreq; // Number of timesteps between remapping
153918dfc20SMatthew G. Knepley EMonitorType efield_monitor; // Flag to show electric field monitor
154918dfc20SMatthew G. Knepley PetscBool moment_monitor; // Flag to show distribution moment monitor
155918dfc20SMatthew G. Knepley PetscBool moment_field_monitor; // Flag to show moment field monitor
156918dfc20SMatthew G. Knepley PetscBool positions_monitor; // Flag to show particle positins at each time step
157918dfc20SMatthew G. Knepley PetscBool poisson_monitor; // Flag to display charge, E field, and potential at each solve
158918dfc20SMatthew G. Knepley PetscBool initial_monitor; // Flag to monitor the initial conditions
159918dfc20SMatthew G. Knepley PetscInt velocity_monitor; // Cell to monitor the velocity distribution for
160918dfc20SMatthew G. Knepley PetscBool perturbed_weights; // Uniformly sample x,v space with gaussian weights
161918dfc20SMatthew G. Knepley PetscInt ostep; // Print the energy at each ostep time steps
162918dfc20SMatthew G. Knepley PetscInt numParticles;
163918dfc20SMatthew G. Knepley PetscReal timeScale; /* Nondimensionalizing time scale */
164918dfc20SMatthew G. Knepley PetscReal charges[2]; /* The charges of each species */
165918dfc20SMatthew G. Knepley PetscReal masses[2]; /* The masses of each species */
166918dfc20SMatthew G. Knepley PetscReal thermal_energy[2]; /* Thermal Energy (used to get other constants)*/
167918dfc20SMatthew G. Knepley PetscReal cosine_coefficients[2]; /*(alpha, k)*/
168918dfc20SMatthew G. Knepley PetscReal totalWeight;
169918dfc20SMatthew G. Knepley PetscReal stepSize;
170918dfc20SMatthew G. Knepley PetscInt steps;
171918dfc20SMatthew G. Knepley PetscReal initVel;
172918dfc20SMatthew G. Knepley EMType em; // Type of electrostatic model
173918dfc20SMatthew G. Knepley SNES snes; // EM solver
174918dfc20SMatthew G. Knepley DM dmMom; // The DM for moment fields
175918dfc20SMatthew G. Knepley DM dmN; // The DM for number density fields
176918dfc20SMatthew G. Knepley IS isN; // The IS mapping dmN into dmMom
177918dfc20SMatthew G. Knepley Mat MN; // The finite element mass matrix for number density
178918dfc20SMatthew G. Knepley DM dmP; // The DM for momentum density fields
179918dfc20SMatthew G. Knepley IS isP; // The IS mapping dmP into dmMom
180918dfc20SMatthew G. Knepley Mat MP; // The finite element mass matrix for momentum density
181918dfc20SMatthew G. Knepley DM dmE; // The DM for energy density (pressure) fields
182918dfc20SMatthew G. Knepley IS isE; // The IS mapping dmE into dmMom
183918dfc20SMatthew G. Knepley Mat ME; // The finite element mass matrix for energy density (pressure)
184918dfc20SMatthew G. Knepley DM dmPot; // The DM for potential
185918dfc20SMatthew G. Knepley Mat fftPot; // Fourier Transform operator for the potential
186918dfc20SMatthew G. Knepley Vec fftX, fftY; // FFT vectors with phases added (complex parts)
187918dfc20SMatthew G. Knepley IS fftReal; // The indices for real parts
188918dfc20SMatthew G. Knepley IS isPot; // The IS for potential, or NULL in primal
189918dfc20SMatthew G. Knepley Mat M; // The finite element mass matrix for potential
190918dfc20SMatthew G. Knepley PetscFEGeom *fegeom; // Geometric information for the DM cells
191918dfc20SMatthew G. Knepley PetscDrawHG drawhgic_x; // Histogram of the particle weight in each X cell
192918dfc20SMatthew G. Knepley PetscDrawHG drawhgic_v; // Histogram of the particle weight in each X cell
193918dfc20SMatthew G. Knepley PetscDrawHG drawhgcell_v; // Histogram of the particle weight in a given cell
194918dfc20SMatthew G. Knepley PetscBool validE; // Flag to indicate E-field in swarm is valid
195918dfc20SMatthew G. Knepley PetscReal drawlgEmin; // The minimum lg(E) to plot
196918dfc20SMatthew G. Knepley PetscDrawLG drawlgE; // Logarithm of maximum electric field
197918dfc20SMatthew G. Knepley PetscDrawSP drawspE; // Electric field at particle positions
198918dfc20SMatthew G. Knepley PetscDrawSP drawspX; // Particle positions
199918dfc20SMatthew G. Knepley PetscViewer viewerRho; // Charge density viewer
200918dfc20SMatthew G. Knepley PetscViewer viewerRhoHat; // Charge density Fourier Transform viewer
201918dfc20SMatthew G. Knepley PetscViewer viewerPhi; // Potential viewer
202918dfc20SMatthew G. Knepley PetscViewer viewerN; // Number density viewer
203918dfc20SMatthew G. Knepley PetscViewer viewerP; // Momentum density viewer
204918dfc20SMatthew G. Knepley PetscViewer viewerE; // Energy density (pressure) viewer
205f14fce1bSMatthew G. Knepley PetscViewer viewerNRes; // Number density residual viewer
206f14fce1bSMatthew G. Knepley PetscViewer viewerPRes; // Momentum density residual viewer
207f14fce1bSMatthew G. Knepley PetscViewer viewerERes; // Energy density (pressure) residual viewer
208f14fce1bSMatthew G. Knepley PetscDrawLG drawlgMomRes; // Residuals for the moment equations
209918dfc20SMatthew G. Knepley DM swarm; // The particle swarm
210918dfc20SMatthew G. Knepley PetscRandom random; // Used for particle perturbations
211918dfc20SMatthew G. Knepley PetscBool twostream; // Flag for activating 2-stream setup
212918dfc20SMatthew G. Knepley PetscBool checkweights; // Check weight normalization
213918dfc20SMatthew G. Knepley PetscInt checkVRes; // Flag to check/output velocity residuals for nightly tests
214918dfc20SMatthew G. Knepley PetscBool checkLandau; // Check the Landau damping result
215f940b0e3Sdanofinn EmaxCtx emaxCtx; // Information for fit to decay profile
216918dfc20SMatthew G. Knepley PetscReal gamma; // The damping rate for Landau damping
217918dfc20SMatthew G. Knepley PetscReal omega; // The perturbed oscillation frequency for Landau damping
218918dfc20SMatthew G. Knepley
219918dfc20SMatthew G. Knepley PetscLogEvent RhsXEvent, RhsVEvent, ESolveEvent, ETabEvent;
220918dfc20SMatthew G. Knepley } AppCtx;
221918dfc20SMatthew G. Knepley
ProcessOptions(MPI_Comm comm,AppCtx * options)222918dfc20SMatthew G. Knepley static PetscErrorCode ProcessOptions(MPI_Comm comm, AppCtx *options)
223918dfc20SMatthew G. Knepley {
224918dfc20SMatthew G. Knepley PetscFunctionBeginUser;
225918dfc20SMatthew G. Knepley PetscInt d = 2;
226918dfc20SMatthew G. Knepley PetscInt maxSpecies = 2;
227918dfc20SMatthew G. Knepley options->error = PETSC_FALSE;
228918dfc20SMatthew G. Knepley options->remapFreq = 1;
229918dfc20SMatthew G. Knepley options->efield_monitor = E_MONITOR_NONE;
230918dfc20SMatthew G. Knepley options->moment_monitor = PETSC_FALSE;
231918dfc20SMatthew G. Knepley options->moment_field_monitor = PETSC_FALSE;
232918dfc20SMatthew G. Knepley options->initial_monitor = PETSC_FALSE;
233918dfc20SMatthew G. Knepley options->perturbed_weights = PETSC_FALSE;
234918dfc20SMatthew G. Knepley options->poisson_monitor = PETSC_FALSE;
235918dfc20SMatthew G. Knepley options->positions_monitor = PETSC_FALSE;
236918dfc20SMatthew G. Knepley options->velocity_monitor = -1;
237918dfc20SMatthew G. Knepley options->ostep = 100;
238918dfc20SMatthew G. Knepley options->timeScale = 2.0e-14;
239918dfc20SMatthew G. Knepley options->charges[0] = -1.0;
240918dfc20SMatthew G. Knepley options->charges[1] = 1.0;
241918dfc20SMatthew G. Knepley options->masses[0] = 1.0;
242918dfc20SMatthew G. Knepley options->masses[1] = 1000.0;
243918dfc20SMatthew G. Knepley options->thermal_energy[0] = 1.0;
244918dfc20SMatthew G. Knepley options->thermal_energy[1] = 1.0;
245918dfc20SMatthew G. Knepley options->cosine_coefficients[0] = 0.01;
246918dfc20SMatthew G. Knepley options->cosine_coefficients[1] = 0.5;
247918dfc20SMatthew G. Knepley options->initVel = 1;
248918dfc20SMatthew G. Knepley options->totalWeight = 1.0;
249918dfc20SMatthew G. Knepley options->drawhgic_x = NULL;
250918dfc20SMatthew G. Knepley options->drawhgic_v = NULL;
251918dfc20SMatthew G. Knepley options->drawhgcell_v = NULL;
252f940b0e3Sdanofinn options->validE = PETSC_FALSE;
253918dfc20SMatthew G. Knepley options->drawlgEmin = -6;
254918dfc20SMatthew G. Knepley options->drawlgE = NULL;
255918dfc20SMatthew G. Knepley options->drawspE = NULL;
256918dfc20SMatthew G. Knepley options->drawspX = NULL;
257918dfc20SMatthew G. Knepley options->viewerRho = NULL;
258918dfc20SMatthew G. Knepley options->viewerRhoHat = NULL;
259918dfc20SMatthew G. Knepley options->viewerPhi = NULL;
260918dfc20SMatthew G. Knepley options->viewerN = NULL;
261918dfc20SMatthew G. Knepley options->viewerP = NULL;
262918dfc20SMatthew G. Knepley options->viewerE = NULL;
263f14fce1bSMatthew G. Knepley options->viewerNRes = NULL;
264f14fce1bSMatthew G. Knepley options->viewerPRes = NULL;
265f14fce1bSMatthew G. Knepley options->viewerERes = NULL;
266f14fce1bSMatthew G. Knepley options->drawlgMomRes = NULL;
267918dfc20SMatthew G. Knepley options->em = EM_COULOMB;
268918dfc20SMatthew G. Knepley options->snes = NULL;
269918dfc20SMatthew G. Knepley options->dmMom = NULL;
270918dfc20SMatthew G. Knepley options->dmN = NULL;
271918dfc20SMatthew G. Knepley options->MN = NULL;
272918dfc20SMatthew G. Knepley options->dmP = NULL;
273918dfc20SMatthew G. Knepley options->MP = NULL;
274918dfc20SMatthew G. Knepley options->dmE = NULL;
275918dfc20SMatthew G. Knepley options->ME = NULL;
276918dfc20SMatthew G. Knepley options->dmPot = NULL;
277918dfc20SMatthew G. Knepley options->fftPot = NULL;
278918dfc20SMatthew G. Knepley options->fftX = NULL;
279918dfc20SMatthew G. Knepley options->fftY = NULL;
280918dfc20SMatthew G. Knepley options->fftReal = NULL;
281918dfc20SMatthew G. Knepley options->isPot = NULL;
282918dfc20SMatthew G. Knepley options->M = NULL;
283918dfc20SMatthew G. Knepley options->numParticles = 32768;
284918dfc20SMatthew G. Knepley options->twostream = PETSC_FALSE;
285918dfc20SMatthew G. Knepley options->checkweights = PETSC_FALSE;
286918dfc20SMatthew G. Knepley options->checkVRes = 0;
287918dfc20SMatthew G. Knepley options->checkLandau = PETSC_FALSE;
288f940b0e3Sdanofinn options->emaxCtx.s = 50;
289f940b0e3Sdanofinn options->emaxCtx.per = 100;
290918dfc20SMatthew G. Knepley
291918dfc20SMatthew G. Knepley PetscOptionsBegin(comm, "", "Landau Damping and Two Stream options", "DMSWARM");
292918dfc20SMatthew G. Knepley PetscCall(PetscOptionsBool("-error", "Flag to print the error", __FILE__, options->error, &options->error, NULL));
293918dfc20SMatthew G. Knepley PetscCall(PetscOptionsInt("-remap_freq", "Number", __FILE__, options->remapFreq, &options->remapFreq, NULL));
294918dfc20SMatthew G. Knepley PetscCall(PetscOptionsEnum("-efield_monitor", "Flag to record and plot log(max E) over time", __FILE__, EMonitorTypes, (PetscEnum)options->efield_monitor, (PetscEnum *)&options->efield_monitor, NULL));
295918dfc20SMatthew G. Knepley PetscCall(PetscOptionsReal("-efield_min_monitor", "Minimum E field to plot", __FILE__, options->drawlgEmin, &options->drawlgEmin, NULL));
296918dfc20SMatthew G. Knepley PetscCall(PetscOptionsBool("-moments_monitor", "Flag to show moments table", __FILE__, options->moment_monitor, &options->moment_monitor, NULL));
297918dfc20SMatthew G. Knepley PetscCall(PetscOptionsBool("-moment_field_monitor", "Flag to show moment fields", __FILE__, options->moment_field_monitor, &options->moment_field_monitor, NULL));
298918dfc20SMatthew G. Knepley PetscCall(PetscOptionsBool("-ics_monitor", "Flag to show initial condition histograms", __FILE__, options->initial_monitor, &options->initial_monitor, NULL));
299918dfc20SMatthew G. Knepley PetscCall(PetscOptionsBool("-positions_monitor", "The flag to show particle positions", __FILE__, options->positions_monitor, &options->positions_monitor, NULL));
300918dfc20SMatthew G. Knepley PetscCall(PetscOptionsBool("-poisson_monitor", "The flag to show charges, Efield and potential solve", __FILE__, options->poisson_monitor, &options->poisson_monitor, NULL));
301918dfc20SMatthew G. Knepley PetscCall(PetscOptionsInt("-velocity_monitor", "Cell to show velocity histograms", __FILE__, options->velocity_monitor, &options->velocity_monitor, NULL));
302918dfc20SMatthew G. Knepley PetscCall(PetscOptionsBool("-twostream", "Run two stream instability", __FILE__, options->twostream, &options->twostream, NULL));
303918dfc20SMatthew G. Knepley PetscCall(PetscOptionsBool("-perturbed_weights", "Flag to run uniform sampling with perturbed weights", __FILE__, options->perturbed_weights, &options->perturbed_weights, NULL));
304918dfc20SMatthew G. Knepley PetscCall(PetscOptionsBool("-check_weights", "Ensure all particle weights are positive", __FILE__, options->checkweights, &options->checkweights, NULL));
305918dfc20SMatthew G. Knepley PetscCall(PetscOptionsBool("-check_landau", "Check the decay from Landau damping", __FILE__, options->checkLandau, &options->checkLandau, NULL));
306918dfc20SMatthew G. Knepley PetscCall(PetscOptionsInt("-output_step", "Number of time steps between output", __FILE__, options->ostep, &options->ostep, NULL));
307918dfc20SMatthew G. Knepley PetscCall(PetscOptionsReal("-timeScale", "Nondimensionalizing time scale", __FILE__, options->timeScale, &options->timeScale, NULL));
308918dfc20SMatthew G. Knepley PetscCall(PetscOptionsInt("-check_vel_res", "Check particle velocity residuals for nightly tests", __FILE__, options->checkVRes, &options->checkVRes, NULL));
309918dfc20SMatthew G. Knepley PetscCall(PetscOptionsReal("-initial_velocity", "Initial velocity of perturbed particle", __FILE__, options->initVel, &options->initVel, NULL));
310918dfc20SMatthew G. Knepley PetscCall(PetscOptionsReal("-total_weight", "Total weight of all particles", __FILE__, options->totalWeight, &options->totalWeight, NULL));
311918dfc20SMatthew G. Knepley PetscCall(PetscOptionsRealArray("-cosine_coefficients", "Amplitude and frequency of cosine equation used in initialization", __FILE__, options->cosine_coefficients, &d, NULL));
312918dfc20SMatthew G. Knepley PetscCall(PetscOptionsRealArray("-charges", "Species charges", __FILE__, options->charges, &maxSpecies, NULL));
313918dfc20SMatthew G. Knepley PetscCall(PetscOptionsEnum("-em_type", "Type of electrostatic solver", __FILE__, EMTypes, (PetscEnum)options->em, (PetscEnum *)&options->em, NULL));
314f940b0e3Sdanofinn PetscCall(PetscOptionsInt("-emax_start_step", "First time step to use for Emax fits", __FILE__, options->emaxCtx.s, &options->emaxCtx.s, NULL));
315f940b0e3Sdanofinn PetscCall(PetscOptionsInt("-emax_solve_step", "Number of time steps between Emax fits", __FILE__, options->emaxCtx.per, &options->emaxCtx.per, NULL));
316918dfc20SMatthew G. Knepley PetscOptionsEnd();
317918dfc20SMatthew G. Knepley
318918dfc20SMatthew G. Knepley PetscCall(PetscLogEventRegister("RhsX", TS_CLASSID, &options->RhsXEvent));
319918dfc20SMatthew G. Knepley PetscCall(PetscLogEventRegister("RhsV", TS_CLASSID, &options->RhsVEvent));
320918dfc20SMatthew G. Knepley PetscCall(PetscLogEventRegister("ESolve", TS_CLASSID, &options->ESolveEvent));
321918dfc20SMatthew G. Knepley PetscCall(PetscLogEventRegister("ETab", TS_CLASSID, &options->ETabEvent));
322918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
323918dfc20SMatthew G. Knepley }
324918dfc20SMatthew G. Knepley
SetupContext(DM dm,DM sw,AppCtx * ctx)325*2a8381b2SBarry Smith static PetscErrorCode SetupContext(DM dm, DM sw, AppCtx *ctx)
326918dfc20SMatthew G. Knepley {
327918dfc20SMatthew G. Knepley MPI_Comm comm;
328918dfc20SMatthew G. Knepley
329918dfc20SMatthew G. Knepley PetscFunctionBeginUser;
330918dfc20SMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
331*2a8381b2SBarry Smith if (ctx->efield_monitor) {
332918dfc20SMatthew G. Knepley PetscDraw draw;
333918dfc20SMatthew G. Knepley PetscDrawAxis axis;
334918dfc20SMatthew G. Knepley
335*2a8381b2SBarry Smith if (ctx->efield_monitor == E_MONITOR_FULL) {
336f14fce1bSMatthew G. Knepley PetscCall(PetscDrawCreate(comm, NULL, "Max Electric Field", 0, 0, 400, 300, &draw));
337918dfc20SMatthew G. Knepley PetscCall(PetscDrawSetSave(draw, "ex2_Efield"));
338918dfc20SMatthew G. Knepley PetscCall(PetscDrawSetFromOptions(draw));
339918dfc20SMatthew G. Knepley } else {
340918dfc20SMatthew G. Knepley PetscCall(PetscDrawOpenNull(comm, &draw));
341918dfc20SMatthew G. Knepley }
342*2a8381b2SBarry Smith PetscCall(PetscDrawLGCreate(draw, 1, &ctx->drawlgE));
343918dfc20SMatthew G. Knepley PetscCall(PetscDrawDestroy(&draw));
344*2a8381b2SBarry Smith PetscCall(PetscDrawLGGetAxis(ctx->drawlgE, &axis));
345918dfc20SMatthew G. Knepley PetscCall(PetscDrawAxisSetLabels(axis, "Max Electric Field", "time", "E_max"));
346*2a8381b2SBarry Smith PetscCall(PetscDrawLGSetLimits(ctx->drawlgE, 0., ctx->steps * ctx->stepSize, ctx->drawlgEmin, 0.));
347918dfc20SMatthew G. Knepley }
348918dfc20SMatthew G. Knepley
349*2a8381b2SBarry Smith if (ctx->initial_monitor) {
350918dfc20SMatthew G. Knepley PetscDraw drawic_x, drawic_v;
351918dfc20SMatthew G. Knepley PetscDrawAxis axis1, axis2;
352918dfc20SMatthew G. Knepley PetscReal dmboxlower[2], dmboxupper[2];
353918dfc20SMatthew G. Knepley PetscInt dim, cStart, cEnd;
354918dfc20SMatthew G. Knepley
355918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim));
356918dfc20SMatthew G. Knepley PetscCall(DMGetBoundingBox(dm, dmboxlower, dmboxupper));
357918dfc20SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
358918dfc20SMatthew G. Knepley
359918dfc20SMatthew G. Knepley PetscCall(PetscDrawCreate(comm, NULL, "monitor_initial_conditions_x", 0, 300, 400, 300, &drawic_x));
360918dfc20SMatthew G. Knepley PetscCall(PetscDrawSetSave(drawic_x, "ex2_ic_x"));
361918dfc20SMatthew G. Knepley PetscCall(PetscDrawSetFromOptions(drawic_x));
362*2a8381b2SBarry Smith PetscCall(PetscDrawHGCreate(drawic_x, (int)dim, &ctx->drawhgic_x));
363*2a8381b2SBarry Smith PetscCall(PetscDrawHGCalcStats(ctx->drawhgic_x, PETSC_TRUE));
364*2a8381b2SBarry Smith PetscCall(PetscDrawHGGetAxis(ctx->drawhgic_x, &axis1));
365*2a8381b2SBarry Smith PetscCall(PetscDrawHGSetNumberBins(ctx->drawhgic_x, (int)(cEnd - cStart)));
366918dfc20SMatthew G. Knepley PetscCall(PetscDrawAxisSetLabels(axis1, "Initial X Distribution", "X", "weight"));
367918dfc20SMatthew G. Knepley PetscCall(PetscDrawAxisSetLimits(axis1, dmboxlower[0], dmboxupper[0], 0, 0));
368918dfc20SMatthew G. Knepley PetscCall(PetscDrawDestroy(&drawic_x));
369918dfc20SMatthew G. Knepley
370918dfc20SMatthew G. Knepley PetscCall(PetscDrawCreate(comm, NULL, "monitor_initial_conditions_v", 400, 300, 400, 300, &drawic_v));
371918dfc20SMatthew G. Knepley PetscCall(PetscDrawSetSave(drawic_v, "ex9_ic_v"));
372918dfc20SMatthew G. Knepley PetscCall(PetscDrawSetFromOptions(drawic_v));
373*2a8381b2SBarry Smith PetscCall(PetscDrawHGCreate(drawic_v, (int)dim, &ctx->drawhgic_v));
374*2a8381b2SBarry Smith PetscCall(PetscDrawHGCalcStats(ctx->drawhgic_v, PETSC_TRUE));
375*2a8381b2SBarry Smith PetscCall(PetscDrawHGGetAxis(ctx->drawhgic_v, &axis2));
376*2a8381b2SBarry Smith PetscCall(PetscDrawHGSetNumberBins(ctx->drawhgic_v, 21));
377918dfc20SMatthew G. Knepley PetscCall(PetscDrawAxisSetLabels(axis2, "Initial V_x Distribution", "V", "weight"));
378918dfc20SMatthew G. Knepley PetscCall(PetscDrawAxisSetLimits(axis2, -6, 6, 0, 0));
379918dfc20SMatthew G. Knepley PetscCall(PetscDrawDestroy(&drawic_v));
380918dfc20SMatthew G. Knepley }
381918dfc20SMatthew G. Knepley
382*2a8381b2SBarry Smith if (ctx->velocity_monitor >= 0) {
383918dfc20SMatthew G. Knepley DM vdm;
384918dfc20SMatthew G. Knepley DMSwarmCellDM celldm;
385918dfc20SMatthew G. Knepley PetscDraw drawcell_v;
386918dfc20SMatthew G. Knepley PetscDrawAxis axis;
387918dfc20SMatthew G. Knepley PetscReal dmboxlower[2], dmboxupper[2];
388918dfc20SMatthew G. Knepley PetscInt dim;
389918dfc20SMatthew G. Knepley char title[PETSC_MAX_PATH_LEN];
390918dfc20SMatthew G. Knepley
391918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetCellDMByName(sw, "velocity", &celldm));
392918dfc20SMatthew G. Knepley PetscCall(DMSwarmCellDMGetDM(celldm, &vdm));
393918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(vdm, &dim));
394918dfc20SMatthew G. Knepley PetscCall(DMGetBoundingBox(vdm, dmboxlower, dmboxupper));
395918dfc20SMatthew G. Knepley
396*2a8381b2SBarry Smith PetscCall(PetscSNPrintf(title, PETSC_MAX_PATH_LEN, "Cell %" PetscInt_FMT ": Velocity Distribution", ctx->velocity_monitor));
397918dfc20SMatthew G. Knepley PetscCall(PetscDrawCreate(comm, NULL, title, 400, 300, 400, 300, &drawcell_v));
398918dfc20SMatthew G. Knepley PetscCall(PetscDrawSetSave(drawcell_v, "ex2_cell_v"));
399918dfc20SMatthew G. Knepley PetscCall(PetscDrawSetFromOptions(drawcell_v));
400*2a8381b2SBarry Smith PetscCall(PetscDrawHGCreate(drawcell_v, (int)dim, &ctx->drawhgcell_v));
401*2a8381b2SBarry Smith PetscCall(PetscDrawHGCalcStats(ctx->drawhgcell_v, PETSC_TRUE));
402*2a8381b2SBarry Smith PetscCall(PetscDrawHGGetAxis(ctx->drawhgcell_v, &axis));
403*2a8381b2SBarry Smith PetscCall(PetscDrawHGSetNumberBins(ctx->drawhgcell_v, 21));
404918dfc20SMatthew G. Knepley PetscCall(PetscDrawAxisSetLabels(axis, "V_x Distribution", "V", "weight"));
405918dfc20SMatthew G. Knepley PetscCall(PetscDrawAxisSetLimits(axis, dmboxlower[0], dmboxupper[0], 0, 0));
406918dfc20SMatthew G. Knepley PetscCall(PetscDrawDestroy(&drawcell_v));
407918dfc20SMatthew G. Knepley }
408918dfc20SMatthew G. Knepley
409*2a8381b2SBarry Smith if (ctx->positions_monitor) {
410918dfc20SMatthew G. Knepley PetscDraw draw;
411918dfc20SMatthew G. Knepley PetscDrawAxis axis;
412918dfc20SMatthew G. Knepley
413918dfc20SMatthew G. Knepley PetscCall(PetscDrawCreate(comm, NULL, "Particle Position", 0, 0, 400, 300, &draw));
414918dfc20SMatthew G. Knepley PetscCall(PetscDrawSetSave(draw, "ex9_pos"));
415918dfc20SMatthew G. Knepley PetscCall(PetscDrawSetFromOptions(draw));
416*2a8381b2SBarry Smith PetscCall(PetscDrawSPCreate(draw, 10, &ctx->drawspX));
417918dfc20SMatthew G. Knepley PetscCall(PetscDrawDestroy(&draw));
418*2a8381b2SBarry Smith PetscCall(PetscDrawSPSetDimension(ctx->drawspX, 1));
419*2a8381b2SBarry Smith PetscCall(PetscDrawSPGetAxis(ctx->drawspX, &axis));
420918dfc20SMatthew G. Knepley PetscCall(PetscDrawAxisSetLabels(axis, "Particles", "x", "v"));
421*2a8381b2SBarry Smith PetscCall(PetscDrawSPReset(ctx->drawspX));
422918dfc20SMatthew G. Knepley }
423*2a8381b2SBarry Smith if (ctx->poisson_monitor) {
424918dfc20SMatthew G. Knepley Vec rho, rhohat, phi;
425918dfc20SMatthew G. Knepley PetscDraw draw;
426918dfc20SMatthew G. Knepley PetscDrawAxis axis;
427918dfc20SMatthew G. Knepley
428918dfc20SMatthew G. Knepley PetscCall(PetscDrawCreate(comm, NULL, "Electric_Field", 0, 0, 400, 300, &draw));
429918dfc20SMatthew G. Knepley PetscCall(PetscDrawSetFromOptions(draw));
430918dfc20SMatthew G. Knepley PetscCall(PetscDrawSetSave(draw, "ex9_E_spatial"));
431*2a8381b2SBarry Smith PetscCall(PetscDrawSPCreate(draw, 10, &ctx->drawspE));
432918dfc20SMatthew G. Knepley PetscCall(PetscDrawDestroy(&draw));
433*2a8381b2SBarry Smith PetscCall(PetscDrawSPSetDimension(ctx->drawspE, 1));
434*2a8381b2SBarry Smith PetscCall(PetscDrawSPGetAxis(ctx->drawspE, &axis));
435918dfc20SMatthew G. Knepley PetscCall(PetscDrawAxisSetLabels(axis, "Particles", "x", "E"));
436*2a8381b2SBarry Smith PetscCall(PetscDrawSPReset(ctx->drawspE));
437918dfc20SMatthew G. Knepley
438*2a8381b2SBarry Smith PetscCall(PetscViewerDrawOpen(comm, NULL, "Charge Density", 0, 0, 400, 300, &ctx->viewerRho));
439*2a8381b2SBarry Smith PetscCall(PetscObjectSetOptionsPrefix((PetscObject)ctx->viewerRho, "rho_"));
440*2a8381b2SBarry Smith PetscCall(PetscViewerDrawGetDraw(ctx->viewerRho, 0, &draw));
441918dfc20SMatthew G. Knepley PetscCall(PetscDrawSetSave(draw, "ex9_rho_spatial"));
442*2a8381b2SBarry Smith PetscCall(PetscViewerSetFromOptions(ctx->viewerRho));
443*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmPot, "rho", &rho));
444918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)rho, "charge_density"));
445*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmPot, "rho", &rho));
446918dfc20SMatthew G. Knepley
447918dfc20SMatthew G. Knepley PetscInt dim, N;
448918dfc20SMatthew G. Knepley
449*2a8381b2SBarry Smith PetscCall(DMGetDimension(ctx->dmPot, &dim));
450918dfc20SMatthew G. Knepley if (dim == 1) {
451*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmPot, "rhohat", &rhohat));
452918dfc20SMatthew G. Knepley PetscCall(VecGetSize(rhohat, &N));
453*2a8381b2SBarry Smith PetscCall(MatCreateFFT(comm, dim, &N, MATFFTW, &ctx->fftPot));
454*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmPot, "rhohat", &rhohat));
455*2a8381b2SBarry Smith PetscCall(MatCreateVecs(ctx->fftPot, &ctx->fftX, &ctx->fftY));
456*2a8381b2SBarry Smith PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &ctx->fftReal));
457918dfc20SMatthew G. Knepley }
458918dfc20SMatthew G. Knepley
459*2a8381b2SBarry Smith PetscCall(PetscViewerDrawOpen(comm, NULL, "rhohat: Charge Density FT", 0, 0, 400, 300, &ctx->viewerRhoHat));
460*2a8381b2SBarry Smith PetscCall(PetscObjectSetOptionsPrefix((PetscObject)ctx->viewerRhoHat, "rhohat_"));
461*2a8381b2SBarry Smith PetscCall(PetscViewerDrawGetDraw(ctx->viewerRhoHat, 0, &draw));
462918dfc20SMatthew G. Knepley PetscCall(PetscDrawSetSave(draw, "ex9_rho_ft"));
463*2a8381b2SBarry Smith PetscCall(PetscViewerSetFromOptions(ctx->viewerRhoHat));
464*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmPot, "rhohat", &rhohat));
465918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)rhohat, "charge_density_ft"));
466*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmPot, "rhohat", &rhohat));
467918dfc20SMatthew G. Knepley
468*2a8381b2SBarry Smith PetscCall(PetscViewerDrawOpen(comm, NULL, "Potential", 400, 0, 400, 300, &ctx->viewerPhi));
469*2a8381b2SBarry Smith PetscCall(PetscObjectSetOptionsPrefix((PetscObject)ctx->viewerPhi, "phi_"));
470*2a8381b2SBarry Smith PetscCall(PetscViewerDrawGetDraw(ctx->viewerPhi, 0, &draw));
471918dfc20SMatthew G. Knepley PetscCall(PetscDrawSetSave(draw, "ex9_phi_spatial"));
472*2a8381b2SBarry Smith PetscCall(PetscViewerSetFromOptions(ctx->viewerPhi));
473*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmPot, "phi", &phi));
474918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)phi, "potential"));
475*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmPot, "phi", &phi));
476918dfc20SMatthew G. Knepley }
477*2a8381b2SBarry Smith if (ctx->moment_field_monitor) {
478918dfc20SMatthew G. Knepley Vec n, p, e;
479f14fce1bSMatthew G. Knepley Vec nres, pres, eres;
480918dfc20SMatthew G. Knepley PetscDraw draw;
481918dfc20SMatthew G. Knepley
482*2a8381b2SBarry Smith PetscCall(PetscViewerDrawOpen(comm, NULL, "Number Density", 400, 0, 400, 300, &ctx->viewerN));
483*2a8381b2SBarry Smith PetscCall(PetscObjectSetOptionsPrefix((PetscObject)ctx->viewerN, "n_"));
484*2a8381b2SBarry Smith PetscCall(PetscViewerDrawGetDraw(ctx->viewerN, 0, &draw));
485f14fce1bSMatthew G. Knepley PetscCall(PetscDrawSetSave(draw, "ex4_n_spatial"));
486*2a8381b2SBarry Smith PetscCall(PetscViewerSetFromOptions(ctx->viewerN));
487*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmN, "n", &n));
488918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)n, "Number Density"));
489*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmN, "n", &n));
490918dfc20SMatthew G. Knepley
491*2a8381b2SBarry Smith PetscCall(PetscViewerDrawOpen(comm, NULL, "Momentum Density", 800, 0, 400, 300, &ctx->viewerP));
492*2a8381b2SBarry Smith PetscCall(PetscObjectSetOptionsPrefix((PetscObject)ctx->viewerP, "p_"));
493*2a8381b2SBarry Smith PetscCall(PetscViewerDrawGetDraw(ctx->viewerP, 0, &draw));
494f14fce1bSMatthew G. Knepley PetscCall(PetscDrawSetSave(draw, "ex4_p_spatial"));
495*2a8381b2SBarry Smith PetscCall(PetscViewerSetFromOptions(ctx->viewerP));
496*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmP, "p", &p));
497918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)p, "Momentum Density"));
498*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmP, "p", &p));
499918dfc20SMatthew G. Knepley
500*2a8381b2SBarry Smith PetscCall(PetscViewerDrawOpen(comm, NULL, "Emergy Density (Pressure)", 1200, 0, 400, 300, &ctx->viewerE));
501*2a8381b2SBarry Smith PetscCall(PetscObjectSetOptionsPrefix((PetscObject)ctx->viewerE, "e_"));
502*2a8381b2SBarry Smith PetscCall(PetscViewerDrawGetDraw(ctx->viewerE, 0, &draw));
503f14fce1bSMatthew G. Knepley PetscCall(PetscDrawSetSave(draw, "ex4_e_spatial"));
504*2a8381b2SBarry Smith PetscCall(PetscViewerSetFromOptions(ctx->viewerE));
505*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmE, "e", &e));
506918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)e, "Energy Density (Pressure)"));
507*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmE, "e", &e));
508f14fce1bSMatthew G. Knepley
509f14fce1bSMatthew G. Knepley PetscDrawAxis axis;
510f14fce1bSMatthew G. Knepley
511f14fce1bSMatthew G. Knepley PetscCall(PetscDrawCreate(comm, NULL, "Moment Residual", 0, 320, 400, 300, &draw));
512f14fce1bSMatthew G. Knepley PetscCall(PetscDrawSetSave(draw, "ex4_moment_res"));
513f14fce1bSMatthew G. Knepley PetscCall(PetscDrawSetFromOptions(draw));
514*2a8381b2SBarry Smith PetscCall(PetscDrawLGCreate(draw, 3, &ctx->drawlgMomRes));
515f14fce1bSMatthew G. Knepley PetscCall(PetscDrawDestroy(&draw));
516*2a8381b2SBarry Smith PetscCall(PetscDrawLGGetAxis(ctx->drawlgMomRes, &axis));
517f14fce1bSMatthew G. Knepley PetscCall(PetscDrawAxisSetLabels(axis, "Moment Residial", "time", "Residual Norm"));
518*2a8381b2SBarry Smith PetscCall(PetscDrawLGSetLimits(ctx->drawlgMomRes, 0., ctx->steps * ctx->stepSize, -8, 0));
519f14fce1bSMatthew G. Knepley
520*2a8381b2SBarry Smith PetscCall(PetscViewerDrawOpen(comm, NULL, "Number Density Residual", 400, 300, 400, 300, &ctx->viewerNRes));
521*2a8381b2SBarry Smith PetscCall(PetscObjectSetOptionsPrefix((PetscObject)ctx->viewerNRes, "nres_"));
522*2a8381b2SBarry Smith PetscCall(PetscViewerDrawGetDraw(ctx->viewerNRes, 0, &draw));
523f14fce1bSMatthew G. Knepley PetscCall(PetscDrawSetSave(draw, "ex4_nres_spatial"));
524*2a8381b2SBarry Smith PetscCall(PetscViewerSetFromOptions(ctx->viewerNRes));
525*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmN, "nres", &nres));
526f14fce1bSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)nres, "Number Density Residual"));
527*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmN, "nres", &nres));
528f14fce1bSMatthew G. Knepley
529*2a8381b2SBarry Smith PetscCall(PetscViewerDrawOpen(comm, NULL, "Momentum Density Residual", 800, 300, 400, 300, &ctx->viewerPRes));
530*2a8381b2SBarry Smith PetscCall(PetscObjectSetOptionsPrefix((PetscObject)ctx->viewerPRes, "pres_"));
531*2a8381b2SBarry Smith PetscCall(PetscViewerDrawGetDraw(ctx->viewerPRes, 0, &draw));
532f14fce1bSMatthew G. Knepley PetscCall(PetscDrawSetSave(draw, "ex4_pres_spatial"));
533*2a8381b2SBarry Smith PetscCall(PetscViewerSetFromOptions(ctx->viewerPRes));
534*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmP, "pres", &pres));
535f14fce1bSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)pres, "Momentum Density Residual"));
536*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmP, "pres", &pres));
537f14fce1bSMatthew G. Knepley
538*2a8381b2SBarry Smith PetscCall(PetscViewerDrawOpen(comm, NULL, "Energy Density Residual", 1200, 300, 400, 300, &ctx->viewerERes));
539*2a8381b2SBarry Smith PetscCall(PetscObjectSetOptionsPrefix((PetscObject)ctx->viewerERes, "eres_"));
540*2a8381b2SBarry Smith PetscCall(PetscViewerDrawGetDraw(ctx->viewerERes, 0, &draw));
541f14fce1bSMatthew G. Knepley PetscCall(PetscDrawSetSave(draw, "ex4_eres_spatial"));
542*2a8381b2SBarry Smith PetscCall(PetscViewerSetFromOptions(ctx->viewerERes));
543*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmE, "eres", &eres));
544f14fce1bSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)eres, "Energy Density Residual"));
545*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmE, "eres", &eres));
546918dfc20SMatthew G. Knepley }
547918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
548918dfc20SMatthew G. Knepley }
549918dfc20SMatthew G. Knepley
DestroyContext(AppCtx * ctx)550*2a8381b2SBarry Smith static PetscErrorCode DestroyContext(AppCtx *ctx)
551918dfc20SMatthew G. Knepley {
552918dfc20SMatthew G. Knepley PetscFunctionBeginUser;
553*2a8381b2SBarry Smith PetscCall(PetscDrawHGDestroy(&ctx->drawhgic_x));
554*2a8381b2SBarry Smith PetscCall(PetscDrawHGDestroy(&ctx->drawhgic_v));
555*2a8381b2SBarry Smith PetscCall(PetscDrawHGDestroy(&ctx->drawhgcell_v));
556918dfc20SMatthew G. Knepley
557*2a8381b2SBarry Smith PetscCall(PetscDrawLGDestroy(&ctx->drawlgE));
558*2a8381b2SBarry Smith PetscCall(PetscDrawSPDestroy(&ctx->drawspE));
559*2a8381b2SBarry Smith PetscCall(PetscDrawSPDestroy(&ctx->drawspX));
560*2a8381b2SBarry Smith PetscCall(PetscViewerDestroy(&ctx->viewerRho));
561*2a8381b2SBarry Smith PetscCall(PetscViewerDestroy(&ctx->viewerRhoHat));
562*2a8381b2SBarry Smith PetscCall(MatDestroy(&ctx->fftPot));
563*2a8381b2SBarry Smith PetscCall(VecDestroy(&ctx->fftX));
564*2a8381b2SBarry Smith PetscCall(VecDestroy(&ctx->fftY));
565*2a8381b2SBarry Smith PetscCall(ISDestroy(&ctx->fftReal));
566*2a8381b2SBarry Smith PetscCall(PetscViewerDestroy(&ctx->viewerPhi));
567*2a8381b2SBarry Smith PetscCall(PetscViewerDestroy(&ctx->viewerN));
568*2a8381b2SBarry Smith PetscCall(PetscViewerDestroy(&ctx->viewerP));
569*2a8381b2SBarry Smith PetscCall(PetscViewerDestroy(&ctx->viewerE));
570*2a8381b2SBarry Smith PetscCall(PetscViewerDestroy(&ctx->viewerNRes));
571*2a8381b2SBarry Smith PetscCall(PetscViewerDestroy(&ctx->viewerPRes));
572*2a8381b2SBarry Smith PetscCall(PetscViewerDestroy(&ctx->viewerERes));
573*2a8381b2SBarry Smith PetscCall(PetscDrawLGDestroy(&ctx->drawlgMomRes));
574918dfc20SMatthew G. Knepley
575*2a8381b2SBarry Smith PetscCall(PetscBagDestroy(&ctx->bag));
576918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
577918dfc20SMatthew G. Knepley }
578918dfc20SMatthew G. Knepley
CheckNonNegativeWeights(DM sw,AppCtx * ctx)579*2a8381b2SBarry Smith static PetscErrorCode CheckNonNegativeWeights(DM sw, AppCtx *ctx)
580918dfc20SMatthew G. Knepley {
581918dfc20SMatthew G. Knepley const PetscScalar *w;
582918dfc20SMatthew G. Knepley PetscInt Np;
583918dfc20SMatthew G. Knepley
584918dfc20SMatthew G. Knepley PetscFunctionBeginUser;
585*2a8381b2SBarry Smith if (!ctx->checkweights) PetscFunctionReturn(PETSC_SUCCESS);
586918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "w_q", NULL, NULL, (void **)&w));
587918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(sw, &Np));
588918dfc20SMatthew G. Knepley 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]);
589918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "w_q", NULL, NULL, (void **)&w));
590918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
591918dfc20SMatthew G. Knepley }
592918dfc20SMatthew G. Knepley
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[])593f940b0e3Sdanofinn 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[])
594f940b0e3Sdanofinn {
595f940b0e3Sdanofinn for (PetscInt d = 0; d < dim; ++d) f0[0] += 0.5 * PetscSqr(u_x[d]);
596f940b0e3Sdanofinn }
597f940b0e3Sdanofinn
computeFieldEnergy(DM dm,Vec u,PetscReal * En)598f940b0e3Sdanofinn static PetscErrorCode computeFieldEnergy(DM dm, Vec u, PetscReal *En)
599f940b0e3Sdanofinn {
600f940b0e3Sdanofinn PetscDS ds;
601f940b0e3Sdanofinn const PetscInt field = 0;
602f940b0e3Sdanofinn PetscInt Nf;
603f940b0e3Sdanofinn void *ctx;
604f940b0e3Sdanofinn
605f940b0e3Sdanofinn PetscFunctionBegin;
606f940b0e3Sdanofinn PetscCall(DMGetApplicationContext(dm, &ctx));
607f940b0e3Sdanofinn PetscCall(DMGetDS(dm, &ds));
608f940b0e3Sdanofinn PetscCall(PetscDSGetNumFields(ds, &Nf));
609f940b0e3Sdanofinn PetscCheck(Nf == 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "We currently only support 1 field, not %" PetscInt_FMT, Nf);
610f940b0e3Sdanofinn PetscCall(PetscDSSetObjective(ds, field, &f0_Dirichlet));
611f940b0e3Sdanofinn PetscCall(DMPlexComputeIntegralFEM(dm, u, En, ctx));
612f940b0e3Sdanofinn PetscFunctionReturn(PETSC_SUCCESS);
613f940b0e3Sdanofinn }
614f940b0e3Sdanofinn
computeVelocityFEMMoments(DM sw,PetscReal moments[],AppCtx * ctx)615*2a8381b2SBarry Smith static PetscErrorCode computeVelocityFEMMoments(DM sw, PetscReal moments[], AppCtx *ctx)
616918dfc20SMatthew G. Knepley {
617918dfc20SMatthew G. Knepley DMSwarmCellDM celldm;
618918dfc20SMatthew G. Knepley DM vdm;
619918dfc20SMatthew G. Knepley Vec u[1];
620918dfc20SMatthew G. Knepley const char *fields[1] = {"w_q"};
621918dfc20SMatthew G. Knepley
622918dfc20SMatthew G. Knepley PetscFunctionBegin;
623918dfc20SMatthew G. Knepley PetscCall(DMSwarmSetCellDMActive(sw, "velocity"));
624918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetCellDMActive(sw, &celldm));
625918dfc20SMatthew G. Knepley PetscCall(DMSwarmCellDMGetDM(celldm, &vdm));
626918dfc20SMatthew G. Knepley PetscCall(DMGetGlobalVector(vdm, &u[0]));
627918dfc20SMatthew G. Knepley PetscCall(DMSwarmProjectFields(sw, vdm, 1, fields, u, SCATTER_FORWARD));
628918dfc20SMatthew G. Knepley PetscCall(DMPlexComputeMoments(vdm, u[0], moments));
629918dfc20SMatthew G. Knepley PetscCall(DMRestoreGlobalVector(vdm, &u[0]));
630918dfc20SMatthew G. Knepley PetscCall(DMSwarmSetCellDMActive(sw, "space"));
631918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
632918dfc20SMatthew G. Knepley }
633918dfc20SMatthew G. Knepley
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[])634918dfc20SMatthew 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[])
635918dfc20SMatthew G. Knepley {
636918dfc20SMatthew G. Knepley f0[0] = 0.;
637918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) f0[0] += PetscSqr(u_x[uOff_x[0] + d * dim + d]);
638918dfc20SMatthew G. Knepley }
639918dfc20SMatthew G. Knepley
640918dfc20SMatthew G. Knepley // Our model is E_max(t) = C e^{-gamma t} |cos(omega t - phi)|
ComputeEmaxResidual(Tao tao,Vec x,Vec res,void * Ctx)641*2a8381b2SBarry Smith static PetscErrorCode ComputeEmaxResidual(Tao tao, Vec x, Vec res, void *Ctx)
642918dfc20SMatthew G. Knepley {
643*2a8381b2SBarry Smith EmaxCtx *ctx = (EmaxCtx *)Ctx;
644918dfc20SMatthew G. Knepley const PetscScalar *a;
645918dfc20SMatthew G. Knepley PetscScalar *F;
646918dfc20SMatthew G. Knepley PetscReal C, gamma, omega, phi;
647918dfc20SMatthew G. Knepley
648918dfc20SMatthew G. Knepley PetscFunctionBegin;
649918dfc20SMatthew G. Knepley PetscCall(VecGetArrayRead(x, &a));
650918dfc20SMatthew G. Knepley PetscCall(VecGetArray(res, &F));
651918dfc20SMatthew G. Knepley C = PetscRealPart(a[0]);
652918dfc20SMatthew G. Knepley gamma = PetscRealPart(a[1]);
653918dfc20SMatthew G. Knepley omega = PetscRealPart(a[2]);
654918dfc20SMatthew G. Knepley phi = PetscRealPart(a[3]);
655918dfc20SMatthew G. Knepley PetscCall(VecRestoreArrayRead(x, &a));
656918dfc20SMatthew G. Knepley for (PetscInt i = ctx->s; i < ctx->e; ++i) F[i - ctx->s] = PetscPowReal(10., ctx->Emax[i]) - C * PetscExpReal(-gamma * ctx->t[i]) * PetscAbsReal(PetscCosReal(omega * ctx->t[i] - phi));
657918dfc20SMatthew G. Knepley PetscCall(VecRestoreArray(res, &F));
658918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
659918dfc20SMatthew G. Knepley }
660918dfc20SMatthew G. Knepley
661918dfc20SMatthew G. Knepley // The Jacobian of the residual J = dr(x)/dx
ComputeEmaxJacobian(Tao tao,Vec x,Mat J,Mat Jpre,void * Ctx)662*2a8381b2SBarry Smith static PetscErrorCode ComputeEmaxJacobian(Tao tao, Vec x, Mat J, Mat Jpre, void *Ctx)
663918dfc20SMatthew G. Knepley {
664*2a8381b2SBarry Smith EmaxCtx *ctx = (EmaxCtx *)Ctx;
665918dfc20SMatthew G. Knepley const PetscScalar *a;
666918dfc20SMatthew G. Knepley PetscScalar *jac;
667918dfc20SMatthew G. Knepley PetscReal C, gamma, omega, phi;
668918dfc20SMatthew G. Knepley const PetscInt n = ctx->e - ctx->s;
669918dfc20SMatthew G. Knepley
670918dfc20SMatthew G. Knepley PetscFunctionBegin;
671918dfc20SMatthew G. Knepley PetscCall(VecGetArrayRead(x, &a));
672918dfc20SMatthew G. Knepley C = PetscRealPart(a[0]);
673918dfc20SMatthew G. Knepley gamma = PetscRealPart(a[1]);
674918dfc20SMatthew G. Knepley omega = PetscRealPart(a[2]);
675918dfc20SMatthew G. Knepley phi = PetscRealPart(a[3]);
676918dfc20SMatthew G. Knepley PetscCall(VecRestoreArrayRead(x, &a));
677918dfc20SMatthew G. Knepley PetscCall(MatDenseGetArray(J, &jac));
678918dfc20SMatthew G. Knepley for (PetscInt i = 0; i < n; ++i) {
679918dfc20SMatthew G. Knepley const PetscInt k = i + ctx->s;
680918dfc20SMatthew G. Knepley
681918dfc20SMatthew G. Knepley jac[i * 4 + 0] = -PetscExpReal(-gamma * ctx->t[k]) * PetscAbsReal(PetscCosReal(omega * ctx->t[k] - phi));
682918dfc20SMatthew G. Knepley jac[i * 4 + 1] = C * ctx->t[k] * PetscExpReal(-gamma * ctx->t[k]) * PetscAbsReal(PetscCosReal(omega * ctx->t[k] - phi));
683918dfc20SMatthew G. Knepley jac[i * 4 + 2] = C * ctx->t[k] * PetscExpReal(-gamma * ctx->t[k]) * (PetscCosReal(omega * ctx->t[k] - phi) < 0. ? -1. : 1.) * PetscSinReal(omega * ctx->t[k] - phi);
684918dfc20SMatthew G. Knepley jac[i * 4 + 3] = -C * PetscExpReal(-gamma * ctx->t[k]) * (PetscCosReal(omega * ctx->t[k] - phi) < 0. ? -1. : 1.) * PetscSinReal(omega * ctx->t[k] - phi);
685918dfc20SMatthew G. Knepley }
686918dfc20SMatthew G. Knepley PetscCall(MatDenseRestoreArray(J, &jac));
687918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
688918dfc20SMatthew G. Knepley }
689918dfc20SMatthew G. Knepley
690918dfc20SMatthew G. Knepley // Our model is log_10 E_max(t) = log_10 C - gamma t log_10 e + log_10 |cos(omega t - phi)|
ComputeLogEmaxResidual(Tao tao,Vec x,Vec res,void * Ctx)691*2a8381b2SBarry Smith static PetscErrorCode ComputeLogEmaxResidual(Tao tao, Vec x, Vec res, void *Ctx)
692918dfc20SMatthew G. Knepley {
693*2a8381b2SBarry Smith EmaxCtx *ctx = (EmaxCtx *)Ctx;
694918dfc20SMatthew G. Knepley const PetscScalar *a;
695918dfc20SMatthew G. Knepley PetscScalar *F;
696918dfc20SMatthew G. Knepley PetscReal C, gamma, omega, phi;
697918dfc20SMatthew G. Knepley
698918dfc20SMatthew G. Knepley PetscFunctionBegin;
699918dfc20SMatthew G. Knepley PetscCall(VecGetArrayRead(x, &a));
700918dfc20SMatthew G. Knepley PetscCall(VecGetArray(res, &F));
701918dfc20SMatthew G. Knepley C = PetscRealPart(a[0]);
702918dfc20SMatthew G. Knepley gamma = PetscRealPart(a[1]);
703918dfc20SMatthew G. Knepley omega = PetscRealPart(a[2]);
704918dfc20SMatthew G. Knepley phi = PetscRealPart(a[3]);
705918dfc20SMatthew G. Knepley PetscCall(VecRestoreArrayRead(x, &a));
706918dfc20SMatthew G. Knepley for (PetscInt i = ctx->s; i < ctx->e; ++i) {
707918dfc20SMatthew G. Knepley if (C < 0) {
708918dfc20SMatthew G. Knepley F[i - ctx->s] = 1e10;
709918dfc20SMatthew G. Knepley continue;
710918dfc20SMatthew G. Knepley }
711918dfc20SMatthew G. Knepley F[i - ctx->s] = ctx->Emax[i] - (PetscLog10Real(C) - gamma * ctx->t[i] * PetscLog10Real(PETSC_E) + PetscLog10Real(PetscAbsReal(PetscCosReal(omega * ctx->t[i] - phi))));
712918dfc20SMatthew G. Knepley }
713918dfc20SMatthew G. Knepley PetscCall(VecRestoreArray(res, &F));
714918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
715918dfc20SMatthew G. Knepley }
716918dfc20SMatthew G. Knepley
717918dfc20SMatthew G. Knepley // The Jacobian of the residual J = dr(x)/dx
ComputeLogEmaxJacobian(Tao tao,Vec x,Mat J,Mat Jpre,void * Ctx)718*2a8381b2SBarry Smith static PetscErrorCode ComputeLogEmaxJacobian(Tao tao, Vec x, Mat J, Mat Jpre, void *Ctx)
719918dfc20SMatthew G. Knepley {
720*2a8381b2SBarry Smith EmaxCtx *ctx = (EmaxCtx *)Ctx;
721918dfc20SMatthew G. Knepley const PetscScalar *a;
722918dfc20SMatthew G. Knepley PetscScalar *jac;
723918dfc20SMatthew G. Knepley PetscReal C, omega, phi;
724918dfc20SMatthew G. Knepley const PetscInt n = ctx->e - ctx->s;
725918dfc20SMatthew G. Knepley
726918dfc20SMatthew G. Knepley PetscFunctionBegin;
727918dfc20SMatthew G. Knepley PetscCall(VecGetArrayRead(x, &a));
728918dfc20SMatthew G. Knepley C = PetscRealPart(a[0]);
729918dfc20SMatthew G. Knepley omega = PetscRealPart(a[2]);
730918dfc20SMatthew G. Knepley phi = PetscRealPart(a[3]);
731918dfc20SMatthew G. Knepley PetscCall(VecRestoreArrayRead(x, &a));
732918dfc20SMatthew G. Knepley PetscCall(MatDenseGetArray(J, &jac));
733918dfc20SMatthew G. Knepley for (PetscInt i = 0; i < n; ++i) {
734918dfc20SMatthew G. Knepley const PetscInt k = i + ctx->s;
735918dfc20SMatthew G. Knepley
736918dfc20SMatthew G. Knepley jac[0 * n + i] = -1. / (PetscLog10Real(PETSC_E) * C);
737918dfc20SMatthew G. Knepley jac[1 * n + i] = ctx->t[k] * PetscLog10Real(PETSC_E);
738918dfc20SMatthew G. Knepley jac[2 * n + i] = (PetscCosReal(omega * ctx->t[k] - phi) < 0. ? -1. : 1.) * ctx->t[k] * PetscSinReal(omega * ctx->t[k] - phi) / (PetscLog10Real(PETSC_E) * PetscAbsReal(PetscCosReal(omega * ctx->t[k] - phi)));
739918dfc20SMatthew G. Knepley jac[3 * n + i] = -(PetscCosReal(omega * ctx->t[k] - phi) < 0. ? -1. : 1.) * PetscSinReal(omega * ctx->t[k] - phi) / (PetscLog10Real(PETSC_E) * PetscAbsReal(PetscCosReal(omega * ctx->t[k] - phi)));
740918dfc20SMatthew G. Knepley }
741918dfc20SMatthew G. Knepley PetscCall(MatDenseRestoreArray(J, &jac));
742918dfc20SMatthew G. Knepley PetscCall(MatViewFromOptions(J, NULL, "-emax_jac_view"));
743918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
744918dfc20SMatthew G. Knepley }
745918dfc20SMatthew G. Knepley
MonitorEField(TS ts,PetscInt step,PetscReal t,Vec U,void * Ctx)746*2a8381b2SBarry Smith static PetscErrorCode MonitorEField(TS ts, PetscInt step, PetscReal t, Vec U, void *Ctx)
747918dfc20SMatthew G. Knepley {
748*2a8381b2SBarry Smith AppCtx *ctx = (AppCtx *)Ctx;
749918dfc20SMatthew G. Knepley DM sw;
750918dfc20SMatthew G. Knepley PetscScalar intESq;
751918dfc20SMatthew G. Knepley PetscReal *E, *x, *weight;
752918dfc20SMatthew G. Knepley PetscReal Enorm = 0., lgEnorm, lgEmax, sum = 0., Emax = 0., chargesum = 0.;
753918dfc20SMatthew G. Knepley PetscReal pmoments[4]; /* \int f, \int v f, \int v^2 f */
754918dfc20SMatthew G. Knepley PetscInt *species, dim, Np, gNp;
755918dfc20SMatthew G. Knepley MPI_Comm comm;
756918dfc20SMatthew G. Knepley PetscMPIInt rank;
757918dfc20SMatthew G. Knepley
758918dfc20SMatthew G. Knepley PetscFunctionBeginUser;
759*2a8381b2SBarry Smith if (step < 0 || !ctx->validE) PetscFunctionReturn(PETSC_SUCCESS);
760918dfc20SMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)ts, &comm));
761918dfc20SMatthew G. Knepley PetscCallMPI(MPI_Comm_rank(comm, &rank));
762918dfc20SMatthew G. Knepley PetscCall(TSGetDM(ts, &sw));
763918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim));
764918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(sw, &Np));
765918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetSize(sw, &gNp));
766918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortGetAccess(sw));
767918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&x));
768918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "E_field", NULL, NULL, (void **)&E));
769918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "species", NULL, NULL, (void **)&species));
770918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "w_q", NULL, NULL, (void **)&weight));
771918dfc20SMatthew G. Knepley
772918dfc20SMatthew G. Knepley for (PetscInt p = 0; p < Np; ++p) {
773918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < 1; ++d) {
774918dfc20SMatthew G. Knepley PetscReal temp = PetscAbsReal(E[p * dim + d]);
775918dfc20SMatthew G. Knepley if (temp > Emax) Emax = temp;
776918dfc20SMatthew G. Knepley }
777918dfc20SMatthew G. Knepley Enorm += PetscSqrtReal(E[p * dim] * E[p * dim]);
778918dfc20SMatthew G. Knepley sum += E[p * dim];
779*2a8381b2SBarry Smith chargesum += ctx->charges[0] * weight[p];
780918dfc20SMatthew G. Knepley }
781918dfc20SMatthew G. Knepley PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &Emax, 1, MPIU_REAL, MPIU_MAX, comm));
782918dfc20SMatthew G. Knepley lgEnorm = Enorm != 0 ? PetscLog10Real(Enorm) : -16.;
783*2a8381b2SBarry Smith lgEmax = Emax != 0 ? PetscLog10Real(Emax) : ctx->drawlgEmin;
784918dfc20SMatthew G. Knepley
785918dfc20SMatthew G. Knepley PetscDS ds;
786918dfc20SMatthew G. Knepley Vec phi;
787918dfc20SMatthew G. Knepley
788*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmPot, "phi", &phi));
789*2a8381b2SBarry Smith PetscCall(DMGetDS(ctx->dmPot, &ds));
790918dfc20SMatthew G. Knepley PetscCall(PetscDSSetObjective(ds, 0, &f0_grad_phi2));
791*2a8381b2SBarry Smith PetscCall(DMPlexComputeIntegralFEM(ctx->dmPot, phi, &intESq, ctx));
792*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmPot, "phi", &phi));
793918dfc20SMatthew G. Knepley
794918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&x));
795918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "w_q", NULL, NULL, (void **)&weight));
796918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "E_field", NULL, NULL, (void **)&E));
797918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "species", NULL, NULL, (void **)&species));
798*2a8381b2SBarry Smith PetscCall(PetscDrawLGAddPoint(ctx->drawlgE, &t, &lgEmax));
799*2a8381b2SBarry Smith if (ctx->efield_monitor == E_MONITOR_FULL) {
800918dfc20SMatthew G. Knepley PetscDraw draw;
801918dfc20SMatthew G. Knepley
802*2a8381b2SBarry Smith PetscCall(PetscDrawLGDraw(ctx->drawlgE));
803*2a8381b2SBarry Smith PetscCall(PetscDrawLGGetDraw(ctx->drawlgE, &draw));
804918dfc20SMatthew G. Knepley PetscCall(PetscDrawSave(draw));
805918dfc20SMatthew G. Knepley
806918dfc20SMatthew G. Knepley PetscCall(DMSwarmComputeMoments(sw, "velocity", "w_q", pmoments));
807918dfc20SMatthew 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));
808918dfc20SMatthew G. Knepley PetscCall(DMViewFromOptions(sw, NULL, "-sw_efield_view"));
809918dfc20SMatthew G. Knepley }
810918dfc20SMatthew G. Knepley
811918dfc20SMatthew G. Knepley // Compute decay rate and frequency
812*2a8381b2SBarry Smith PetscCall(PetscDrawLGGetData(ctx->drawlgE, NULL, &ctx->emaxCtx.e, &ctx->emaxCtx.t, &ctx->emaxCtx.Emax));
813*2a8381b2SBarry Smith if (!rank && !(ctx->emaxCtx.e % ctx->emaxCtx.per)) {
814918dfc20SMatthew G. Knepley Tao tao;
815918dfc20SMatthew G. Knepley Mat J;
816918dfc20SMatthew G. Knepley Vec x, r;
817918dfc20SMatthew G. Knepley PetscScalar *a;
818918dfc20SMatthew G. Knepley PetscBool fitLog = PETSC_TRUE, debug = PETSC_FALSE;
819918dfc20SMatthew G. Knepley
820918dfc20SMatthew G. Knepley PetscCall(TaoCreate(PETSC_COMM_SELF, &tao));
821918dfc20SMatthew G. Knepley PetscCall(TaoSetOptionsPrefix(tao, "emax_"));
822918dfc20SMatthew G. Knepley PetscCall(VecCreateSeq(PETSC_COMM_SELF, 4, &x));
823918dfc20SMatthew G. Knepley PetscCall(TaoSetSolution(tao, x));
824*2a8381b2SBarry Smith PetscCall(VecCreateSeq(PETSC_COMM_SELF, ctx->emaxCtx.e - ctx->emaxCtx.s, &r));
825*2a8381b2SBarry Smith if (fitLog) PetscCall(TaoSetResidualRoutine(tao, r, ComputeLogEmaxResidual, &ctx->emaxCtx));
826*2a8381b2SBarry Smith else PetscCall(TaoSetResidualRoutine(tao, r, ComputeEmaxResidual, &ctx->emaxCtx));
827918dfc20SMatthew G. Knepley PetscCall(VecDestroy(&r));
828*2a8381b2SBarry Smith PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, ctx->emaxCtx.e - ctx->emaxCtx.s, 4, NULL, &J));
829*2a8381b2SBarry Smith if (fitLog) PetscCall(TaoSetJacobianResidualRoutine(tao, J, J, ComputeLogEmaxJacobian, &ctx->emaxCtx));
830*2a8381b2SBarry Smith else PetscCall(TaoSetJacobianResidualRoutine(tao, J, J, ComputeEmaxJacobian, &ctx->emaxCtx));
831918dfc20SMatthew G. Knepley PetscCall(MatDestroy(&J));
832918dfc20SMatthew G. Knepley PetscCall(TaoSetFromOptions(tao));
833918dfc20SMatthew G. Knepley PetscCall(VecGetArray(x, &a));
834918dfc20SMatthew G. Knepley a[0] = 0.02;
835918dfc20SMatthew G. Knepley a[1] = 0.15;
836918dfc20SMatthew G. Knepley a[2] = 1.4;
837918dfc20SMatthew G. Knepley a[3] = 0.45;
838918dfc20SMatthew G. Knepley PetscCall(VecRestoreArray(x, &a));
839918dfc20SMatthew G. Knepley PetscCall(TaoSolve(tao));
840918dfc20SMatthew G. Knepley if (debug) {
841918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, "t = ["));
842*2a8381b2SBarry Smith for (PetscInt i = 0; i < ctx->emaxCtx.e; ++i) {
843918dfc20SMatthew G. Knepley if (i > 0) PetscCall(PetscPrintf(PETSC_COMM_SELF, ", "));
844*2a8381b2SBarry Smith PetscCall(PetscPrintf(PETSC_COMM_SELF, "%g", ctx->emaxCtx.t[i]));
845918dfc20SMatthew G. Knepley }
846918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, "]\n"));
847918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, "Emax = ["));
848*2a8381b2SBarry Smith for (PetscInt i = 0; i < ctx->emaxCtx.e; ++i) {
849918dfc20SMatthew G. Knepley if (i > 0) PetscCall(PetscPrintf(PETSC_COMM_SELF, ", "));
850*2a8381b2SBarry Smith PetscCall(PetscPrintf(PETSC_COMM_SELF, "%g", ctx->emaxCtx.Emax[i]));
851918dfc20SMatthew G. Knepley }
852918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, "]\n"));
853918dfc20SMatthew G. Knepley }
854918dfc20SMatthew G. Knepley PetscDraw draw;
855918dfc20SMatthew G. Knepley PetscDrawAxis axis;
856918dfc20SMatthew G. Knepley char title[PETSC_MAX_PATH_LEN];
857918dfc20SMatthew G. Knepley
858918dfc20SMatthew G. Knepley PetscCall(VecGetArray(x, &a));
859*2a8381b2SBarry Smith ctx->gamma = a[1];
860*2a8381b2SBarry Smith ctx->omega = a[2];
861*2a8381b2SBarry Smith if (ctx->efield_monitor == E_MONITOR_FULL) {
862918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, "Emax Fit: gamma %g omega %g C %g phi %g\n", a[1], a[2], a[0], a[3]));
863*2a8381b2SBarry Smith PetscCall(PetscDrawLGGetDraw(ctx->drawlgE, &draw));
864918dfc20SMatthew G. Knepley PetscCall(PetscSNPrintf(title, PETSC_MAX_PATH_LEN, "Max Electric Field gamma %.4g omega %.4g", a[1], a[2]));
865918dfc20SMatthew G. Knepley PetscCall(PetscDrawSetTitle(draw, title));
866*2a8381b2SBarry Smith PetscCall(PetscDrawLGGetAxis(ctx->drawlgE, &axis));
867918dfc20SMatthew G. Knepley PetscCall(PetscDrawAxisSetLabels(axis, title, "time", "E_max"));
868918dfc20SMatthew G. Knepley }
869918dfc20SMatthew G. Knepley PetscCall(VecRestoreArray(x, &a));
870918dfc20SMatthew G. Knepley PetscCall(VecDestroy(&x));
871918dfc20SMatthew G. Knepley PetscCall(TaoDestroy(&tao));
872918dfc20SMatthew G. Knepley }
873918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
874918dfc20SMatthew G. Knepley }
875918dfc20SMatthew G. Knepley
MonitorMoments(TS ts,PetscInt step,PetscReal t,Vec U,void * Ctx)876*2a8381b2SBarry Smith static PetscErrorCode MonitorMoments(TS ts, PetscInt step, PetscReal t, Vec U, void *Ctx)
877918dfc20SMatthew G. Knepley {
878*2a8381b2SBarry Smith AppCtx *ctx = (AppCtx *)Ctx;
879918dfc20SMatthew G. Knepley DM sw;
880918dfc20SMatthew G. Knepley PetscReal pmoments[4], fmoments[4]; /* \int f, \int v f, \int v^2 f */
881918dfc20SMatthew G. Knepley
882918dfc20SMatthew G. Knepley PetscFunctionBeginUser;
883918dfc20SMatthew G. Knepley if (step < 0) PetscFunctionReturn(PETSC_SUCCESS);
884918dfc20SMatthew G. Knepley PetscCall(TSGetDM(ts, &sw));
885918dfc20SMatthew G. Knepley
886918dfc20SMatthew G. Knepley PetscCall(DMSwarmComputeMoments(sw, "velocity", "w_q", pmoments));
887*2a8381b2SBarry Smith PetscCall(computeVelocityFEMMoments(sw, fmoments, ctx));
888918dfc20SMatthew G. Knepley
889918dfc20SMatthew 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]));
890918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
891918dfc20SMatthew G. Knepley }
892918dfc20SMatthew G. Knepley
zero(PetscInt dim,PetscReal time,const PetscReal x[],PetscInt Nc,PetscScalar * u,PetscCtx ctx)893*2a8381b2SBarry Smith static PetscErrorCode zero(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, PetscCtx ctx)
894918dfc20SMatthew G. Knepley {
895918dfc20SMatthew G. Knepley u[0] = 0.0;
896918dfc20SMatthew G. Knepley return PETSC_SUCCESS;
897918dfc20SMatthew G. Knepley }
898918dfc20SMatthew G. Knepley
899918dfc20SMatthew G. Knepley /*
900918dfc20SMatthew G. Knepley M_p w_p
901918dfc20SMatthew G. Knepley - Make M_p with "moments"
902918dfc20SMatthew G. Knepley - Get w_p from Swarm
903918dfc20SMatthew G. Knepley M_p v_p w_p
904918dfc20SMatthew G. Knepley - Get v_p from Swarm
905918dfc20SMatthew G. Knepley - pointwise multiply v_p and w_p
906918dfc20SMatthew G. Knepley M_p (v_p - (\sum_j p_F \phi_j(x_p)) / m (\sum_k n_F \phi_k(x_p)))^2 w_p
907918dfc20SMatthew G. Knepley - ProjectField(sw, {n, p} U, {v_p} A, tmp_p)
908918dfc20SMatthew G. Knepley - pointwise multiply tmp_p and w_p
909918dfc20SMatthew G. Knepley
910f14fce1bSMatthew G. Knepley Projection works fpr swarms
911f14fce1bSMatthew G. Knepley Fields are FE from the CellDM, and aux fields are the swarm fields
912918dfc20SMatthew G. Knepley */
ComputeMomentFields(TS ts)913918dfc20SMatthew G. Knepley static PetscErrorCode ComputeMomentFields(TS ts)
914918dfc20SMatthew G. Knepley {
915*2a8381b2SBarry Smith AppCtx *ctx;
916918dfc20SMatthew G. Knepley DM sw;
917918dfc20SMatthew G. Knepley KSP ksp;
918f14fce1bSMatthew G. Knepley Mat M_p, D_p;
919f14fce1bSMatthew G. Knepley Vec f, v, E, tmpMom;
920f14fce1bSMatthew G. Knepley Vec m, mold, mfluxold, mres, n, nrhs, nflux, nres, p, prhs, pflux, pres, e, erhs, eflux, eres;
921f14fce1bSMatthew G. Knepley PetscReal dt, t;
922918dfc20SMatthew G. Knepley PetscInt Nts;
923918dfc20SMatthew G. Knepley
924918dfc20SMatthew G. Knepley PetscFunctionBegin;
925918dfc20SMatthew G. Knepley PetscCall(TSGetStepNumber(ts, &Nts));
926918dfc20SMatthew G. Knepley PetscCall(TSGetTimeStep(ts, &dt));
927f14fce1bSMatthew G. Knepley PetscCall(TSGetTime(ts, &t));
928918dfc20SMatthew G. Knepley PetscCall(TSGetDM(ts, &sw));
929*2a8381b2SBarry Smith PetscCall(DMGetApplicationContext(sw, &ctx));
930918dfc20SMatthew G. Knepley PetscCall(DMSwarmSetCellDMActive(sw, "moment fields"));
931918dfc20SMatthew G. Knepley PetscCall(DMSwarmMigrate(sw, PETSC_FALSE));
932f14fce1bSMatthew G. Knepley // TODO In higher dimensions, we will have to create different M_p and D_p for each field
933*2a8381b2SBarry Smith PetscCall(DMCreateMassMatrix(sw, ctx->dmN, &M_p));
934*2a8381b2SBarry Smith PetscCall(DMCreateGradientMatrix(sw, ctx->dmN, &D_p));
935918dfc20SMatthew G. Knepley PetscCall(DMSwarmCreateGlobalVectorFromField(sw, "w_q", &f));
936918dfc20SMatthew G. Knepley PetscCall(DMSwarmCreateGlobalVectorFromField(sw, "velocity", &v));
937f14fce1bSMatthew G. Knepley PetscCall(DMSwarmCreateGlobalVectorFromField(sw, "E_field", &E));
938918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)f, "particle weight"));
939918dfc20SMatthew G. Knepley
940*2a8381b2SBarry Smith PetscCall(MatViewFromOptions(ctx->MN, NULL, "-mn_view"));
941*2a8381b2SBarry Smith PetscCall(MatViewFromOptions(ctx->MP, NULL, "-mp_view"));
942*2a8381b2SBarry Smith PetscCall(MatViewFromOptions(ctx->ME, NULL, "-me_view"));
943918dfc20SMatthew G. Knepley PetscCall(VecViewFromOptions(f, NULL, "-weights_view"));
944918dfc20SMatthew G. Knepley
945*2a8381b2SBarry Smith PetscCall(DMGetGlobalVector(ctx->dmN, &nrhs));
946*2a8381b2SBarry Smith PetscCall(DMGetGlobalVector(ctx->dmN, &nflux));
947f14fce1bSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)nrhs, "Weak number density"));
948*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmN, "n", &n));
949*2a8381b2SBarry Smith PetscCall(DMGetGlobalVector(ctx->dmP, &prhs));
950*2a8381b2SBarry Smith PetscCall(DMGetGlobalVector(ctx->dmP, &pflux));
951f14fce1bSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)prhs, "Weak momentum density"));
952*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmP, "p", &p));
953*2a8381b2SBarry Smith PetscCall(DMGetGlobalVector(ctx->dmE, &erhs));
954*2a8381b2SBarry Smith PetscCall(DMGetGlobalVector(ctx->dmE, &eflux));
955f14fce1bSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)erhs, "Weak energy density (pressure)"));
956*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmE, "e", &e));
957918dfc20SMatthew G. Knepley
958f14fce1bSMatthew G. Knepley // Compute moments and fluxes
959f14fce1bSMatthew G. Knepley PetscCall(VecDuplicate(f, &tmpMom));
960918dfc20SMatthew G. Knepley
961f14fce1bSMatthew G. Knepley PetscCall(MatMultTranspose(M_p, f, nrhs));
962f14fce1bSMatthew G. Knepley
963f14fce1bSMatthew G. Knepley PetscCall(VecPointwiseMult(tmpMom, f, v));
964f14fce1bSMatthew G. Knepley PetscCall(MatMultTranspose(M_p, tmpMom, prhs));
965f14fce1bSMatthew G. Knepley PetscCall(MatMultTranspose(D_p, tmpMom, nflux));
966f14fce1bSMatthew G. Knepley
967f14fce1bSMatthew G. Knepley PetscCall(VecPointwiseMult(tmpMom, tmpMom, v));
968f14fce1bSMatthew G. Knepley PetscCall(MatMultTranspose(M_p, tmpMom, erhs));
969f14fce1bSMatthew G. Knepley PetscCall(MatMultTranspose(D_p, tmpMom, pflux));
970f14fce1bSMatthew G. Knepley
971f14fce1bSMatthew G. Knepley PetscCall(VecPointwiseMult(tmpMom, tmpMom, v));
972f14fce1bSMatthew G. Knepley PetscCall(MatMultTranspose(D_p, tmpMom, eflux));
973f14fce1bSMatthew G. Knepley
974f14fce1bSMatthew G. Knepley PetscCall(VecPointwiseMult(tmpMom, f, E));
975f14fce1bSMatthew G. Knepley PetscCall(MatMultTransposeAdd(M_p, tmpMom, pflux, pflux));
976f14fce1bSMatthew G. Knepley
977f14fce1bSMatthew G. Knepley PetscCall(VecPointwiseMult(tmpMom, v, E));
978f14fce1bSMatthew G. Knepley PetscCall(VecScale(tmpMom, 2.));
979f14fce1bSMatthew G. Knepley PetscCall(MatMultTransposeAdd(M_p, tmpMom, eflux, eflux));
980f14fce1bSMatthew G. Knepley
981f14fce1bSMatthew G. Knepley PetscCall(VecDestroy(&tmpMom));
982918dfc20SMatthew G. Knepley PetscCall(DMSwarmDestroyGlobalVectorFromField(sw, "velocity", &v));
983918dfc20SMatthew G. Knepley PetscCall(DMSwarmDestroyGlobalVectorFromField(sw, "w_q", &f));
984f14fce1bSMatthew G. Knepley PetscCall(DMSwarmDestroyGlobalVectorFromField(sw, "E_field", &E));
985918dfc20SMatthew G. Knepley
986918dfc20SMatthew G. Knepley PetscCall(MatDestroy(&M_p));
987f14fce1bSMatthew G. Knepley PetscCall(MatDestroy(&D_p));
988918dfc20SMatthew G. Knepley
989918dfc20SMatthew G. Knepley PetscCall(KSPCreate(PetscObjectComm((PetscObject)sw), &ksp));
990918dfc20SMatthew G. Knepley PetscCall(KSPSetOptionsPrefix(ksp, "mom_proj_"));
991*2a8381b2SBarry Smith PetscCall(KSPSetOperators(ksp, ctx->MN, ctx->MN));
992918dfc20SMatthew G. Knepley PetscCall(KSPSetFromOptions(ksp));
993f14fce1bSMatthew G. Knepley PetscCall(KSPSolve(ksp, nrhs, n));
994*2a8381b2SBarry Smith PetscCall(KSPSetOperators(ksp, ctx->MP, ctx->MP));
995918dfc20SMatthew G. Knepley PetscCall(KSPSetFromOptions(ksp));
996f14fce1bSMatthew G. Knepley PetscCall(KSPSolve(ksp, prhs, p));
997*2a8381b2SBarry Smith PetscCall(KSPSetOperators(ksp, ctx->ME, ctx->ME));
998918dfc20SMatthew G. Knepley PetscCall(KSPSetFromOptions(ksp));
999f14fce1bSMatthew G. Knepley PetscCall(KSPSolve(ksp, erhs, e));
1000918dfc20SMatthew G. Knepley PetscCall(KSPDestroy(&ksp));
1001*2a8381b2SBarry Smith PetscCall(DMRestoreGlobalVector(ctx->dmN, &nrhs));
1002*2a8381b2SBarry Smith PetscCall(DMRestoreGlobalVector(ctx->dmP, &prhs));
1003*2a8381b2SBarry Smith PetscCall(DMRestoreGlobalVector(ctx->dmE, &erhs));
1004918dfc20SMatthew G. Knepley
1005918dfc20SMatthew G. Knepley // Check moment residual
1006918dfc20SMatthew G. Knepley // TODO Fix global2local here
1007f14fce1bSMatthew G. Knepley PetscReal res[3], logres[3];
1008918dfc20SMatthew G. Knepley
1009*2a8381b2SBarry Smith PetscCall(DMGetGlobalVector(ctx->dmMom, &m));
1010*2a8381b2SBarry Smith PetscCall(VecISCopy(m, ctx->isN, SCATTER_FORWARD, n));
1011*2a8381b2SBarry Smith PetscCall(VecISCopy(m, ctx->isP, SCATTER_FORWARD, p));
1012*2a8381b2SBarry Smith PetscCall(VecISCopy(m, ctx->isE, SCATTER_FORWARD, e));
1013*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmMom, "mold", &mold));
1014*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmMom, "mfluxold", &mfluxold));
1015f14fce1bSMatthew G. Knepley if (!Nts) goto end;
1016f14fce1bSMatthew G. Knepley
1017f14fce1bSMatthew G. Knepley // e = \Tr{\tau}
1018f14fce1bSMatthew G. Knepley // M_p w^{k+1} - M_p w^k - \Delta t D_p (w^k \vb{v}^k) = 0
1019f14fce1bSMatthew G. Knepley // M_p \vb{p}^{k+1} - M_p \vb{p}^k - \Delta t D_p \tau - e \Delta t M_p \left( n \vb{E} \right) = 0
1020f14fce1bSMatthew G. Knepley // M_p e^{k+1} - M_p e^k - \Delta t D_p \vb{Q} - 2 e \Delta t M_p \left( \vb{p} \cdot \vb{E} \right) = 0
1021*2a8381b2SBarry Smith PetscCall(DMGetGlobalVector(ctx->dmMom, &mres));
1022f14fce1bSMatthew G. Knepley PetscCall(VecCopy(mfluxold, mres));
1023f14fce1bSMatthew G. Knepley PetscCall(VecAXPBYPCZ(mres, 1. / dt, -1. / dt, -1., m, mold));
1024f14fce1bSMatthew G. Knepley
1025*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmN, "nres", &nres));
1026*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmP, "pres", &pres));
1027*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmE, "eres", &eres));
1028*2a8381b2SBarry Smith PetscCall(VecISCopy(mres, ctx->isN, SCATTER_REVERSE, nres));
1029*2a8381b2SBarry Smith PetscCall(VecISCopy(mres, ctx->isP, SCATTER_REVERSE, pres));
1030*2a8381b2SBarry Smith PetscCall(VecISCopy(mres, ctx->isE, SCATTER_REVERSE, eres));
1031f14fce1bSMatthew G. Knepley PetscCall(VecNorm(nres, NORM_2, &res[0]));
1032f14fce1bSMatthew G. Knepley PetscCall(VecNorm(pres, NORM_2, &res[1]));
1033f14fce1bSMatthew G. Knepley PetscCall(VecNorm(eres, NORM_2, &res[2]));
1034f14fce1bSMatthew G. Knepley PetscCall(PetscPrintf(PetscObjectComm((PetscObject)sw), "Mass Residual: %g\n", (double)res[0]));
1035f14fce1bSMatthew G. Knepley PetscCall(PetscPrintf(PetscObjectComm((PetscObject)sw), "Momentum Residual: %g\n", (double)res[1]));
1036f14fce1bSMatthew G. Knepley PetscCall(PetscPrintf(PetscObjectComm((PetscObject)sw), "Energy Residual: %g\n", (double)res[2]));
1037*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmN, "nres", &nres));
1038*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmP, "pres", &pres));
1039*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmE, "eres", &eres));
1040*2a8381b2SBarry Smith PetscCall(DMRestoreGlobalVector(ctx->dmMom, &mres));
1041f14fce1bSMatthew G. Knepley
1042f14fce1bSMatthew G. Knepley for (PetscInt i = 0; i < 3; ++i) logres[i] = PetscLog10Real(res[i]);
1043*2a8381b2SBarry Smith PetscCall(PetscDrawLGAddCommonPoint(ctx->drawlgMomRes, t, logres));
1044*2a8381b2SBarry Smith PetscCall(PetscDrawLGDraw(ctx->drawlgMomRes));
1045f14fce1bSMatthew G. Knepley {
1046f14fce1bSMatthew G. Knepley PetscDraw draw;
1047f14fce1bSMatthew G. Knepley
1048*2a8381b2SBarry Smith PetscCall(PetscDrawLGGetDraw(ctx->drawlgMomRes, &draw));
1049f14fce1bSMatthew G. Knepley PetscCall(PetscDrawSave(draw));
1050f14fce1bSMatthew G. Knepley }
1051f14fce1bSMatthew G. Knepley
1052f14fce1bSMatthew G. Knepley end:
1053918dfc20SMatthew G. Knepley PetscCall(VecCopy(m, mold));
1054*2a8381b2SBarry Smith PetscCall(DMRestoreGlobalVector(ctx->dmMom, &m));
1055*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmMom, "mold", &mold));
1056*2a8381b2SBarry Smith PetscCall(VecISCopy(mfluxold, ctx->isN, SCATTER_FORWARD, nflux));
1057*2a8381b2SBarry Smith PetscCall(VecISCopy(mfluxold, ctx->isP, SCATTER_FORWARD, pflux));
1058*2a8381b2SBarry Smith PetscCall(VecISCopy(mfluxold, ctx->isE, SCATTER_FORWARD, eflux));
1059*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmMom, "mfluxold", &mfluxold));
1060918dfc20SMatthew G. Knepley
1061*2a8381b2SBarry Smith PetscCall(DMRestoreGlobalVector(ctx->dmN, &nflux));
1062*2a8381b2SBarry Smith PetscCall(DMRestoreGlobalVector(ctx->dmP, &pflux));
1063*2a8381b2SBarry Smith PetscCall(DMRestoreGlobalVector(ctx->dmE, &eflux));
1064*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmN, "n", &n));
1065*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmP, "p", &p));
1066*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmE, "e", &e));
1067918dfc20SMatthew G. Knepley PetscCall(DMSwarmSetCellDMActive(sw, "space"));
1068918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
1069918dfc20SMatthew G. Knepley }
1070918dfc20SMatthew G. Knepley
MonitorMomentFields(TS ts,PetscInt step,PetscReal t,Vec U,void * Ctx)1071*2a8381b2SBarry Smith static PetscErrorCode MonitorMomentFields(TS ts, PetscInt step, PetscReal t, Vec U, void *Ctx)
1072918dfc20SMatthew G. Knepley {
1073*2a8381b2SBarry Smith AppCtx *ctx = (AppCtx *)Ctx;
1074918dfc20SMatthew G. Knepley Vec n, p, e;
1075f14fce1bSMatthew G. Knepley Vec nres, pres, eres;
1076918dfc20SMatthew G. Knepley
1077918dfc20SMatthew G. Knepley PetscFunctionBeginUser;
1078918dfc20SMatthew G. Knepley if (step < 0) PetscFunctionReturn(PETSC_SUCCESS);
1079918dfc20SMatthew G. Knepley PetscCall(ComputeMomentFields(ts));
1080918dfc20SMatthew G. Knepley
1081*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmN, "n", &n));
1082*2a8381b2SBarry Smith PetscCall(VecView(n, ctx->viewerN));
1083*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmN, "n", &n));
1084918dfc20SMatthew G. Knepley
1085*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmP, "p", &p));
1086*2a8381b2SBarry Smith PetscCall(VecView(p, ctx->viewerP));
1087*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmP, "p", &p));
1088918dfc20SMatthew G. Knepley
1089*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmE, "e", &e));
1090*2a8381b2SBarry Smith PetscCall(VecView(e, ctx->viewerE));
1091*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmE, "e", &e));
1092f14fce1bSMatthew G. Knepley
1093*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmN, "nres", &nres));
1094*2a8381b2SBarry Smith PetscCall(VecView(nres, ctx->viewerNRes));
1095*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmN, "nres", &nres));
1096f14fce1bSMatthew G. Knepley
1097*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmP, "pres", &pres));
1098*2a8381b2SBarry Smith PetscCall(VecView(pres, ctx->viewerPRes));
1099*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmP, "pres", &pres));
1100f14fce1bSMatthew G. Knepley
1101*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmE, "eres", &eres));
1102*2a8381b2SBarry Smith PetscCall(VecView(eres, ctx->viewerERes));
1103*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmE, "eres", &eres));
1104918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
1105918dfc20SMatthew G. Knepley }
1106918dfc20SMatthew G. Knepley
MonitorInitialConditions(TS ts,PetscInt step,PetscReal t,Vec U,void * Ctx)1107*2a8381b2SBarry Smith PetscErrorCode MonitorInitialConditions(TS ts, PetscInt step, PetscReal t, Vec U, void *Ctx)
1108918dfc20SMatthew G. Knepley {
1109*2a8381b2SBarry Smith AppCtx *ctx = (AppCtx *)Ctx;
1110918dfc20SMatthew G. Knepley DM sw;
1111918dfc20SMatthew G. Knepley PetscDraw drawic_x, drawic_v;
1112918dfc20SMatthew G. Knepley PetscReal *weight, *pos, *vel;
1113918dfc20SMatthew G. Knepley PetscInt dim, Np;
1114918dfc20SMatthew G. Knepley
1115918dfc20SMatthew G. Knepley PetscFunctionBegin;
1116918dfc20SMatthew G. Knepley if (step < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates interpolated solution */
1117918dfc20SMatthew G. Knepley if (step == 0) {
1118918dfc20SMatthew G. Knepley PetscCall(TSGetDM(ts, &sw));
1119918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim));
1120918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(sw, &Np));
1121918dfc20SMatthew G. Knepley
1122*2a8381b2SBarry Smith PetscCall(PetscDrawHGReset(ctx->drawhgic_x));
1123*2a8381b2SBarry Smith PetscCall(PetscDrawHGGetDraw(ctx->drawhgic_x, &drawic_x));
1124918dfc20SMatthew G. Knepley PetscCall(PetscDrawClear(drawic_x));
1125918dfc20SMatthew G. Knepley PetscCall(PetscDrawFlush(drawic_x));
1126918dfc20SMatthew G. Knepley
1127*2a8381b2SBarry Smith PetscCall(PetscDrawHGReset(ctx->drawhgic_v));
1128*2a8381b2SBarry Smith PetscCall(PetscDrawHGGetDraw(ctx->drawhgic_v, &drawic_v));
1129918dfc20SMatthew G. Knepley PetscCall(PetscDrawClear(drawic_v));
1130918dfc20SMatthew G. Knepley PetscCall(PetscDrawFlush(drawic_v));
1131918dfc20SMatthew G. Knepley
1132918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&pos));
1133918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "velocity", NULL, NULL, (void **)&vel));
1134918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "w_q", NULL, NULL, (void **)&weight));
1135918dfc20SMatthew G. Knepley for (PetscInt p = 0; p < Np; ++p) {
1136*2a8381b2SBarry Smith PetscCall(PetscDrawHGAddWeightedValue(ctx->drawhgic_x, pos[p * dim], weight[p]));
1137*2a8381b2SBarry Smith PetscCall(PetscDrawHGAddWeightedValue(ctx->drawhgic_v, vel[p * dim], weight[p]));
1138918dfc20SMatthew G. Knepley }
1139918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&pos));
1140918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "velocity", NULL, NULL, (void **)&vel));
1141918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "w_q", NULL, NULL, (void **)&weight));
1142918dfc20SMatthew G. Knepley
1143*2a8381b2SBarry Smith PetscCall(PetscDrawHGDraw(ctx->drawhgic_x));
1144*2a8381b2SBarry Smith PetscCall(PetscDrawHGSave(ctx->drawhgic_x));
1145*2a8381b2SBarry Smith PetscCall(PetscDrawHGDraw(ctx->drawhgic_v));
1146*2a8381b2SBarry Smith PetscCall(PetscDrawHGSave(ctx->drawhgic_v));
1147918dfc20SMatthew G. Knepley }
1148918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
1149918dfc20SMatthew G. Knepley }
1150918dfc20SMatthew G. Knepley
1151918dfc20SMatthew G. Knepley // Right now, make the complete velocity histogram
MonitorVelocity(TS ts,PetscInt step,PetscReal t,Vec U,void * Ctx)1152*2a8381b2SBarry Smith PetscErrorCode MonitorVelocity(TS ts, PetscInt step, PetscReal t, Vec U, void *Ctx)
1153918dfc20SMatthew G. Knepley {
1154*2a8381b2SBarry Smith AppCtx *ctx = (AppCtx *)Ctx;
1155918dfc20SMatthew G. Knepley DM sw, dm;
1156918dfc20SMatthew G. Knepley Vec ks;
1157918dfc20SMatthew G. Knepley PetscProbFn *cdf;
1158918dfc20SMatthew G. Knepley PetscDraw drawcell_v;
1159918dfc20SMatthew G. Knepley PetscScalar *ksa;
1160918dfc20SMatthew G. Knepley PetscReal *weight, *vel;
1161918dfc20SMatthew G. Knepley PetscInt *pidx;
1162*2a8381b2SBarry Smith PetscInt dim, Npc, cStart, cEnd, cell = ctx->velocity_monitor;
1163918dfc20SMatthew G. Knepley
1164918dfc20SMatthew G. Knepley PetscFunctionBegin;
1165918dfc20SMatthew G. Knepley PetscCall(TSGetDM(ts, &sw));
1166918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim));
1167918dfc20SMatthew G. Knepley
1168918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetCellDM(sw, &dm));
1169918dfc20SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
1170918dfc20SMatthew G. Knepley PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &ks));
1171918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)ks, "KS Statistic by Cell"));
1172918dfc20SMatthew G. Knepley PetscCall(VecSetSizes(ks, cEnd - cStart, PETSC_DETERMINE));
1173918dfc20SMatthew G. Knepley PetscCall(VecSetFromOptions(ks));
1174918dfc20SMatthew G. Knepley switch (dim) {
1175918dfc20SMatthew G. Knepley case 1:
1176918dfc20SMatthew G. Knepley //cdf = PetscCDFMaxwellBoltzmann1D;
1177918dfc20SMatthew G. Knepley cdf = PetscCDFGaussian1D;
1178918dfc20SMatthew G. Knepley break;
1179918dfc20SMatthew G. Knepley case 2:
1180918dfc20SMatthew G. Knepley cdf = PetscCDFMaxwellBoltzmann2D;
1181918dfc20SMatthew G. Knepley break;
1182918dfc20SMatthew G. Knepley case 3:
1183918dfc20SMatthew G. Knepley cdf = PetscCDFMaxwellBoltzmann3D;
1184918dfc20SMatthew G. Knepley break;
1185918dfc20SMatthew G. Knepley default:
1186918dfc20SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Dimension %" PetscInt_FMT " not supported", dim);
1187918dfc20SMatthew G. Knepley }
1188918dfc20SMatthew G. Knepley
1189*2a8381b2SBarry Smith PetscCall(PetscDrawHGReset(ctx->drawhgcell_v));
1190*2a8381b2SBarry Smith PetscCall(PetscDrawHGGetDraw(ctx->drawhgcell_v, &drawcell_v));
1191918dfc20SMatthew G. Knepley PetscCall(PetscDrawClear(drawcell_v));
1192918dfc20SMatthew G. Knepley PetscCall(PetscDrawFlush(drawcell_v));
1193918dfc20SMatthew G. Knepley
1194918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "velocity", NULL, NULL, (void **)&vel));
1195918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "w_q", NULL, NULL, (void **)&weight));
1196918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortGetAccess(sw));
1197918dfc20SMatthew G. Knepley PetscCall(VecGetArrayWrite(ks, &ksa));
1198918dfc20SMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) {
1199918dfc20SMatthew G. Knepley Vec cellv, cellw;
1200918dfc20SMatthew G. Knepley PetscScalar *cella, *cellaw;
1201918dfc20SMatthew G. Knepley PetscReal totWgt = 0.;
1202918dfc20SMatthew G. Knepley
1203918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortGetPointsPerCell(sw, c, &Npc, &pidx));
1204918dfc20SMatthew G. Knepley PetscCall(VecCreate(PETSC_COMM_SELF, &cellv));
1205918dfc20SMatthew G. Knepley PetscCall(VecSetBlockSize(cellv, dim));
1206918dfc20SMatthew G. Knepley PetscCall(VecSetSizes(cellv, Npc * dim, Npc));
1207918dfc20SMatthew G. Knepley PetscCall(VecSetFromOptions(cellv));
1208918dfc20SMatthew G. Knepley PetscCall(VecCreate(PETSC_COMM_SELF, &cellw));
1209918dfc20SMatthew G. Knepley PetscCall(VecSetSizes(cellw, Npc, Npc));
1210918dfc20SMatthew G. Knepley PetscCall(VecSetFromOptions(cellw));
1211918dfc20SMatthew G. Knepley PetscCall(VecGetArrayWrite(cellv, &cella));
1212918dfc20SMatthew G. Knepley PetscCall(VecGetArrayWrite(cellw, &cellaw));
1213918dfc20SMatthew G. Knepley for (PetscInt q = 0; q < Npc; ++q) {
1214918dfc20SMatthew G. Knepley const PetscInt p = pidx[q];
1215*2a8381b2SBarry Smith if (c == cell) PetscCall(PetscDrawHGAddWeightedValue(ctx->drawhgcell_v, vel[p * dim], weight[p]));
1216918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) cella[q * dim + d] = vel[p * dim + d];
1217918dfc20SMatthew G. Knepley cellaw[q] = weight[p];
1218918dfc20SMatthew G. Knepley totWgt += weight[p];
1219918dfc20SMatthew G. Knepley }
1220918dfc20SMatthew G. Knepley PetscCall(VecRestoreArrayWrite(cellv, &cella));
1221918dfc20SMatthew G. Knepley PetscCall(VecRestoreArrayWrite(cellw, &cellaw));
1222918dfc20SMatthew G. Knepley PetscCall(VecScale(cellw, 1. / totWgt));
1223918dfc20SMatthew G. Knepley PetscCall(PetscProbComputeKSStatisticWeighted(cellv, cellw, cdf, &ksa[c - cStart]));
1224918dfc20SMatthew G. Knepley PetscCall(VecDestroy(&cellv));
1225918dfc20SMatthew G. Knepley PetscCall(VecDestroy(&cellw));
1226918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(sw, c, &Npc, &pidx));
1227918dfc20SMatthew G. Knepley }
1228918dfc20SMatthew G. Knepley PetscCall(VecRestoreArrayWrite(ks, &ksa));
1229918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "velocity", NULL, NULL, (void **)&vel));
1230918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "w_q", NULL, NULL, (void **)&weight));
1231918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortRestoreAccess(sw));
1232918dfc20SMatthew G. Knepley
1233918dfc20SMatthew G. Knepley PetscReal minalpha, maxalpha;
1234918dfc20SMatthew G. Knepley PetscInt mincell, maxcell;
1235918dfc20SMatthew G. Knepley
1236918dfc20SMatthew G. Knepley PetscCall(VecFilter(ks, PETSC_SMALL));
1237918dfc20SMatthew G. Knepley PetscCall(VecMin(ks, &mincell, &minalpha));
1238918dfc20SMatthew G. Knepley PetscCall(VecMax(ks, &maxcell, &maxalpha));
1239918dfc20SMatthew 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));
1240918dfc20SMatthew G. Knepley PetscCall(VecViewFromOptions(ks, NULL, "-ks_view"));
1241918dfc20SMatthew G. Knepley PetscCall(VecDestroy(&ks));
1242918dfc20SMatthew G. Knepley
1243*2a8381b2SBarry Smith PetscCall(PetscDrawHGDraw(ctx->drawhgcell_v));
1244*2a8381b2SBarry Smith PetscCall(PetscDrawHGSave(ctx->drawhgcell_v));
1245918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
1246918dfc20SMatthew G. Knepley }
1247918dfc20SMatthew G. Knepley
MonitorPositions_2D(TS ts,PetscInt step,PetscReal t,Vec U,void * Ctx)1248*2a8381b2SBarry Smith static PetscErrorCode MonitorPositions_2D(TS ts, PetscInt step, PetscReal t, Vec U, void *Ctx)
1249918dfc20SMatthew G. Knepley {
1250*2a8381b2SBarry Smith AppCtx *ctx = (AppCtx *)Ctx;
1251918dfc20SMatthew G. Knepley DM dm, sw;
1252f940b0e3Sdanofinn PetscDrawAxis axis;
1253f940b0e3Sdanofinn char title[1024];
1254918dfc20SMatthew G. Knepley PetscScalar *x, *v, *weight;
1255918dfc20SMatthew G. Knepley PetscReal lower[3], upper[3], speed;
1256918dfc20SMatthew G. Knepley const PetscInt *s;
1257918dfc20SMatthew G. Knepley PetscInt dim, cStart, cEnd, c;
1258918dfc20SMatthew G. Knepley
1259918dfc20SMatthew G. Knepley PetscFunctionBeginUser;
1260*2a8381b2SBarry Smith if (step > 0 && step % ctx->ostep == 0) {
1261918dfc20SMatthew G. Knepley PetscCall(TSGetDM(ts, &sw));
1262918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetCellDM(sw, &dm));
1263918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(dm, &dim));
1264918dfc20SMatthew G. Knepley PetscCall(DMGetBoundingBox(dm, lower, upper));
1265918dfc20SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
1266918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&x));
1267918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "velocity", NULL, NULL, (void **)&v));
1268918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "w_q", NULL, NULL, (void **)&weight));
1269918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "species", NULL, NULL, (void **)&s));
1270918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortGetAccess(sw));
1271*2a8381b2SBarry Smith PetscCall(PetscDrawSPReset(ctx->drawspX));
1272*2a8381b2SBarry Smith PetscCall(PetscDrawSPGetAxis(ctx->drawspX, &axis));
1273f940b0e3Sdanofinn PetscCall(PetscSNPrintf(title, 1024, "Step %" PetscInt_FMT " Time: %g", step, (double)t));
1274f940b0e3Sdanofinn PetscCall(PetscDrawAxisSetLabels(axis, title, "x", "v"));
1275*2a8381b2SBarry Smith PetscCall(PetscDrawSPSetLimits(ctx->drawspX, lower[0], upper[0], lower[1], upper[1]));
1276*2a8381b2SBarry Smith PetscCall(PetscDrawSPSetLimits(ctx->drawspX, lower[0], upper[0], -12, 12));
1277918dfc20SMatthew G. Knepley for (c = 0; c < cEnd - cStart; ++c) {
1278918dfc20SMatthew G. Knepley PetscInt *pidx, Npc, q;
1279918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortGetPointsPerCell(sw, c, &Npc, &pidx));
1280918dfc20SMatthew G. Knepley for (q = 0; q < Npc; ++q) {
1281918dfc20SMatthew G. Knepley const PetscInt p = pidx[q];
1282918dfc20SMatthew G. Knepley if (s[p] == 0) {
1283918dfc20SMatthew G. Knepley speed = 0.;
1284918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) speed += PetscSqr(v[p * dim + d]);
1285918dfc20SMatthew G. Knepley speed = PetscSqrtReal(speed);
1286918dfc20SMatthew G. Knepley if (dim == 1) {
1287*2a8381b2SBarry Smith PetscCall(PetscDrawSPAddPointColorized(ctx->drawspX, &x[p * dim], &v[p * dim], &speed));
1288918dfc20SMatthew G. Knepley } else {
1289*2a8381b2SBarry Smith PetscCall(PetscDrawSPAddPointColorized(ctx->drawspX, &x[p * dim], &x[p * dim + 1], &speed));
1290918dfc20SMatthew G. Knepley }
1291918dfc20SMatthew G. Knepley } else if (s[p] == 1) {
1292*2a8381b2SBarry Smith PetscCall(PetscDrawSPAddPoint(ctx->drawspX, &x[p * dim], &v[p * dim]));
1293918dfc20SMatthew G. Knepley }
1294918dfc20SMatthew G. Knepley }
1295918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(sw, c, &Npc, &pidx));
1296918dfc20SMatthew G. Knepley }
1297*2a8381b2SBarry Smith PetscCall(PetscDrawSPDraw(ctx->drawspX, PETSC_TRUE));
1298918dfc20SMatthew G. Knepley PetscDraw draw;
1299*2a8381b2SBarry Smith PetscCall(PetscDrawSPGetDraw(ctx->drawspX, &draw));
1300918dfc20SMatthew G. Knepley PetscCall(PetscDrawSave(draw));
1301918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortRestoreAccess(sw));
1302918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&x));
1303918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "w_q", NULL, NULL, (void **)&weight));
1304918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "velocity", NULL, NULL, (void **)&v));
1305918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "species", NULL, NULL, (void **)&s));
1306918dfc20SMatthew G. Knepley }
1307918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
1308918dfc20SMatthew G. Knepley }
1309918dfc20SMatthew G. Knepley
MonitorPoisson(TS ts,PetscInt step,PetscReal t,Vec U,void * Ctx)1310*2a8381b2SBarry Smith static PetscErrorCode MonitorPoisson(TS ts, PetscInt step, PetscReal t, Vec U, void *Ctx)
1311918dfc20SMatthew G. Knepley {
1312*2a8381b2SBarry Smith AppCtx *ctx = (AppCtx *)Ctx;
1313918dfc20SMatthew G. Knepley DM dm, sw;
1314918dfc20SMatthew G. Knepley
1315918dfc20SMatthew G. Knepley PetscFunctionBeginUser;
1316*2a8381b2SBarry Smith if (step > 0 && step % ctx->ostep == 0) {
1317918dfc20SMatthew G. Knepley PetscCall(TSGetDM(ts, &sw));
1318918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetCellDM(sw, &dm));
1319918dfc20SMatthew G. Knepley
1320*2a8381b2SBarry Smith if (ctx->validE) {
1321918dfc20SMatthew G. Knepley PetscScalar *x, *E, *weight;
1322918dfc20SMatthew G. Knepley PetscReal lower[3], upper[3], xval;
1323918dfc20SMatthew G. Knepley PetscDraw draw;
1324918dfc20SMatthew G. Knepley PetscInt dim, cStart, cEnd;
1325918dfc20SMatthew G. Knepley
1326918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(dm, &dim));
1327918dfc20SMatthew G. Knepley PetscCall(DMGetBoundingBox(dm, lower, upper));
1328918dfc20SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
1329918dfc20SMatthew G. Knepley
1330*2a8381b2SBarry Smith PetscCall(PetscDrawSPReset(ctx->drawspE));
1331918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&x));
1332918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "E_field", NULL, NULL, (void **)&E));
1333918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "w_q", NULL, NULL, (void **)&weight));
1334918dfc20SMatthew G. Knepley
1335918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortGetAccess(sw));
1336918dfc20SMatthew G. Knepley for (PetscInt c = 0; c < cEnd - cStart; ++c) {
1337918dfc20SMatthew G. Knepley PetscReal Eavg = 0.0;
1338918dfc20SMatthew G. Knepley PetscInt *pidx, Npc;
1339918dfc20SMatthew G. Knepley
1340918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortGetPointsPerCell(sw, c, &Npc, &pidx));
1341918dfc20SMatthew G. Knepley for (PetscInt q = 0; q < Npc; ++q) {
1342918dfc20SMatthew G. Knepley const PetscInt p = pidx[q];
1343918dfc20SMatthew G. Knepley Eavg += E[p * dim];
1344918dfc20SMatthew G. Knepley }
1345918dfc20SMatthew G. Knepley Eavg /= Npc;
1346918dfc20SMatthew G. Knepley xval = (c + 0.5) * ((upper[0] - lower[0]) / (cEnd - cStart));
1347*2a8381b2SBarry Smith PetscCall(PetscDrawSPAddPoint(ctx->drawspE, &xval, &Eavg));
1348918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(sw, c, &Npc, &pidx));
1349918dfc20SMatthew G. Knepley }
1350*2a8381b2SBarry Smith PetscCall(PetscDrawSPDraw(ctx->drawspE, PETSC_TRUE));
1351*2a8381b2SBarry Smith PetscCall(PetscDrawSPGetDraw(ctx->drawspE, &draw));
1352918dfc20SMatthew G. Knepley PetscCall(PetscDrawSave(draw));
1353918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortRestoreAccess(sw));
1354918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&x));
1355918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "w_q", NULL, NULL, (void **)&weight));
1356918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "E_field", NULL, NULL, (void **)&E));
1357918dfc20SMatthew G. Knepley }
1358918dfc20SMatthew G. Knepley
1359918dfc20SMatthew G. Knepley Vec rho, rhohat, phi;
1360918dfc20SMatthew G. Knepley
1361*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmPot, "rho", &rho));
1362*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmPot, "rhohat", &rhohat));
1363*2a8381b2SBarry Smith PetscCall(VecView(rho, ctx->viewerRho));
1364*2a8381b2SBarry Smith PetscCall(VecISCopy(ctx->fftX, ctx->fftReal, SCATTER_FORWARD, rho));
1365*2a8381b2SBarry Smith PetscCall(MatMult(ctx->fftPot, ctx->fftX, ctx->fftY));
1366*2a8381b2SBarry Smith PetscCall(VecFilter(ctx->fftY, PETSC_SMALL));
1367*2a8381b2SBarry Smith PetscCall(VecViewFromOptions(ctx->fftX, NULL, "-real_view"));
1368*2a8381b2SBarry Smith PetscCall(VecViewFromOptions(ctx->fftY, NULL, "-fft_view"));
1369*2a8381b2SBarry Smith PetscCall(VecISCopy(ctx->fftY, ctx->fftReal, SCATTER_REVERSE, rhohat));
1370918dfc20SMatthew G. Knepley PetscCall(VecSetValue(rhohat, 0, 0., INSERT_VALUES)); // Remove large DC component
1371*2a8381b2SBarry Smith PetscCall(VecView(rhohat, ctx->viewerRhoHat));
1372*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmPot, "rho", &rho));
1373*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmPot, "rhohat", &rhohat));
1374918dfc20SMatthew G. Knepley
1375*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmPot, "phi", &phi));
1376*2a8381b2SBarry Smith PetscCall(VecView(phi, ctx->viewerPhi));
1377*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmPot, "phi", &phi));
1378918dfc20SMatthew G. Knepley }
1379918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
1380918dfc20SMatthew G. Knepley }
1381918dfc20SMatthew G. Knepley
SetupParameters(MPI_Comm comm,AppCtx * ctx)1382918dfc20SMatthew G. Knepley static PetscErrorCode SetupParameters(MPI_Comm comm, AppCtx *ctx)
1383918dfc20SMatthew G. Knepley {
1384918dfc20SMatthew G. Knepley PetscBag bag;
1385918dfc20SMatthew G. Knepley Parameter *p;
1386918dfc20SMatthew G. Knepley
1387918dfc20SMatthew G. Knepley PetscFunctionBeginUser;
1388918dfc20SMatthew G. Knepley /* setup PETSc parameter bag */
1389*2a8381b2SBarry Smith PetscCall(PetscBagGetData(ctx->bag, &p));
1390918dfc20SMatthew G. Knepley PetscCall(PetscBagSetName(ctx->bag, "par", "Vlasov-Poisson Parameters"));
1391918dfc20SMatthew G. Knepley bag = ctx->bag;
1392918dfc20SMatthew G. Knepley PetscCall(PetscBagRegisterScalar(bag, &p->v0, 1.0, "v0", "Velocity scale, m/s"));
1393918dfc20SMatthew G. Knepley PetscCall(PetscBagRegisterScalar(bag, &p->t0, 1.0, "t0", "Time scale, s"));
1394918dfc20SMatthew G. Knepley PetscCall(PetscBagRegisterScalar(bag, &p->x0, 1.0, "x0", "Space scale, m"));
1395918dfc20SMatthew G. Knepley PetscCall(PetscBagRegisterScalar(bag, &p->v0, 1.0, "phi0", "Potential scale, kg*m^2/A*s^3"));
1396918dfc20SMatthew G. Knepley PetscCall(PetscBagRegisterScalar(bag, &p->q0, 1.0, "q0", "Charge Scale, A*s"));
1397918dfc20SMatthew G. Knepley PetscCall(PetscBagRegisterScalar(bag, &p->m0, 1.0, "m0", "Mass Scale, kg"));
1398918dfc20SMatthew G. Knepley PetscCall(PetscBagRegisterScalar(bag, &p->epsi0, 1.0, "epsi0", "Permittivity of Free Space, kg"));
1399918dfc20SMatthew G. Knepley PetscCall(PetscBagRegisterScalar(bag, &p->kb, 1.0, "kb", "Boltzmann Constant, m^2 kg/s^2 K^1"));
1400918dfc20SMatthew G. Knepley
1401918dfc20SMatthew G. Knepley PetscCall(PetscBagRegisterScalar(bag, &p->sigma, 1.0, "sigma", "Charge per unit area, C/m^3"));
1402918dfc20SMatthew G. Knepley PetscCall(PetscBagRegisterScalar(bag, &p->poissonNumber, 1.0, "poissonNumber", "Non-Dimensional Poisson Number"));
1403918dfc20SMatthew G. Knepley PetscCall(PetscBagRegisterScalar(bag, &p->vlasovNumber, 1.0, "vlasovNumber", "Non-Dimensional Vlasov Number"));
1404918dfc20SMatthew G. Knepley PetscCall(PetscBagSetFromOptions(bag));
1405918dfc20SMatthew G. Knepley {
1406918dfc20SMatthew G. Knepley PetscViewer viewer;
1407918dfc20SMatthew G. Knepley PetscViewerFormat format;
1408918dfc20SMatthew G. Knepley PetscBool flg;
1409918dfc20SMatthew G. Knepley
1410918dfc20SMatthew G. Knepley PetscCall(PetscOptionsCreateViewer(comm, NULL, NULL, "-param_view", &viewer, &format, &flg));
1411918dfc20SMatthew G. Knepley if (flg) {
1412918dfc20SMatthew G. Knepley PetscCall(PetscViewerPushFormat(viewer, format));
1413918dfc20SMatthew G. Knepley PetscCall(PetscBagView(bag, viewer));
1414918dfc20SMatthew G. Knepley PetscCall(PetscViewerFlush(viewer));
1415918dfc20SMatthew G. Knepley PetscCall(PetscViewerPopFormat(viewer));
1416918dfc20SMatthew G. Knepley PetscCall(PetscViewerDestroy(&viewer));
1417918dfc20SMatthew G. Knepley }
1418918dfc20SMatthew G. Knepley }
1419918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
1420918dfc20SMatthew G. Knepley }
1421918dfc20SMatthew G. Knepley
CreateMesh(MPI_Comm comm,AppCtx * ctx,DM * dm)1422*2a8381b2SBarry Smith static PetscErrorCode CreateMesh(MPI_Comm comm, AppCtx *ctx, DM *dm)
1423918dfc20SMatthew G. Knepley {
1424*2a8381b2SBarry Smith DMField coordField;
1425*2a8381b2SBarry Smith IS cellIS;
1426*2a8381b2SBarry Smith PetscQuadrature quad;
1427*2a8381b2SBarry Smith PetscReal *wt, *pt;
1428*2a8381b2SBarry Smith PetscInt cdim, cStart, cEnd;
1429*2a8381b2SBarry Smith
1430918dfc20SMatthew G. Knepley PetscFunctionBeginUser;
1431918dfc20SMatthew G. Knepley PetscCall(DMCreate(comm, dm));
1432918dfc20SMatthew G. Knepley PetscCall(DMSetType(*dm, DMPLEX));
1433918dfc20SMatthew G. Knepley PetscCall(DMSetFromOptions(*dm));
1434918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)*dm, "space"));
1435918dfc20SMatthew G. Knepley PetscCall(DMViewFromOptions(*dm, NULL, "-dm_view"));
1436918dfc20SMatthew G. Knepley
1437918dfc20SMatthew G. Knepley // Cache the mesh geometry
1438918dfc20SMatthew G. Knepley PetscCall(DMGetCoordinateField(*dm, &coordField));
1439918dfc20SMatthew G. Knepley PetscCheck(coordField, comm, PETSC_ERR_USER, "DM must have a coordinate field");
1440918dfc20SMatthew G. Knepley PetscCall(DMGetCoordinateDim(*dm, &cdim));
1441918dfc20SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(*dm, 0, &cStart, &cEnd));
1442918dfc20SMatthew G. Knepley PetscCall(ISCreateStride(PETSC_COMM_SELF, cEnd - cStart, cStart, 1, &cellIS));
1443918dfc20SMatthew G. Knepley PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, &quad));
1444918dfc20SMatthew G. Knepley PetscCall(PetscMalloc1(1, &wt));
1445918dfc20SMatthew G. Knepley PetscCall(PetscMalloc1(2, &pt));
1446918dfc20SMatthew G. Knepley wt[0] = 1.;
1447918dfc20SMatthew G. Knepley pt[0] = -1.;
1448918dfc20SMatthew G. Knepley pt[1] = -1.;
1449918dfc20SMatthew G. Knepley PetscCall(PetscQuadratureSetData(quad, cdim, 1, 1, pt, wt));
1450*2a8381b2SBarry Smith PetscCall(DMFieldCreateFEGeom(coordField, cellIS, quad, PETSC_FEGEOM_BASIC, &ctx->fegeom));
1451918dfc20SMatthew G. Knepley PetscCall(PetscQuadratureDestroy(&quad));
1452918dfc20SMatthew G. Knepley PetscCall(ISDestroy(&cellIS));
1453918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
1454918dfc20SMatthew G. Knepley }
1455918dfc20SMatthew G. Knepley
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[])1456918dfc20SMatthew G. Knepley 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[])
1457918dfc20SMatthew G. Knepley {
1458918dfc20SMatthew G. Knepley f0[0] = -constants[SIGMA];
1459918dfc20SMatthew G. Knepley }
1460918dfc20SMatthew G. Knepley
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[])1461918dfc20SMatthew G. Knepley 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[])
1462918dfc20SMatthew G. Knepley {
1463918dfc20SMatthew G. Knepley PetscInt d;
1464918dfc20SMatthew G. Knepley for (d = 0; d < dim; ++d) f1[d] = u_x[d];
1465918dfc20SMatthew G. Knepley }
1466918dfc20SMatthew G. Knepley
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[])1467918dfc20SMatthew G. Knepley 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[])
1468918dfc20SMatthew G. Knepley {
1469918dfc20SMatthew G. Knepley PetscInt d;
1470918dfc20SMatthew G. Knepley for (d = 0; d < dim; ++d) g3[d * dim + d] = 1.0;
1471918dfc20SMatthew G. Knepley }
1472918dfc20SMatthew G. Knepley
1473918dfc20SMatthew G. Knepley /*
1474918dfc20SMatthew G. Knepley / I -grad\ / q \ = /0\
1475918dfc20SMatthew G. Knepley \-div 0 / \phi/ \f/
1476918dfc20SMatthew G. Knepley */
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[])1477918dfc20SMatthew G. Knepley 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[])
1478918dfc20SMatthew G. Knepley {
1479918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) f0[d] += u[uOff[0] + d];
1480918dfc20SMatthew G. Knepley }
1481918dfc20SMatthew G. Knepley
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[])1482918dfc20SMatthew G. Knepley 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[])
1483918dfc20SMatthew G. Knepley {
1484918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) f1[d * dim + d] = u[uOff[1]];
1485918dfc20SMatthew G. Knepley }
1486918dfc20SMatthew G. Knepley
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[])1487918dfc20SMatthew G. Knepley 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[])
1488918dfc20SMatthew G. Knepley {
1489918dfc20SMatthew G. Knepley f0[0] += constants[SIGMA];
1490918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) f0[0] += u_x[uOff_x[0] + d * dim + d];
1491918dfc20SMatthew G. Knepley }
1492918dfc20SMatthew G. Knepley
1493918dfc20SMatthew G. Knepley /* 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[])1494918dfc20SMatthew G. Knepley 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[])
1495918dfc20SMatthew G. Knepley {
1496918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) g0[d * dim + d] = 1.0;
1497918dfc20SMatthew G. Knepley }
1498918dfc20SMatthew G. Knepley
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[])1499918dfc20SMatthew G. Knepley 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[])
1500918dfc20SMatthew G. Knepley {
1501918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) g2[d * dim + d] = 1.0;
1502918dfc20SMatthew G. Knepley }
1503918dfc20SMatthew G. Knepley
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[])1504918dfc20SMatthew G. Knepley 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[])
1505918dfc20SMatthew G. Knepley {
1506918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) g1[d * dim + d] = 1.0;
1507918dfc20SMatthew G. Knepley }
1508918dfc20SMatthew G. Knepley
CreateFEM(DM dm,AppCtx * ctx)1509*2a8381b2SBarry Smith static PetscErrorCode CreateFEM(DM dm, AppCtx *ctx)
1510918dfc20SMatthew G. Knepley {
1511918dfc20SMatthew G. Knepley PetscFE fephi, feq;
1512918dfc20SMatthew G. Knepley PetscDS ds;
1513918dfc20SMatthew G. Knepley PetscBool simplex;
1514918dfc20SMatthew G. Knepley PetscInt dim;
1515918dfc20SMatthew G. Knepley
1516918dfc20SMatthew G. Knepley PetscFunctionBeginUser;
1517918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(dm, &dim));
1518918dfc20SMatthew G. Knepley PetscCall(DMPlexIsSimplex(dm, &simplex));
1519*2a8381b2SBarry Smith if (ctx->em == EM_MIXED) {
1520918dfc20SMatthew G. Knepley DMLabel label;
1521918dfc20SMatthew G. Knepley const PetscInt id = 1;
1522918dfc20SMatthew G. Knepley
1523918dfc20SMatthew G. Knepley PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, dim, simplex, "field_", PETSC_DETERMINE, &feq));
1524918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)feq, "field"));
1525918dfc20SMatthew G. Knepley PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "potential_", PETSC_DETERMINE, &fephi));
1526918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)fephi, "potential"));
1527918dfc20SMatthew G. Knepley PetscCall(PetscFECopyQuadrature(feq, fephi));
1528918dfc20SMatthew G. Knepley PetscCall(DMSetField(dm, 0, NULL, (PetscObject)feq));
1529918dfc20SMatthew G. Knepley PetscCall(DMSetField(dm, 1, NULL, (PetscObject)fephi));
1530918dfc20SMatthew G. Knepley PetscCall(DMCreateDS(dm));
1531918dfc20SMatthew G. Knepley PetscCall(PetscFEDestroy(&fephi));
1532918dfc20SMatthew G. Knepley PetscCall(PetscFEDestroy(&feq));
1533918dfc20SMatthew G. Knepley
1534918dfc20SMatthew G. Knepley PetscCall(DMGetLabel(dm, "marker", &label));
1535918dfc20SMatthew G. Knepley PetscCall(DMGetDS(dm, &ds));
1536918dfc20SMatthew G. Knepley
1537918dfc20SMatthew G. Knepley PetscCall(PetscDSSetResidual(ds, 0, f0_q, f1_q));
1538918dfc20SMatthew G. Knepley PetscCall(PetscDSSetResidual(ds, 1, f0_phi_backgroundCharge, NULL));
1539918dfc20SMatthew G. Knepley PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_qq, NULL, NULL, NULL));
1540918dfc20SMatthew G. Knepley PetscCall(PetscDSSetJacobian(ds, 0, 1, NULL, NULL, g2_qphi, NULL));
1541918dfc20SMatthew G. Knepley PetscCall(PetscDSSetJacobian(ds, 1, 0, NULL, g1_phiq, NULL, NULL));
1542918dfc20SMatthew G. Knepley
154357d50842SBarry Smith PetscCall(DMAddBoundary(dm, DM_BC_ESSENTIAL, "wall", label, 1, &id, 0, 0, NULL, (PetscVoidFn *)zero, NULL, NULL, NULL));
1544918dfc20SMatthew G. Knepley
1545918dfc20SMatthew G. Knepley } else {
1546918dfc20SMatthew G. Knepley MatNullSpace nullsp;
1547918dfc20SMatthew G. Knepley PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, NULL, PETSC_DETERMINE, &fephi));
1548918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)fephi, "potential"));
1549918dfc20SMatthew G. Knepley PetscCall(DMSetField(dm, 0, NULL, (PetscObject)fephi));
1550918dfc20SMatthew G. Knepley PetscCall(DMCreateDS(dm));
1551918dfc20SMatthew G. Knepley PetscCall(DMGetDS(dm, &ds));
1552918dfc20SMatthew G. Knepley PetscCall(PetscDSSetResidual(ds, 0, ion_f0, laplacian_f1));
1553918dfc20SMatthew G. Knepley PetscCall(PetscDSSetJacobian(ds, 0, 0, NULL, NULL, NULL, laplacian_g3));
1554918dfc20SMatthew G. Knepley PetscCall(MatNullSpaceCreate(PetscObjectComm((PetscObject)dm), PETSC_TRUE, 0, NULL, &nullsp));
1555918dfc20SMatthew G. Knepley PetscCall(PetscObjectCompose((PetscObject)fephi, "nullspace", (PetscObject)nullsp));
1556918dfc20SMatthew G. Knepley PetscCall(MatNullSpaceDestroy(&nullsp));
1557918dfc20SMatthew G. Knepley PetscCall(PetscFEDestroy(&fephi));
1558918dfc20SMatthew G. Knepley }
1559918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
1560918dfc20SMatthew G. Knepley }
1561918dfc20SMatthew G. Knepley
CreatePoisson(DM dm,AppCtx * ctx)1562*2a8381b2SBarry Smith static PetscErrorCode CreatePoisson(DM dm, AppCtx *ctx)
1563918dfc20SMatthew G. Knepley {
1564918dfc20SMatthew G. Knepley SNES snes;
1565918dfc20SMatthew G. Knepley Mat J;
1566918dfc20SMatthew G. Knepley MatNullSpace nullSpace;
1567918dfc20SMatthew G. Knepley
1568918dfc20SMatthew G. Knepley PetscFunctionBeginUser;
1569*2a8381b2SBarry Smith PetscCall(CreateFEM(dm, ctx));
1570918dfc20SMatthew G. Knepley PetscCall(SNESCreate(PetscObjectComm((PetscObject)dm), &snes));
1571918dfc20SMatthew G. Knepley PetscCall(SNESSetOptionsPrefix(snes, "em_"));
1572918dfc20SMatthew G. Knepley PetscCall(SNESSetDM(snes, dm));
1573*2a8381b2SBarry Smith PetscCall(DMPlexSetSNESLocalFEM(dm, PETSC_FALSE, ctx));
1574918dfc20SMatthew G. Knepley PetscCall(SNESSetFromOptions(snes));
1575918dfc20SMatthew G. Knepley
1576918dfc20SMatthew G. Knepley PetscCall(DMCreateMatrix(dm, &J));
1577918dfc20SMatthew G. Knepley PetscCall(MatNullSpaceCreate(PetscObjectComm((PetscObject)dm), PETSC_TRUE, 0, NULL, &nullSpace));
1578918dfc20SMatthew G. Knepley PetscCall(MatSetNullSpace(J, nullSpace));
1579918dfc20SMatthew G. Knepley PetscCall(MatNullSpaceDestroy(&nullSpace));
1580918dfc20SMatthew G. Knepley PetscCall(SNESSetJacobian(snes, J, J, NULL, NULL));
1581918dfc20SMatthew G. Knepley PetscCall(MatDestroy(&J));
1582*2a8381b2SBarry Smith if (ctx->em == EM_MIXED) {
1583918dfc20SMatthew G. Knepley const PetscInt potential = 1;
1584918dfc20SMatthew G. Knepley
1585*2a8381b2SBarry Smith PetscCall(DMCreateSubDM(dm, 1, &potential, &ctx->isPot, &ctx->dmPot));
1586918dfc20SMatthew G. Knepley } else {
1587*2a8381b2SBarry Smith ctx->dmPot = dm;
1588*2a8381b2SBarry Smith PetscCall(PetscObjectReference((PetscObject)ctx->dmPot));
1589918dfc20SMatthew G. Knepley }
1590*2a8381b2SBarry Smith PetscCall(DMCreateMassMatrix(ctx->dmPot, ctx->dmPot, &ctx->M));
1591918dfc20SMatthew G. Knepley PetscCall(DMPlexCreateClosureIndex(dm, NULL));
1592*2a8381b2SBarry Smith ctx->snes = snes;
1593918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
1594918dfc20SMatthew G. Knepley }
1595918dfc20SMatthew G. Knepley
1596918dfc20SMatthew G. Knepley // Conservation of mass (m = 1.0)
1597918dfc20SMatthew G. Knepley // n_t + 1/ m p_x = 0
f0_mass(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[])1598918dfc20SMatthew G. Knepley static void f0_mass(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[])
1599918dfc20SMatthew G. Knepley {
1600918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) f0[0] += u_t[uOff[0]] + u_x[uOff_x[1] + d * dim + d];
1601918dfc20SMatthew G. Knepley }
1602918dfc20SMatthew G. Knepley
1603918dfc20SMatthew G. Knepley // Conservation of momentum (m = 1, e = 1)
1604918dfc20SMatthew G. Knepley // p_t + (u p)_x = -pr_x + e n E
1605918dfc20SMatthew G. Knepley // p_t + (div u) p + u . grad p = -pr_x + e n E
1606918dfc20SMatthew G. Knepley // p_t + (div p) p / n - (p . grad n) p / n^2 + p / n . grad p = -pr_x + e n E
f0_momentum(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[])1607918dfc20SMatthew G. Knepley static void f0_momentum(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[])
1608918dfc20SMatthew G. Knepley {
1609918dfc20SMatthew G. Knepley const PetscScalar n = u[uOff[0]];
1610918dfc20SMatthew G. Knepley
1611918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) {
1612918dfc20SMatthew G. Knepley PetscReal divp = 0.;
1613918dfc20SMatthew G. Knepley
1614918dfc20SMatthew G. Knepley f0[d] += u_t[uOff[1] + d];
1615918dfc20SMatthew G. Knepley for (PetscInt e = 0; e < dim; ++e) {
1616918dfc20SMatthew G. Knepley f0[d] += u[uOff[1] + e] * u_x[uOff_x[1] + d * dim + e] / n; // p / n . grad p
1617918dfc20SMatthew G. Knepley f0[d] -= (u[uOff[1] + e] * u_x[uOff_x[0] + e]) * u[uOff[1] + d] / PetscSqr(n); // -(p . grad n) p / n^2
1618918dfc20SMatthew G. Knepley divp += u_x[uOff_x[1] + e * dim + e];
1619918dfc20SMatthew G. Knepley }
1620918dfc20SMatthew G. Knepley f0[d] += divp * u[uOff[1] + d] / n; // (div p) p / n
1621918dfc20SMatthew G. Knepley f0[d] += u_x[uOff_x[2] + d]; // pr_x
1622918dfc20SMatthew G. Knepley f0[d] -= n * a[d]; // -e n E
1623918dfc20SMatthew G. Knepley }
1624918dfc20SMatthew G. Knepley }
1625918dfc20SMatthew G. Knepley
1626918dfc20SMatthew G. Knepley // Conservation of energy
1627918dfc20SMatthew G. Knepley // pr_t + (u pr)_x = -3 pr u_x - q_x
1628918dfc20SMatthew G. Knepley // pr_t + (div u) pr + u . grad pr = -3 pr (div u) - q_x
1629918dfc20SMatthew G. Knepley // pr_t + 4 (div u) pr + u . grad pr = -q_x
1630918dfc20SMatthew G. Knepley // pr_t + 4 div p pr / n - 4 (p . grad n) pr / n^2 + p . grad pr / n = -q_x
f0_energy(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[])1631918dfc20SMatthew G. Knepley static void f0_energy(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[])
1632918dfc20SMatthew G. Knepley {
1633918dfc20SMatthew G. Knepley const PetscScalar n = u[uOff[0]];
1634918dfc20SMatthew G. Knepley const PetscScalar pr = u[uOff[2]];
1635918dfc20SMatthew G. Knepley PetscReal divp = 0.;
1636918dfc20SMatthew G. Knepley
1637918dfc20SMatthew G. Knepley f0[0] += u_t[uOff[2]];
1638918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) {
1639918dfc20SMatthew G. Knepley f0[0] += u[uOff[1] + d] * u_x[uOff_x[2] + d] / n; // p . grad pr / n
1640918dfc20SMatthew G. Knepley f0[0] -= 4. * u[uOff[1] + d] * u_x[uOff_x[0] + d] * pr / PetscSqr(n); // -4 (p . grad n) pr / n^2
1641918dfc20SMatthew G. Knepley divp += u_x[uOff_x[1] + d * dim + d];
1642918dfc20SMatthew G. Knepley }
1643918dfc20SMatthew G. Knepley f0[0] += 4. * divp * pr / n; // 4 div p pr / n
1644918dfc20SMatthew G. Knepley }
1645918dfc20SMatthew G. Knepley
SetupMomentProblem(DM dm,AppCtx * ctx)1646918dfc20SMatthew G. Knepley static PetscErrorCode SetupMomentProblem(DM dm, AppCtx *ctx)
1647918dfc20SMatthew G. Knepley {
1648918dfc20SMatthew G. Knepley PetscDS ds;
1649918dfc20SMatthew G. Knepley
1650918dfc20SMatthew G. Knepley PetscFunctionBegin;
1651918dfc20SMatthew G. Knepley PetscCall(DMGetDS(dm, &ds));
1652918dfc20SMatthew G. Knepley PetscCall(PetscDSSetResidual(ds, 0, f0_mass, NULL));
1653918dfc20SMatthew G. Knepley PetscCall(PetscDSSetResidual(ds, 1, f0_momentum, NULL));
1654918dfc20SMatthew G. Knepley PetscCall(PetscDSSetResidual(ds, 2, f0_energy, NULL));
1655918dfc20SMatthew G. Knepley //PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_mass_uu, NULL, NULL, NULL));
1656918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
1657918dfc20SMatthew G. Knepley }
1658918dfc20SMatthew G. Knepley
CreateMomentFields(DM odm,AppCtx * ctx)1659*2a8381b2SBarry Smith static PetscErrorCode CreateMomentFields(DM odm, AppCtx *ctx)
1660918dfc20SMatthew G. Knepley {
1661918dfc20SMatthew G. Knepley DM dm;
1662918dfc20SMatthew G. Knepley PetscFE fe;
1663918dfc20SMatthew G. Knepley DMPolytopeType ct;
1664918dfc20SMatthew G. Knepley PetscInt dim, cStart;
1665918dfc20SMatthew G. Knepley
1666918dfc20SMatthew G. Knepley PetscFunctionBeginUser;
1667918dfc20SMatthew G. Knepley PetscCall(DMClone(odm, &dm));
1668918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(dm, &dim));
1669918dfc20SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, NULL));
1670918dfc20SMatthew G. Knepley PetscCall(DMPlexGetCellType(dm, cStart, &ct));
1671918dfc20SMatthew G. Knepley PetscCall(PetscFECreateByCell(PETSC_COMM_SELF, dim, 1, ct, NULL, PETSC_DETERMINE, &fe));
1672918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)fe, "number density"));
1673918dfc20SMatthew G. Knepley PetscCall(DMSetField(dm, 0, NULL, (PetscObject)fe));
1674918dfc20SMatthew G. Knepley PetscCall(PetscFEDestroy(&fe));
1675918dfc20SMatthew G. Knepley PetscCall(PetscFECreateByCell(PETSC_COMM_SELF, dim, dim, ct, NULL, PETSC_DETERMINE, &fe));
1676918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)fe, "momentum density"));
1677918dfc20SMatthew G. Knepley PetscCall(DMSetField(dm, 1, NULL, (PetscObject)fe));
1678918dfc20SMatthew G. Knepley PetscCall(PetscFEDestroy(&fe));
1679918dfc20SMatthew G. Knepley PetscCall(PetscFECreateByCell(PETSC_COMM_SELF, dim, 1, ct, NULL, PETSC_DETERMINE, &fe));
1680918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)fe, "energy density"));
1681918dfc20SMatthew G. Knepley PetscCall(DMSetField(dm, 2, NULL, (PetscObject)fe));
1682918dfc20SMatthew G. Knepley PetscCall(PetscFEDestroy(&fe));
1683918dfc20SMatthew G. Knepley PetscCall(DMCreateDS(dm));
1684*2a8381b2SBarry Smith PetscCall(SetupMomentProblem(dm, ctx));
1685*2a8381b2SBarry Smith ctx->dmMom = dm;
1686918dfc20SMatthew G. Knepley PetscInt field;
1687918dfc20SMatthew G. Knepley
1688918dfc20SMatthew G. Knepley field = 0;
1689*2a8381b2SBarry Smith PetscCall(DMCreateSubDM(ctx->dmMom, 1, &field, &ctx->isN, &ctx->dmN));
1690*2a8381b2SBarry Smith PetscCall(DMCreateMassMatrix(ctx->dmN, ctx->dmN, &ctx->MN));
1691918dfc20SMatthew G. Knepley field = 1;
1692*2a8381b2SBarry Smith PetscCall(DMCreateSubDM(ctx->dmMom, 1, &field, &ctx->isP, &ctx->dmP));
1693*2a8381b2SBarry Smith PetscCall(DMCreateMassMatrix(ctx->dmP, ctx->dmP, &ctx->MP));
1694918dfc20SMatthew G. Knepley field = 2;
1695*2a8381b2SBarry Smith PetscCall(DMCreateSubDM(ctx->dmMom, 1, &field, &ctx->isE, &ctx->dmE));
1696*2a8381b2SBarry Smith PetscCall(DMCreateMassMatrix(ctx->dmE, ctx->dmE, &ctx->ME));
1697918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
1698918dfc20SMatthew G. Knepley }
1699918dfc20SMatthew G. Knepley
PetscPDFPertubedConstant2D(const PetscReal x[],const PetscReal dummy[],PetscReal p[])1700918dfc20SMatthew G. Knepley PetscErrorCode PetscPDFPertubedConstant2D(const PetscReal x[], const PetscReal dummy[], PetscReal p[])
1701918dfc20SMatthew G. Knepley {
1702918dfc20SMatthew G. Knepley p[0] = (1 + 0.01 * PetscCosReal(0.5 * x[0])) / (2 * PETSC_PI);
1703918dfc20SMatthew G. Knepley p[1] = (1 + 0.01 * PetscCosReal(0.5 * x[1])) / (2 * PETSC_PI);
1704918dfc20SMatthew G. Knepley return PETSC_SUCCESS;
1705918dfc20SMatthew G. Knepley }
PetscPDFPertubedConstant1D(const PetscReal x[],const PetscReal dummy[],PetscReal p[])1706918dfc20SMatthew G. Knepley PetscErrorCode PetscPDFPertubedConstant1D(const PetscReal x[], const PetscReal dummy[], PetscReal p[])
1707918dfc20SMatthew G. Knepley {
1708918dfc20SMatthew G. Knepley p[0] = (1. + 0.01 * PetscCosReal(0.5 * x[0])) / (2 * PETSC_PI);
1709918dfc20SMatthew G. Knepley return PETSC_SUCCESS;
1710918dfc20SMatthew G. Knepley }
1711918dfc20SMatthew G. Knepley
PetscPDFCosine1D(const PetscReal x[],const PetscReal scale[],PetscReal p[])1712918dfc20SMatthew G. Knepley PetscErrorCode PetscPDFCosine1D(const PetscReal x[], const PetscReal scale[], PetscReal p[])
1713918dfc20SMatthew G. Knepley {
1714918dfc20SMatthew G. Knepley const PetscReal alpha = scale ? scale[0] : 0.0;
1715918dfc20SMatthew G. Knepley const PetscReal k = scale ? scale[1] : 1.;
1716918dfc20SMatthew G. Knepley p[0] = (1 + alpha * PetscCosReal(k * x[0]));
1717918dfc20SMatthew G. Knepley return PETSC_SUCCESS;
1718918dfc20SMatthew G. Knepley }
1719918dfc20SMatthew G. Knepley
PetscPDFCosine2D(const PetscReal x[],const PetscReal scale[],PetscReal p[])1720918dfc20SMatthew G. Knepley PetscErrorCode PetscPDFCosine2D(const PetscReal x[], const PetscReal scale[], PetscReal p[])
1721918dfc20SMatthew G. Knepley {
1722918dfc20SMatthew G. Knepley const PetscReal alpha = scale ? scale[0] : 0.;
1723918dfc20SMatthew G. Knepley const PetscReal k = scale ? scale[0] : 1.;
1724918dfc20SMatthew G. Knepley p[0] = (1 + alpha * PetscCosReal(k * (x[0] + x[1])));
1725918dfc20SMatthew G. Knepley return PETSC_SUCCESS;
1726918dfc20SMatthew G. Knepley }
1727918dfc20SMatthew G. Knepley
CreateVelocityDM(DM sw,DM * vdm)1728918dfc20SMatthew G. Knepley static PetscErrorCode CreateVelocityDM(DM sw, DM *vdm)
1729918dfc20SMatthew G. Knepley {
1730918dfc20SMatthew G. Knepley PetscFE fe;
1731918dfc20SMatthew G. Knepley DMPolytopeType ct;
1732918dfc20SMatthew G. Knepley PetscInt dim, cStart;
1733918dfc20SMatthew G. Knepley const char *prefix = "v";
1734918dfc20SMatthew G. Knepley
1735918dfc20SMatthew G. Knepley PetscFunctionBegin;
1736918dfc20SMatthew G. Knepley PetscCall(DMCreate(PETSC_COMM_SELF, vdm));
1737918dfc20SMatthew G. Knepley PetscCall(DMSetType(*vdm, DMPLEX));
1738918dfc20SMatthew G. Knepley PetscCall(DMPlexSetOptionsPrefix(*vdm, prefix));
1739918dfc20SMatthew G. Knepley PetscCall(DMSetFromOptions(*vdm));
1740918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)*vdm, "velocity"));
1741918dfc20SMatthew G. Knepley PetscCall(DMViewFromOptions(*vdm, NULL, "-dm_view"));
1742918dfc20SMatthew G. Knepley
1743918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(*vdm, &dim));
1744918dfc20SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(*vdm, 0, &cStart, NULL));
1745918dfc20SMatthew G. Knepley PetscCall(DMPlexGetCellType(*vdm, cStart, &ct));
1746918dfc20SMatthew G. Knepley PetscCall(PetscFECreateByCell(PETSC_COMM_SELF, dim, 1, ct, prefix, PETSC_DETERMINE, &fe));
1747918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)fe, "distribution"));
1748918dfc20SMatthew G. Knepley PetscCall(DMSetField(*vdm, 0, NULL, (PetscObject)fe));
1749918dfc20SMatthew G. Knepley PetscCall(DMCreateDS(*vdm));
1750918dfc20SMatthew G. Knepley PetscCall(PetscFEDestroy(&fe));
1751918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
1752918dfc20SMatthew G. Knepley }
1753918dfc20SMatthew G. Knepley
1754918dfc20SMatthew G. Knepley /*
1755918dfc20SMatthew G. Knepley InitializeParticles_Centroid - Initialize a regular grid of particles.
1756918dfc20SMatthew G. Knepley
1757918dfc20SMatthew G. Knepley Input Parameters:
1758918dfc20SMatthew G. Knepley + sw - The `DMSWARM`
1759918dfc20SMatthew G. Knepley - force1D - Treat the spatial domain as 1D
1760918dfc20SMatthew G. Knepley
1761918dfc20SMatthew G. Knepley Notes:
1762918dfc20SMatthew G. Knepley This functions sets the species, cellid, spatial coordinate, and velocity fields for all particles.
1763918dfc20SMatthew G. Knepley
1764918dfc20SMatthew G. Knepley It places one particle in the centroid of each cell in the implicit tensor product of the spatial
1765918dfc20SMatthew G. Knepley and velocity meshes.
1766918dfc20SMatthew G. Knepley */
InitializeParticles_Centroid(DM sw)1767918dfc20SMatthew G. Knepley static PetscErrorCode InitializeParticles_Centroid(DM sw)
1768918dfc20SMatthew G. Knepley {
1769918dfc20SMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)sw->data;
1770918dfc20SMatthew G. Knepley DMSwarmCellDM celldm;
1771918dfc20SMatthew G. Knepley DM xdm, vdm;
1772918dfc20SMatthew G. Knepley PetscReal vmin[3], vmax[3];
1773918dfc20SMatthew G. Knepley PetscReal *x, *v;
1774918dfc20SMatthew G. Knepley PetscInt *species, *cellid;
1775918dfc20SMatthew G. Knepley PetscInt dim, xcStart, xcEnd, vcStart, vcEnd, Ns, Np, Npc, debug;
1776918dfc20SMatthew G. Knepley PetscBool flg;
1777918dfc20SMatthew G. Knepley MPI_Comm comm;
1778918dfc20SMatthew G. Knepley const char *cellidname;
1779918dfc20SMatthew G. Knepley
1780918dfc20SMatthew G. Knepley PetscFunctionBegin;
1781918dfc20SMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)sw, &comm));
1782918dfc20SMatthew G. Knepley
1783918dfc20SMatthew G. Knepley PetscOptionsBegin(comm, "", "DMSwarm Options", "DMSWARM");
1784918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetNumSpecies(sw, &Ns));
1785f14fce1bSMatthew G. Knepley PetscCall(PetscOptionsInt("-dm_swarm_num_species", "The number of species", "DMSwarmSetNumSpecies", Ns, &Ns, &flg));
1786918dfc20SMatthew G. Knepley if (flg) PetscCall(DMSwarmSetNumSpecies(sw, Ns));
1787918dfc20SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_swarm_print_coords", "Debug output level for particle coordinate computations", "InitializeParticles", 0, &swarm->printCoords, NULL, 0));
1788918dfc20SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_swarm_print_weights", "Debug output level for particle weight computations", "InitializeWeights", 0, &swarm->printWeights, NULL, 0));
1789918dfc20SMatthew G. Knepley PetscOptionsEnd();
1790918dfc20SMatthew G. Knepley debug = swarm->printCoords;
1791918dfc20SMatthew G. Knepley
1792918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim));
1793918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetCellDM(sw, &xdm));
1794918dfc20SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(xdm, 0, &xcStart, &xcEnd));
1795918dfc20SMatthew G. Knepley
1796918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetCellDMByName(sw, "velocity", &celldm));
1797918dfc20SMatthew G. Knepley PetscCall(DMSwarmCellDMGetDM(celldm, &vdm));
1798918dfc20SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(vdm, 0, &vcStart, &vcEnd));
1799918dfc20SMatthew G. Knepley
1800918dfc20SMatthew G. Knepley // One particle per centroid on the tensor product grid
1801918dfc20SMatthew G. Knepley Npc = (vcEnd - vcStart) * Ns;
1802918dfc20SMatthew G. Knepley Np = (xcEnd - xcStart) * Npc;
1803918dfc20SMatthew G. Knepley PetscCall(DMSwarmSetLocalSizes(sw, Np, 0));
1804918dfc20SMatthew G. Knepley if (debug) {
1805918dfc20SMatthew G. Knepley PetscInt gNp, gNc, Nc = xcEnd - xcStart;
1806918dfc20SMatthew G. Knepley PetscCallMPI(MPIU_Allreduce(&Np, &gNp, 1, MPIU_INT, MPIU_SUM, comm));
1807918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(comm, "Global Np = %" PetscInt_FMT "\n", gNp));
1808918dfc20SMatthew G. Knepley PetscCallMPI(MPIU_Allreduce(&Nc, &gNc, 1, MPIU_INT, MPIU_SUM, comm));
1809918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(comm, "Global X-cells = %" PetscInt_FMT "\n", gNc));
1810918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(comm, "Global V-cells = %" PetscInt_FMT "\n", vcEnd - vcStart));
1811918dfc20SMatthew G. Knepley }
1812918dfc20SMatthew G. Knepley
1813918dfc20SMatthew G. Knepley // Set species and cellid
1814918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetCellDMActive(sw, &celldm));
1815918dfc20SMatthew G. Knepley PetscCall(DMSwarmCellDMGetCellID(celldm, &cellidname));
1816918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "species", NULL, NULL, (void **)&species));
1817918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, cellidname, NULL, NULL, (void **)&cellid));
1818918dfc20SMatthew G. Knepley for (PetscInt c = 0, p = 0; c < xcEnd - xcStart; ++c) {
1819918dfc20SMatthew G. Knepley for (PetscInt s = 0; s < Ns; ++s) {
1820918dfc20SMatthew G. Knepley for (PetscInt q = 0; q < Npc / Ns; ++q, ++p) {
1821918dfc20SMatthew G. Knepley species[p] = s;
1822918dfc20SMatthew G. Knepley cellid[p] = c;
1823918dfc20SMatthew G. Knepley }
1824918dfc20SMatthew G. Knepley }
1825918dfc20SMatthew G. Knepley }
1826918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "species", NULL, NULL, (void **)&species));
1827918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, cellidname, NULL, NULL, (void **)&cellid));
1828918dfc20SMatthew G. Knepley
1829918dfc20SMatthew G. Knepley // Set particle coordinates
1830918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&x));
1831918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "velocity", NULL, NULL, (void **)&v));
1832918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortGetAccess(sw));
1833918dfc20SMatthew G. Knepley PetscCall(DMGetBoundingBox(vdm, vmin, vmax));
1834918dfc20SMatthew G. Knepley PetscCall(DMGetCoordinatesLocalSetUp(xdm));
1835918dfc20SMatthew G. Knepley for (PetscInt c = 0; c < xcEnd - xcStart; ++c) {
1836918dfc20SMatthew G. Knepley const PetscInt cell = c + xcStart;
1837918dfc20SMatthew G. Knepley PetscInt *pidx, Npc;
1838918dfc20SMatthew G. Knepley PetscReal centroid[3], volume;
1839918dfc20SMatthew G. Knepley
1840918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortGetPointsPerCell(sw, c, &Npc, &pidx));
1841918dfc20SMatthew G. Knepley PetscCall(DMPlexComputeCellGeometryFVM(xdm, cell, &volume, centroid, NULL));
1842918dfc20SMatthew G. Knepley for (PetscInt s = 0; s < Ns; ++s) {
1843918dfc20SMatthew G. Knepley for (PetscInt q = 0; q < Npc / Ns; ++q) {
1844918dfc20SMatthew G. Knepley const PetscInt p = pidx[q * Ns + s];
1845918dfc20SMatthew G. Knepley
1846918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) {
1847918dfc20SMatthew G. Knepley x[p * dim + d] = centroid[d];
1848918dfc20SMatthew G. Knepley v[p * dim + d] = vmin[0] + (q + 0.5) * ((vmax[0] - vmin[0]) / (Npc / Ns));
1849918dfc20SMatthew G. Knepley }
1850918dfc20SMatthew G. Knepley if (debug > 1) {
1851918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, "Particle %4" PetscInt_FMT " ", p));
1852918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, " x: ("));
1853918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) {
1854918dfc20SMatthew G. Knepley if (d > 0) PetscCall(PetscPrintf(PETSC_COMM_SELF, ", "));
1855918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, "%g", x[p * dim + d]));
1856918dfc20SMatthew G. Knepley }
1857918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, ") v:("));
1858918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) {
1859918dfc20SMatthew G. Knepley if (d > 0) PetscCall(PetscPrintf(PETSC_COMM_SELF, ", "));
1860918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, "%g", v[p * dim + d]));
1861918dfc20SMatthew G. Knepley }
1862918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, ")\n"));
1863918dfc20SMatthew G. Knepley }
1864918dfc20SMatthew G. Knepley }
1865918dfc20SMatthew G. Knepley }
1866918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(sw, c, &Npc, &pidx));
1867918dfc20SMatthew G. Knepley }
1868918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortRestoreAccess(sw));
1869918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&x));
1870918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "velocity", NULL, NULL, (void **)&v));
1871918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
1872918dfc20SMatthew G. Knepley }
1873918dfc20SMatthew G. Knepley
1874918dfc20SMatthew G. Knepley /*
1875918dfc20SMatthew G. Knepley InitializeWeights - Compute weight for each local particle
1876918dfc20SMatthew G. Knepley
1877918dfc20SMatthew G. Knepley Input Parameters:
1878918dfc20SMatthew G. Knepley + sw - The `DMSwarm`
1879918dfc20SMatthew G. Knepley . totalWeight - The sum of all particle weights
1880918dfc20SMatthew G. Knepley . func - The PDF for the particle spatial distribution
1881918dfc20SMatthew G. Knepley - param - The PDF parameters
1882918dfc20SMatthew G. Knepley
1883918dfc20SMatthew G. Knepley Notes:
1884918dfc20SMatthew G. Knepley The PDF for velocity is assumed to be a Gaussian
1885918dfc20SMatthew G. Knepley
1886918dfc20SMatthew G. Knepley The particle weights are returned in the `w_q` field of `sw`.
1887918dfc20SMatthew G. Knepley */
InitializeWeights(DM sw,PetscReal totalWeight,PetscProbFn * func,const PetscReal param[])1888918dfc20SMatthew G. Knepley static PetscErrorCode InitializeWeights(DM sw, PetscReal totalWeight, PetscProbFn *func, const PetscReal param[])
1889918dfc20SMatthew G. Knepley {
1890918dfc20SMatthew G. Knepley DM xdm, vdm;
1891918dfc20SMatthew G. Knepley DMSwarmCellDM celldm;
1892918dfc20SMatthew G. Knepley PetscScalar *weight;
1893918dfc20SMatthew G. Knepley PetscQuadrature xquad;
1894918dfc20SMatthew G. Knepley const PetscReal *xq, *xwq;
1895918dfc20SMatthew G. Knepley const PetscInt order = 5;
1896918dfc20SMatthew G. Knepley PetscReal xi0[3];
1897918dfc20SMatthew G. Knepley PetscReal xwtot = 0., pwtot = 0.;
1898918dfc20SMatthew G. Knepley PetscInt xNq;
1899918dfc20SMatthew G. Knepley PetscInt dim, Ns, xcStart, xcEnd, vcStart, vcEnd, debug = ((DM_Swarm *)sw->data)->printWeights;
1900918dfc20SMatthew G. Knepley MPI_Comm comm;
1901918dfc20SMatthew G. Knepley PetscMPIInt rank;
1902918dfc20SMatthew G. Knepley
1903918dfc20SMatthew G. Knepley PetscFunctionBegin;
1904918dfc20SMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)sw, &comm));
1905918dfc20SMatthew G. Knepley PetscCallMPI(MPI_Comm_rank(comm, &rank));
1906918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim));
1907918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetCellDM(sw, &xdm));
1908918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetNumSpecies(sw, &Ns));
1909918dfc20SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(xdm, 0, &xcStart, &xcEnd));
1910918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetCellDMByName(sw, "velocity", &celldm));
1911918dfc20SMatthew G. Knepley PetscCall(DMSwarmCellDMGetDM(celldm, &vdm));
1912918dfc20SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(vdm, 0, &vcStart, &vcEnd));
1913918dfc20SMatthew G. Knepley
1914918dfc20SMatthew G. Knepley // Setup Quadrature for spatial and velocity weight calculations
1915918dfc20SMatthew G. Knepley PetscCall(PetscDTGaussTensorQuadrature(dim, 1, order, -1.0, 1.0, &xquad));
1916918dfc20SMatthew G. Knepley PetscCall(PetscQuadratureGetData(xquad, NULL, NULL, &xNq, &xq, &xwq));
1917918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) xi0[d] = -1.0;
1918918dfc20SMatthew G. Knepley
1919918dfc20SMatthew G. Knepley // Integrate the density function to get the weights of particles in each cell
1920918dfc20SMatthew G. Knepley PetscCall(DMGetCoordinatesLocalSetUp(vdm));
1921918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortGetAccess(sw));
1922918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "w_q", NULL, NULL, (void **)&weight));
1923918dfc20SMatthew G. Knepley for (PetscInt c = xcStart; c < xcEnd; ++c) {
1924918dfc20SMatthew G. Knepley PetscReal xv0[3], xJ[9], xinvJ[9], xdetJ, xqr[3], xden, xw = 0.;
1925918dfc20SMatthew G. Knepley PetscInt *pidx, Npc;
1926918dfc20SMatthew G. Knepley PetscInt xNc;
1927918dfc20SMatthew G. Knepley const PetscScalar *xarray;
1928918dfc20SMatthew G. Knepley PetscScalar *xcoords = NULL;
1929918dfc20SMatthew G. Knepley PetscBool xisDG;
1930918dfc20SMatthew G. Knepley
1931918dfc20SMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(xdm, c, &xisDG, &xNc, &xarray, &xcoords));
1932918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortGetPointsPerCell(sw, c, &Npc, &pidx));
1933918dfc20SMatthew 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);
1934918dfc20SMatthew G. Knepley PetscCall(DMPlexComputeCellGeometryFEM(xdm, c, NULL, xv0, xJ, xinvJ, &xdetJ));
1935918dfc20SMatthew G. Knepley for (PetscInt q = 0; q < xNq; ++q) {
1936918dfc20SMatthew G. Knepley // Transform quadrature points from ref space to real space
1937918dfc20SMatthew G. Knepley CoordinatesRefToReal(dim, dim, xi0, xv0, xJ, &xq[q * dim], xqr);
1938918dfc20SMatthew G. Knepley // Get probability density at quad point
1939918dfc20SMatthew G. Knepley // No need to scale xqr since PDF will be periodic
1940918dfc20SMatthew G. Knepley PetscCall((*func)(xqr, param, &xden));
1941918dfc20SMatthew G. Knepley xw += xden * (xwq[q] * xdetJ);
1942918dfc20SMatthew G. Knepley }
1943918dfc20SMatthew G. Knepley xwtot += xw;
1944918dfc20SMatthew G. Knepley if (debug) {
1945918dfc20SMatthew G. Knepley IS globalOrdering;
1946918dfc20SMatthew G. Knepley const PetscInt *ordering;
1947918dfc20SMatthew G. Knepley
1948918dfc20SMatthew G. Knepley PetscCall(DMPlexGetCellNumbering(xdm, &globalOrdering));
1949918dfc20SMatthew G. Knepley PetscCall(ISGetIndices(globalOrdering, &ordering));
1950918dfc20SMatthew 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));
1951918dfc20SMatthew G. Knepley PetscCall(ISRestoreIndices(globalOrdering, &ordering));
1952918dfc20SMatthew G. Knepley }
1953918dfc20SMatthew G. Knepley // Set weights to be Gaussian in velocity cells
1954918dfc20SMatthew G. Knepley for (PetscInt vc = vcStart; vc < vcEnd; ++vc) {
1955918dfc20SMatthew G. Knepley const PetscInt p = pidx[vc * Ns + 0];
1956918dfc20SMatthew G. Knepley PetscReal vw = 0.;
1957918dfc20SMatthew G. Knepley PetscInt vNc;
1958918dfc20SMatthew G. Knepley const PetscScalar *varray;
1959918dfc20SMatthew G. Knepley PetscScalar *vcoords = NULL;
1960918dfc20SMatthew G. Knepley PetscBool visDG;
1961918dfc20SMatthew G. Knepley
1962918dfc20SMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(vdm, vc, &visDG, &vNc, &varray, &vcoords));
1963918dfc20SMatthew G. Knepley // TODO: Fix 2 stream Ask Joe
1964918dfc20SMatthew G. Knepley // Two stream function from 1/2pi v^2 e^(-v^2/2)
1965918dfc20SMatthew 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.)));
1966918dfc20SMatthew G. Knepley vw = 0.5 * (PetscErfReal(vcoords[1] / PetscSqrtReal(2.)) - PetscErfReal(vcoords[0] / PetscSqrtReal(2.)));
1967918dfc20SMatthew G. Knepley
1968918dfc20SMatthew G. Knepley weight[p] = totalWeight * vw * xw;
1969918dfc20SMatthew G. Knepley pwtot += weight[p];
1970918dfc20SMatthew G. Knepley PetscCheck(weight[p] <= 10., PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Particle %" PetscInt_FMT " weight exceeded 1: %g, %g, %g", p, xw, vw, totalWeight);
1971918dfc20SMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(vdm, vc, &visDG, &vNc, &varray, &vcoords));
1972918dfc20SMatthew G. Knepley if (debug > 1) PetscCall(PetscPrintf(comm, "particle %" PetscInt_FMT ": %g, vw: %g xw: %g\n", p, weight[p], vw, xw));
1973918dfc20SMatthew G. Knepley }
1974918dfc20SMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(xdm, c, &xisDG, &xNc, &xarray, &xcoords));
1975918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(sw, c, &Npc, &pidx));
1976918dfc20SMatthew G. Knepley }
1977918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "w_q", NULL, NULL, (void **)&weight));
1978918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortRestoreAccess(sw));
1979918dfc20SMatthew G. Knepley PetscCall(PetscQuadratureDestroy(&xquad));
1980918dfc20SMatthew G. Knepley
1981918dfc20SMatthew G. Knepley if (debug) {
1982918dfc20SMatthew G. Knepley PetscReal wtot[2] = {pwtot, xwtot}, gwtot[2];
1983918dfc20SMatthew G. Knepley
1984918dfc20SMatthew G. Knepley PetscCall(PetscSynchronizedFlush(comm, NULL));
1985918dfc20SMatthew G. Knepley PetscCallMPI(MPIU_Allreduce(wtot, gwtot, 2, MPIU_REAL, MPIU_SUM, PETSC_COMM_WORLD));
1986918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(comm, "particle weight sum = %1.10f cell weight sum = %1.10f\n", (double)gwtot[0], (double)gwtot[1]));
1987918dfc20SMatthew G. Knepley }
1988918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
1989918dfc20SMatthew G. Knepley }
1990918dfc20SMatthew G. Knepley
InitializeParticles_PerturbedWeights(DM sw,AppCtx * ctx)1991*2a8381b2SBarry Smith static PetscErrorCode InitializeParticles_PerturbedWeights(DM sw, AppCtx *ctx)
1992918dfc20SMatthew G. Knepley {
1993*2a8381b2SBarry Smith PetscReal scale[2] = {ctx->cosine_coefficients[0], ctx->cosine_coefficients[1]};
1994918dfc20SMatthew G. Knepley PetscInt dim;
1995918dfc20SMatthew G. Knepley
1996918dfc20SMatthew G. Knepley PetscFunctionBegin;
1997918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim));
1998918dfc20SMatthew G. Knepley PetscCall(InitializeParticles_Centroid(sw));
1999*2a8381b2SBarry Smith PetscCall(InitializeWeights(sw, ctx->totalWeight, dim == 1 ? PetscPDFCosine1D : PetscPDFCosine2D, scale));
2000918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
2001918dfc20SMatthew G. Knepley }
2002918dfc20SMatthew G. Knepley
InitializeConstants(DM sw,AppCtx * ctx)2003*2a8381b2SBarry Smith static PetscErrorCode InitializeConstants(DM sw, AppCtx *ctx)
2004918dfc20SMatthew G. Knepley {
2005918dfc20SMatthew G. Knepley DM dm;
2006918dfc20SMatthew G. Knepley PetscInt *species;
2007918dfc20SMatthew G. Knepley PetscReal *weight, totalCharge = 0., totalWeight = 0., gmin[3], gmax[3], global_charge, global_weight;
2008918dfc20SMatthew G. Knepley PetscInt Np, dim;
2009918dfc20SMatthew G. Knepley
2010918dfc20SMatthew G. Knepley PetscFunctionBegin;
2011918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetCellDM(sw, &dm));
2012918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim));
2013918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(sw, &Np));
2014918dfc20SMatthew G. Knepley PetscCall(DMGetBoundingBox(dm, gmin, gmax));
2015918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "w_q", NULL, NULL, (void **)&weight));
2016918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "species", NULL, NULL, (void **)&species));
2017918dfc20SMatthew G. Knepley for (PetscInt p = 0; p < Np; ++p) {
2018918dfc20SMatthew G. Knepley totalWeight += weight[p];
2019*2a8381b2SBarry Smith totalCharge += ctx->charges[species[p]] * weight[p];
2020918dfc20SMatthew G. Knepley }
2021918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "w_q", NULL, NULL, (void **)&weight));
2022918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "species", NULL, NULL, (void **)&species));
2023918dfc20SMatthew G. Knepley {
2024918dfc20SMatthew G. Knepley Parameter *param;
2025918dfc20SMatthew G. Knepley PetscReal Area;
2026918dfc20SMatthew G. Knepley
2027*2a8381b2SBarry Smith PetscCall(PetscBagGetData(ctx->bag, ¶m));
2028918dfc20SMatthew G. Knepley switch (dim) {
2029918dfc20SMatthew G. Knepley case 1:
2030918dfc20SMatthew G. Knepley Area = (gmax[0] - gmin[0]);
2031918dfc20SMatthew G. Knepley break;
2032918dfc20SMatthew G. Knepley case 2:
2033918dfc20SMatthew G. Knepley Area = (gmax[0] - gmin[0]) * (gmax[1] - gmin[1]);
2034918dfc20SMatthew G. Knepley break;
2035918dfc20SMatthew G. Knepley case 3:
2036918dfc20SMatthew G. Knepley Area = (gmax[0] - gmin[0]) * (gmax[1] - gmin[1]) * (gmax[2] - gmin[2]);
2037918dfc20SMatthew G. Knepley break;
2038918dfc20SMatthew G. Knepley default:
2039918dfc20SMatthew G. Knepley SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Dimension %" PetscInt_FMT " not supported", dim);
2040918dfc20SMatthew G. Knepley }
2041918dfc20SMatthew G. Knepley PetscCallMPI(MPIU_Allreduce(&totalWeight, &global_weight, 1, MPIU_REAL, MPIU_SUM, PETSC_COMM_WORLD));
2042918dfc20SMatthew G. Knepley PetscCallMPI(MPIU_Allreduce(&totalCharge, &global_charge, 1, MPIU_REAL, MPIU_SUM, PETSC_COMM_WORLD));
2043*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));
2044918dfc20SMatthew G. Knepley param->sigma = PetscAbsReal(global_charge / (Area));
2045918dfc20SMatthew G. Knepley
2046918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_WORLD, "sigma: %g\n", (double)param->sigma));
2047918dfc20SMatthew G. Knepley 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,
2048918dfc20SMatthew G. Knepley (double)param->vlasovNumber));
2049918dfc20SMatthew G. Knepley }
2050918dfc20SMatthew G. Knepley /* Setup Constants */
2051918dfc20SMatthew G. Knepley {
2052918dfc20SMatthew G. Knepley PetscDS ds;
2053918dfc20SMatthew G. Knepley Parameter *param;
2054*2a8381b2SBarry Smith PetscCall(PetscBagGetData(ctx->bag, ¶m));
2055918dfc20SMatthew G. Knepley PetscScalar constants[NUM_CONSTANTS];
2056918dfc20SMatthew G. Knepley constants[SIGMA] = param->sigma;
2057918dfc20SMatthew G. Knepley constants[V0] = param->v0;
2058918dfc20SMatthew G. Knepley constants[T0] = param->t0;
2059918dfc20SMatthew G. Knepley constants[X0] = param->x0;
2060918dfc20SMatthew G. Knepley constants[M0] = param->m0;
2061918dfc20SMatthew G. Knepley constants[Q0] = param->q0;
2062918dfc20SMatthew G. Knepley constants[PHI0] = param->phi0;
2063918dfc20SMatthew G. Knepley constants[POISSON] = param->poissonNumber;
2064918dfc20SMatthew G. Knepley constants[VLASOV] = param->vlasovNumber;
2065918dfc20SMatthew G. Knepley PetscCall(DMGetDS(dm, &ds));
2066918dfc20SMatthew G. Knepley PetscCall(PetscDSSetConstants(ds, NUM_CONSTANTS, constants));
2067918dfc20SMatthew G. Knepley }
2068918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
2069918dfc20SMatthew G. Knepley }
2070918dfc20SMatthew G. Knepley
CreateSwarm(DM dm,AppCtx * ctx,DM * sw)2071*2a8381b2SBarry Smith static PetscErrorCode CreateSwarm(DM dm, AppCtx *ctx, DM *sw)
2072918dfc20SMatthew G. Knepley {
2073918dfc20SMatthew G. Knepley DMSwarmCellDM celldm;
2074918dfc20SMatthew G. Knepley DM vdm;
2075918dfc20SMatthew G. Knepley PetscReal v0[2] = {1., 0.};
2076918dfc20SMatthew G. Knepley PetscInt dim;
2077918dfc20SMatthew G. Knepley
2078918dfc20SMatthew G. Knepley PetscFunctionBeginUser;
2079918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(dm, &dim));
2080918dfc20SMatthew G. Knepley PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), sw));
2081918dfc20SMatthew G. Knepley PetscCall(DMSetType(*sw, DMSWARM));
2082918dfc20SMatthew G. Knepley PetscCall(DMSetDimension(*sw, dim));
2083918dfc20SMatthew G. Knepley PetscCall(DMSwarmSetType(*sw, DMSWARM_PIC));
2084*2a8381b2SBarry Smith PetscCall(DMSetApplicationContext(*sw, ctx));
2085918dfc20SMatthew G. Knepley
2086918dfc20SMatthew G. Knepley PetscCall(DMSwarmRegisterPetscDatatypeField(*sw, "w_q", 1, PETSC_SCALAR));
2087918dfc20SMatthew G. Knepley PetscCall(DMSwarmRegisterPetscDatatypeField(*sw, "velocity", dim, PETSC_REAL));
2088918dfc20SMatthew G. Knepley PetscCall(DMSwarmRegisterPetscDatatypeField(*sw, "species", 1, PETSC_INT));
2089918dfc20SMatthew G. Knepley PetscCall(DMSwarmRegisterPetscDatatypeField(*sw, "E_field", dim, PETSC_REAL));
2090918dfc20SMatthew G. Knepley
2091918dfc20SMatthew G. Knepley const char *fieldnames[2] = {DMSwarmPICField_coor, "velocity"};
2092918dfc20SMatthew G. Knepley
2093918dfc20SMatthew G. Knepley PetscCall(DMSwarmCellDMCreate(dm, 2, fieldnames, 1, fieldnames, &celldm));
2094918dfc20SMatthew G. Knepley PetscCall(DMSwarmAddCellDM(*sw, celldm));
2095918dfc20SMatthew G. Knepley PetscCall(DMSwarmCellDMDestroy(&celldm));
2096918dfc20SMatthew G. Knepley
2097918dfc20SMatthew G. Knepley const char *vfieldnames[2] = {"w_q"};
2098918dfc20SMatthew G. Knepley
2099918dfc20SMatthew G. Knepley PetscCall(CreateVelocityDM(*sw, &vdm));
2100918dfc20SMatthew G. Knepley PetscCall(DMSwarmCellDMCreate(vdm, 1, vfieldnames, 1, &fieldnames[1], &celldm));
2101918dfc20SMatthew G. Knepley PetscCall(DMSwarmAddCellDM(*sw, celldm));
2102918dfc20SMatthew G. Knepley PetscCall(DMSwarmCellDMDestroy(&celldm));
2103918dfc20SMatthew G. Knepley PetscCall(DMDestroy(&vdm));
2104918dfc20SMatthew G. Knepley
2105918dfc20SMatthew G. Knepley DM mdm;
2106918dfc20SMatthew G. Knepley
2107918dfc20SMatthew G. Knepley PetscCall(DMClone(dm, &mdm));
2108918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)mdm, "moments"));
2109918dfc20SMatthew G. Knepley PetscCall(DMCopyDisc(dm, mdm));
2110918dfc20SMatthew G. Knepley PetscCall(DMSwarmCellDMCreate(mdm, 1, vfieldnames, 1, fieldnames, &celldm));
2111918dfc20SMatthew G. Knepley PetscCall(DMDestroy(&mdm));
2112918dfc20SMatthew G. Knepley PetscCall(DMSwarmAddCellDM(*sw, celldm));
2113918dfc20SMatthew G. Knepley PetscCall(DMSwarmCellDMDestroy(&celldm));
2114918dfc20SMatthew G. Knepley
2115918dfc20SMatthew G. Knepley DM mfdm;
2116918dfc20SMatthew G. Knepley
2117918dfc20SMatthew G. Knepley PetscCall(DMClone(dm, &mfdm));
2118918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)mfdm, "moment fields"));
2119918dfc20SMatthew G. Knepley PetscCall(DMCopyDisc(dm, mfdm));
2120918dfc20SMatthew G. Knepley PetscCall(DMSwarmCellDMCreate(mfdm, 1, &fieldnames[1], 1, fieldnames, &celldm));
2121918dfc20SMatthew G. Knepley PetscCall(DMDestroy(&mfdm));
2122918dfc20SMatthew G. Knepley PetscCall(DMSwarmAddCellDM(*sw, celldm));
2123918dfc20SMatthew G. Knepley PetscCall(DMSwarmCellDMDestroy(&celldm));
2124918dfc20SMatthew G. Knepley
2125918dfc20SMatthew G. Knepley PetscCall(DMSetFromOptions(*sw));
2126918dfc20SMatthew G. Knepley PetscCall(DMSetUp(*sw));
2127918dfc20SMatthew G. Knepley
2128918dfc20SMatthew G. Knepley PetscCall(DMSwarmSetCellDMActive(*sw, "space"));
2129*2a8381b2SBarry Smith ctx->swarm = *sw;
2130918dfc20SMatthew G. Knepley // TODO: This is redundant init since it is done in InitializeSolveAndSwarm, however DMSetUp() requires the local size be set
2131*2a8381b2SBarry Smith if (ctx->perturbed_weights) {
2132*2a8381b2SBarry Smith PetscCall(InitializeParticles_PerturbedWeights(*sw, ctx));
2133918dfc20SMatthew G. Knepley } else {
2134918dfc20SMatthew G. Knepley PetscCall(DMSwarmComputeLocalSizeFromOptions(*sw));
2135918dfc20SMatthew G. Knepley PetscCall(DMSwarmInitializeCoordinates(*sw));
2136918dfc20SMatthew G. Knepley PetscCall(DMSwarmInitializeVelocitiesFromOptions(*sw, v0));
2137918dfc20SMatthew G. Knepley }
2138918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)*sw, "Particles"));
2139918dfc20SMatthew G. Knepley PetscCall(DMViewFromOptions(*sw, NULL, "-sw_view"));
2140918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
2141918dfc20SMatthew G. Knepley }
2142918dfc20SMatthew G. Knepley
ComputeFieldAtParticles_Coulomb(SNES snes,DM sw,PetscReal E[])2143918dfc20SMatthew G. Knepley static PetscErrorCode ComputeFieldAtParticles_Coulomb(SNES snes, DM sw, PetscReal E[])
2144918dfc20SMatthew G. Knepley {
2145*2a8381b2SBarry Smith AppCtx *ctx;
2146918dfc20SMatthew G. Knepley PetscReal *coords;
2147918dfc20SMatthew G. Knepley PetscInt *species, dim, Np, Ns;
2148918dfc20SMatthew G. Knepley PetscMPIInt size;
2149918dfc20SMatthew G. Knepley
2150918dfc20SMatthew G. Knepley PetscFunctionBegin;
2151918dfc20SMatthew G. Knepley PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)snes), &size));
2152918dfc20SMatthew G. Knepley PetscCheck(size == 1, PetscObjectComm((PetscObject)snes), PETSC_ERR_SUP, "Coulomb code only works in serial");
2153918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim));
2154918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(sw, &Np));
2155918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetNumSpecies(sw, &Ns));
2156*2a8381b2SBarry Smith PetscCall(DMGetApplicationContext(sw, &ctx));
2157918dfc20SMatthew G. Knepley
2158918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
2159918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "species", NULL, NULL, (void **)&species));
2160918dfc20SMatthew G. Knepley for (PetscInt p = 0; p < Np; ++p) {
2161918dfc20SMatthew G. Knepley PetscReal *pcoord = &coords[p * dim];
2162918dfc20SMatthew G. Knepley PetscReal pE[3] = {0., 0., 0.};
2163918dfc20SMatthew G. Knepley
2164918dfc20SMatthew G. Knepley /* Calculate field at particle p due to particle q */
2165918dfc20SMatthew G. Knepley for (PetscInt q = 0; q < Np; ++q) {
2166918dfc20SMatthew G. Knepley PetscReal *qcoord = &coords[q * dim];
2167918dfc20SMatthew G. Knepley PetscReal rpq[3], r, r3, q_q;
2168918dfc20SMatthew G. Knepley
2169918dfc20SMatthew G. Knepley if (p == q) continue;
2170*2a8381b2SBarry Smith q_q = ctx->charges[species[q]] * 1.;
2171918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) rpq[d] = pcoord[d] - qcoord[d];
2172918dfc20SMatthew G. Knepley r = DMPlex_NormD_Internal(dim, rpq);
2173918dfc20SMatthew G. Knepley if (r < PETSC_SQRT_MACHINE_EPSILON) continue;
2174918dfc20SMatthew G. Knepley r3 = PetscPowRealInt(r, 3);
2175918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) pE[d] += q_q * rpq[d] / r3;
2176918dfc20SMatthew G. Knepley }
2177918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) E[p * dim + d] = pE[d];
2178918dfc20SMatthew G. Knepley }
2179918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "species", NULL, NULL, (void **)&species));
2180918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
2181918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
2182918dfc20SMatthew G. Knepley }
2183918dfc20SMatthew G. Knepley
ComputeFieldAtParticles_Primal(SNES snes,DM sw,Mat M_p,PetscReal E[])2184918dfc20SMatthew G. Knepley static PetscErrorCode ComputeFieldAtParticles_Primal(SNES snes, DM sw, Mat M_p, PetscReal E[])
2185918dfc20SMatthew G. Knepley {
2186918dfc20SMatthew G. Knepley DM dm;
2187*2a8381b2SBarry Smith AppCtx *ctx;
2188918dfc20SMatthew G. Knepley PetscDS ds;
2189918dfc20SMatthew G. Knepley PetscFE fe;
2190918dfc20SMatthew G. Knepley KSP ksp;
2191918dfc20SMatthew G. Knepley Vec rhoRhs; // Weak charge density, \int phi_i rho
2192918dfc20SMatthew G. Knepley Vec rho; // Charge density, M^{-1} rhoRhs
2193918dfc20SMatthew G. Knepley Vec phi, locPhi; // Potential
2194918dfc20SMatthew G. Knepley Vec f; // Particle weights
2195918dfc20SMatthew G. Knepley PetscReal *coords;
2196918dfc20SMatthew G. Knepley PetscInt dim, cStart, cEnd, Np;
2197918dfc20SMatthew G. Knepley
2198918dfc20SMatthew G. Knepley PetscFunctionBegin;
2199*2a8381b2SBarry Smith PetscCall(DMGetApplicationContext(sw, &ctx));
2200*2a8381b2SBarry Smith PetscCall(PetscLogEventBegin(ctx->ESolveEvent, snes, sw, 0, 0));
2201918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim));
2202918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(sw, &Np));
2203918dfc20SMatthew G. Knepley
2204918dfc20SMatthew G. Knepley PetscCall(SNESGetDM(snes, &dm));
2205918dfc20SMatthew G. Knepley PetscCall(DMGetGlobalVector(dm, &rhoRhs));
2206918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)rhoRhs, "Weak charge density"));
2207*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmPot, "rho", &rho));
2208918dfc20SMatthew G. Knepley PetscCall(DMSwarmCreateGlobalVectorFromField(sw, "w_q", &f));
2209918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)f, "particle weight"));
2210918dfc20SMatthew G. Knepley
2211918dfc20SMatthew G. Knepley PetscCall(MatViewFromOptions(M_p, NULL, "-mp_view"));
2212*2a8381b2SBarry Smith PetscCall(MatViewFromOptions(ctx->M, NULL, "-m_view"));
2213918dfc20SMatthew G. Knepley PetscCall(VecViewFromOptions(f, NULL, "-weights_view"));
2214918dfc20SMatthew G. Knepley
2215918dfc20SMatthew G. Knepley PetscCall(MatMultTranspose(M_p, f, rhoRhs));
2216918dfc20SMatthew G. Knepley PetscCall(DMSwarmDestroyGlobalVectorFromField(sw, "w_q", &f));
2217918dfc20SMatthew G. Knepley
2218918dfc20SMatthew G. Knepley PetscCall(KSPCreate(PetscObjectComm((PetscObject)dm), &ksp));
2219918dfc20SMatthew G. Knepley PetscCall(KSPSetOptionsPrefix(ksp, "em_proj_"));
2220*2a8381b2SBarry Smith PetscCall(KSPSetOperators(ksp, ctx->M, ctx->M));
2221918dfc20SMatthew G. Knepley PetscCall(KSPSetFromOptions(ksp));
2222918dfc20SMatthew G. Knepley PetscCall(KSPSolve(ksp, rhoRhs, rho));
2223918dfc20SMatthew G. Knepley
2224918dfc20SMatthew G. Knepley PetscCall(VecScale(rhoRhs, -1.0));
2225918dfc20SMatthew G. Knepley
2226918dfc20SMatthew G. Knepley PetscCall(VecViewFromOptions(rhoRhs, NULL, "-rho_view"));
2227*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmPot, "rho", &rho));
2228918dfc20SMatthew G. Knepley PetscCall(KSPDestroy(&ksp));
2229918dfc20SMatthew G. Knepley
2230*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmPot, "phi", &phi));
2231918dfc20SMatthew G. Knepley PetscCall(VecSet(phi, 0.0));
2232918dfc20SMatthew G. Knepley PetscCall(SNESSolve(snes, rhoRhs, phi));
2233918dfc20SMatthew G. Knepley PetscCall(DMRestoreGlobalVector(dm, &rhoRhs));
2234918dfc20SMatthew G. Knepley PetscCall(VecViewFromOptions(phi, NULL, "-phi_view"));
2235918dfc20SMatthew G. Knepley
2236918dfc20SMatthew G. Knepley PetscCall(DMGetLocalVector(dm, &locPhi));
2237918dfc20SMatthew G. Knepley PetscCall(DMGlobalToLocalBegin(dm, phi, INSERT_VALUES, locPhi));
2238918dfc20SMatthew G. Knepley PetscCall(DMGlobalToLocalEnd(dm, phi, INSERT_VALUES, locPhi));
2239*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmPot, "phi", &phi));
2240*2a8381b2SBarry Smith PetscCall(PetscLogEventEnd(ctx->ESolveEvent, snes, sw, 0, 0));
2241918dfc20SMatthew G. Knepley
2242918dfc20SMatthew G. Knepley PetscCall(DMGetDS(dm, &ds));
2243918dfc20SMatthew G. Knepley PetscCall(PetscDSGetDiscretization(ds, 0, (PetscObject *)&fe));
2244918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortGetAccess(sw));
2245918dfc20SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
2246918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
2247918dfc20SMatthew G. Knepley
2248*2a8381b2SBarry Smith PetscCall(PetscLogEventBegin(ctx->ETabEvent, snes, sw, 0, 0));
2249918dfc20SMatthew G. Knepley PetscTabulation tab;
2250918dfc20SMatthew G. Knepley PetscReal *pcoord, *refcoord;
2251918dfc20SMatthew G. Knepley PetscFEGeom *chunkgeom = NULL;
2252918dfc20SMatthew G. Knepley PetscInt maxNcp = 0;
2253918dfc20SMatthew G. Knepley
2254918dfc20SMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) {
2255918dfc20SMatthew G. Knepley PetscInt Ncp;
2256918dfc20SMatthew G. Knepley
2257918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortGetNumberOfPointsPerCell(sw, c, &Ncp));
2258918dfc20SMatthew G. Knepley maxNcp = PetscMax(maxNcp, Ncp);
2259918dfc20SMatthew G. Knepley }
2260918dfc20SMatthew G. Knepley PetscCall(DMGetWorkArray(dm, maxNcp * dim, MPIU_REAL, &refcoord));
2261918dfc20SMatthew G. Knepley PetscCall(DMGetWorkArray(dm, maxNcp * dim, MPIU_REAL, &pcoord));
2262918dfc20SMatthew G. Knepley // This can raise an FP_INEXACT in the dgemm inside
2263918dfc20SMatthew G. Knepley PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
2264918dfc20SMatthew G. Knepley PetscCall(PetscFECreateTabulation(fe, 1, maxNcp, refcoord, 1, &tab));
2265918dfc20SMatthew G. Knepley PetscCall(PetscFPTrapPop());
2266918dfc20SMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) {
2267918dfc20SMatthew G. Knepley PetscScalar *clPhi = NULL;
2268918dfc20SMatthew G. Knepley PetscInt *points;
2269918dfc20SMatthew G. Knepley PetscInt Ncp;
2270918dfc20SMatthew G. Knepley
2271918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortGetPointsPerCell(sw, c, &Ncp, &points));
2272918dfc20SMatthew G. Knepley for (PetscInt cp = 0; cp < Ncp; ++cp)
2273918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) pcoord[cp * dim + d] = coords[points[cp] * dim + d];
2274918dfc20SMatthew G. Knepley {
2275*2a8381b2SBarry Smith PetscCall(PetscFEGeomGetChunk(ctx->fegeom, c - cStart, c - cStart + 1, &chunkgeom));
2276918dfc20SMatthew G. Knepley for (PetscInt i = 0; i < Ncp; ++i) {
2277918dfc20SMatthew G. Knepley const PetscReal x0[3] = {-1., -1., -1.};
2278918dfc20SMatthew G. Knepley CoordinatesRealToRef(dim, dim, x0, chunkgeom->v, chunkgeom->invJ, &pcoord[dim * i], &refcoord[dim * i]);
2279918dfc20SMatthew G. Knepley }
2280918dfc20SMatthew G. Knepley }
2281918dfc20SMatthew G. Knepley PetscCall(PetscFEComputeTabulation(fe, Ncp, refcoord, 1, tab));
2282918dfc20SMatthew G. Knepley PetscCall(DMPlexVecGetClosure(dm, NULL, locPhi, c, NULL, &clPhi));
2283918dfc20SMatthew G. Knepley for (PetscInt cp = 0; cp < Ncp; ++cp) {
2284918dfc20SMatthew G. Knepley const PetscReal *basisDer = tab->T[1];
2285918dfc20SMatthew G. Knepley const PetscInt p = points[cp];
2286918dfc20SMatthew G. Knepley
2287918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) E[p * dim + d] = 0.;
2288918dfc20SMatthew G. Knepley PetscCall(PetscFEFreeInterpolateGradient_Static(fe, basisDer, clPhi, dim, chunkgeom->invJ, NULL, cp, &E[p * dim]));
2289918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) E[p * dim + d] *= -1.0;
2290918dfc20SMatthew G. Knepley }
2291918dfc20SMatthew G. Knepley PetscCall(DMPlexVecRestoreClosure(dm, NULL, locPhi, c, NULL, &clPhi));
2292918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(sw, c, &Ncp, &points));
2293918dfc20SMatthew G. Knepley }
2294918dfc20SMatthew G. Knepley PetscCall(DMRestoreWorkArray(dm, maxNcp * dim, MPIU_REAL, &pcoord));
2295918dfc20SMatthew G. Knepley PetscCall(DMRestoreWorkArray(dm, maxNcp * dim, MPIU_REAL, &refcoord));
2296918dfc20SMatthew G. Knepley PetscCall(PetscTabulationDestroy(&tab));
2297918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
2298918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortRestoreAccess(sw));
2299918dfc20SMatthew G. Knepley PetscCall(DMRestoreLocalVector(dm, &locPhi));
2300*2a8381b2SBarry Smith PetscCall(PetscFEGeomRestoreChunk(ctx->fegeom, 0, 1, &chunkgeom));
2301*2a8381b2SBarry Smith PetscCall(PetscLogEventEnd(ctx->ETabEvent, snes, sw, 0, 0));
2302918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
2303918dfc20SMatthew G. Knepley }
2304918dfc20SMatthew G. Knepley
ComputeFieldAtParticles_Mixed(SNES snes,DM sw,Mat M_p,PetscReal E[])2305918dfc20SMatthew G. Knepley static PetscErrorCode ComputeFieldAtParticles_Mixed(SNES snes, DM sw, Mat M_p, PetscReal E[])
2306918dfc20SMatthew G. Knepley {
2307918dfc20SMatthew G. Knepley DM dm;
2308*2a8381b2SBarry Smith AppCtx *ctx;
2309918dfc20SMatthew G. Knepley PetscDS ds;
2310918dfc20SMatthew G. Knepley PetscFE fe;
2311918dfc20SMatthew G. Knepley KSP ksp;
2312918dfc20SMatthew G. Knepley Vec rhoRhs, rhoRhsFull; // Weak charge density, \int phi_i rho, and embedding in mixed problem
2313918dfc20SMatthew G. Knepley Vec rho; // Charge density, M^{-1} rhoRhs
2314918dfc20SMatthew G. Knepley Vec phi, locPhi, phiFull; // Potential and embedding in mixed problem
2315918dfc20SMatthew G. Knepley Vec f; // Particle weights
2316918dfc20SMatthew G. Knepley PetscReal *coords;
2317918dfc20SMatthew G. Knepley PetscInt dim, cStart, cEnd, Np;
2318918dfc20SMatthew G. Knepley
2319918dfc20SMatthew G. Knepley PetscFunctionBegin;
2320*2a8381b2SBarry Smith PetscCall(DMGetApplicationContext(sw, &ctx));
2321*2a8381b2SBarry Smith PetscCall(PetscLogEventBegin(ctx->ESolveEvent, snes, sw, 0, 0));
2322918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim));
2323918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(sw, &Np));
2324918dfc20SMatthew G. Knepley
2325918dfc20SMatthew G. Knepley PetscCall(SNESGetDM(snes, &dm));
2326*2a8381b2SBarry Smith PetscCall(DMGetGlobalVector(ctx->dmPot, &rhoRhs));
2327918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)rhoRhs, "Weak charge density"));
2328918dfc20SMatthew G. Knepley PetscCall(DMGetGlobalVector(dm, &rhoRhsFull));
2329918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)rhoRhsFull, "Weak charge density"));
2330*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmPot, "rho", &rho));
2331918dfc20SMatthew G. Knepley PetscCall(DMSwarmCreateGlobalVectorFromField(sw, "w_q", &f));
2332918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)f, "particle weight"));
2333918dfc20SMatthew G. Knepley
2334918dfc20SMatthew G. Knepley PetscCall(MatViewFromOptions(M_p, NULL, "-mp_view"));
2335*2a8381b2SBarry Smith PetscCall(MatViewFromOptions(ctx->M, NULL, "-m_view"));
2336918dfc20SMatthew G. Knepley PetscCall(VecViewFromOptions(f, NULL, "-weights_view"));
2337918dfc20SMatthew G. Knepley
2338918dfc20SMatthew G. Knepley PetscCall(MatMultTranspose(M_p, f, rhoRhs));
2339918dfc20SMatthew G. Knepley PetscCall(DMSwarmDestroyGlobalVectorFromField(sw, "w_q", &f));
2340918dfc20SMatthew G. Knepley
2341918dfc20SMatthew G. Knepley PetscCall(KSPCreate(PetscObjectComm((PetscObject)dm), &ksp));
2342918dfc20SMatthew G. Knepley PetscCall(KSPSetOptionsPrefix(ksp, "em_proj"));
2343*2a8381b2SBarry Smith PetscCall(KSPSetOperators(ksp, ctx->M, ctx->M));
2344918dfc20SMatthew G. Knepley PetscCall(KSPSetFromOptions(ksp));
2345918dfc20SMatthew G. Knepley PetscCall(KSPSolve(ksp, rhoRhs, rho));
2346918dfc20SMatthew G. Knepley
2347*2a8381b2SBarry Smith PetscCall(VecISCopy(rhoRhsFull, ctx->isPot, SCATTER_FORWARD, rhoRhs));
2348918dfc20SMatthew G. Knepley //PetscCall(VecScale(rhoRhsFull, -1.0));
2349918dfc20SMatthew G. Knepley
2350918dfc20SMatthew G. Knepley PetscCall(VecViewFromOptions(rhoRhs, NULL, "-rho_view"));
2351918dfc20SMatthew G. Knepley PetscCall(VecViewFromOptions(rhoRhsFull, NULL, "-rho_full_view"));
2352*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmPot, "rho", &rho));
2353*2a8381b2SBarry Smith PetscCall(DMRestoreGlobalVector(ctx->dmPot, &rhoRhs));
2354918dfc20SMatthew G. Knepley PetscCall(KSPDestroy(&ksp));
2355918dfc20SMatthew G. Knepley
2356918dfc20SMatthew G. Knepley PetscCall(DMGetGlobalVector(dm, &phiFull));
2357*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmPot, "phi", &phi));
2358918dfc20SMatthew G. Knepley PetscCall(VecSet(phiFull, 0.0));
2359918dfc20SMatthew G. Knepley PetscCall(SNESSolve(snes, rhoRhsFull, phiFull));
2360918dfc20SMatthew G. Knepley PetscCall(DMRestoreGlobalVector(dm, &rhoRhsFull));
2361918dfc20SMatthew G. Knepley PetscCall(VecViewFromOptions(phi, NULL, "-phi_view"));
2362918dfc20SMatthew G. Knepley
2363*2a8381b2SBarry Smith PetscCall(VecISCopy(phiFull, ctx->isPot, SCATTER_REVERSE, phi));
2364*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmPot, "phi", &phi));
2365918dfc20SMatthew G. Knepley
2366918dfc20SMatthew G. Knepley PetscCall(DMGetLocalVector(dm, &locPhi));
2367918dfc20SMatthew G. Knepley PetscCall(DMGlobalToLocalBegin(dm, phiFull, INSERT_VALUES, locPhi));
2368918dfc20SMatthew G. Knepley PetscCall(DMGlobalToLocalEnd(dm, phiFull, INSERT_VALUES, locPhi));
2369918dfc20SMatthew G. Knepley PetscCall(DMRestoreGlobalVector(dm, &phiFull));
2370*2a8381b2SBarry Smith PetscCall(PetscLogEventEnd(ctx->ESolveEvent, snes, sw, 0, 0));
2371918dfc20SMatthew G. Knepley
2372918dfc20SMatthew G. Knepley PetscCall(DMGetDS(dm, &ds));
2373918dfc20SMatthew G. Knepley PetscCall(PetscDSGetDiscretization(ds, 0, (PetscObject *)&fe));
2374918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortGetAccess(sw));
2375918dfc20SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
2376918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
2377918dfc20SMatthew G. Knepley
2378*2a8381b2SBarry Smith PetscCall(PetscLogEventBegin(ctx->ETabEvent, snes, sw, 0, 0));
2379918dfc20SMatthew G. Knepley PetscTabulation tab;
2380918dfc20SMatthew G. Knepley PetscReal *pcoord, *refcoord;
2381918dfc20SMatthew G. Knepley PetscFEGeom *chunkgeom = NULL;
2382918dfc20SMatthew G. Knepley PetscInt maxNcp = 0;
2383918dfc20SMatthew G. Knepley
2384918dfc20SMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) {
2385918dfc20SMatthew G. Knepley PetscInt Ncp;
2386918dfc20SMatthew G. Knepley
2387918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortGetNumberOfPointsPerCell(sw, c, &Ncp));
2388918dfc20SMatthew G. Knepley maxNcp = PetscMax(maxNcp, Ncp);
2389918dfc20SMatthew G. Knepley }
2390918dfc20SMatthew G. Knepley PetscCall(DMGetWorkArray(dm, maxNcp * dim, MPIU_REAL, &refcoord));
2391918dfc20SMatthew G. Knepley PetscCall(DMGetWorkArray(dm, maxNcp * dim, MPIU_REAL, &pcoord));
2392918dfc20SMatthew G. Knepley PetscCall(PetscFECreateTabulation(fe, 1, maxNcp, refcoord, 1, &tab));
2393918dfc20SMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) {
2394918dfc20SMatthew G. Knepley PetscScalar *clPhi = NULL;
2395918dfc20SMatthew G. Knepley PetscInt *points;
2396918dfc20SMatthew G. Knepley PetscInt Ncp;
2397918dfc20SMatthew G. Knepley
2398918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortGetPointsPerCell(sw, c, &Ncp, &points));
2399918dfc20SMatthew G. Knepley for (PetscInt cp = 0; cp < Ncp; ++cp)
2400918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) pcoord[cp * dim + d] = coords[points[cp] * dim + d];
2401918dfc20SMatthew G. Knepley {
2402*2a8381b2SBarry Smith PetscCall(PetscFEGeomGetChunk(ctx->fegeom, c - cStart, c - cStart + 1, &chunkgeom));
2403918dfc20SMatthew G. Knepley for (PetscInt i = 0; i < Ncp; ++i) {
2404918dfc20SMatthew G. Knepley const PetscReal x0[3] = {-1., -1., -1.};
2405918dfc20SMatthew G. Knepley CoordinatesRealToRef(dim, dim, x0, chunkgeom->v, chunkgeom->invJ, &pcoord[dim * i], &refcoord[dim * i]);
2406918dfc20SMatthew G. Knepley }
2407918dfc20SMatthew G. Knepley }
2408918dfc20SMatthew G. Knepley PetscCall(PetscFEComputeTabulation(fe, Ncp, refcoord, 1, tab));
2409918dfc20SMatthew G. Knepley PetscCall(DMPlexVecGetClosure(dm, NULL, locPhi, c, NULL, &clPhi));
2410918dfc20SMatthew G. Knepley for (PetscInt cp = 0; cp < Ncp; ++cp) {
2411918dfc20SMatthew G. Knepley const PetscInt p = points[cp];
2412918dfc20SMatthew G. Knepley
2413918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) E[p * dim + d] = 0.;
2414918dfc20SMatthew G. Knepley PetscCall(PetscFEInterpolateAtPoints_Static(fe, tab, clPhi, chunkgeom, cp, &E[p * dim]));
2415918dfc20SMatthew G. Knepley PetscCall(PetscFEPushforward(fe, chunkgeom, 1, &E[p * dim]));
2416918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) E[p * dim + d] *= -1.0;
2417918dfc20SMatthew G. Knepley }
2418918dfc20SMatthew G. Knepley PetscCall(DMPlexVecRestoreClosure(dm, NULL, locPhi, c, NULL, &clPhi));
2419918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(sw, c, &Ncp, &points));
2420918dfc20SMatthew G. Knepley }
2421918dfc20SMatthew G. Knepley PetscCall(DMRestoreWorkArray(dm, maxNcp * dim, MPIU_REAL, &pcoord));
2422918dfc20SMatthew G. Knepley PetscCall(DMRestoreWorkArray(dm, maxNcp * dim, MPIU_REAL, &refcoord));
2423918dfc20SMatthew G. Knepley PetscCall(PetscTabulationDestroy(&tab));
2424918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
2425918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortRestoreAccess(sw));
2426918dfc20SMatthew G. Knepley PetscCall(DMRestoreLocalVector(dm, &locPhi));
2427*2a8381b2SBarry Smith PetscCall(PetscFEGeomRestoreChunk(ctx->fegeom, 0, 1, &chunkgeom));
2428*2a8381b2SBarry Smith PetscCall(PetscLogEventEnd(ctx->ETabEvent, snes, sw, 0, 0));
2429918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
2430918dfc20SMatthew G. Knepley }
2431918dfc20SMatthew G. Knepley
ComputeFieldAtParticles(SNES snes,DM sw)2432918dfc20SMatthew G. Knepley static PetscErrorCode ComputeFieldAtParticles(SNES snes, DM sw)
2433918dfc20SMatthew G. Knepley {
2434*2a8381b2SBarry Smith AppCtx *ctx;
2435918dfc20SMatthew G. Knepley Mat M_p;
2436918dfc20SMatthew G. Knepley PetscReal *E;
2437918dfc20SMatthew G. Knepley PetscInt dim, Np;
2438918dfc20SMatthew G. Knepley
2439918dfc20SMatthew G. Knepley PetscFunctionBegin;
2440918dfc20SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2441918dfc20SMatthew G. Knepley PetscValidHeaderSpecific(sw, DM_CLASSID, 2);
2442918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim));
2443918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(sw, &Np));
2444*2a8381b2SBarry Smith PetscCall(DMGetApplicationContext(sw, &ctx));
2445918dfc20SMatthew G. Knepley
2446918dfc20SMatthew G. Knepley PetscCall(DMSwarmSetCellDMActive(sw, "moments"));
2447918dfc20SMatthew G. Knepley // TODO: Could share sort context with space cellDM
2448918dfc20SMatthew G. Knepley PetscCall(DMSwarmMigrate(sw, PETSC_FALSE));
2449*2a8381b2SBarry Smith PetscCall(DMCreateMassMatrix(sw, ctx->dmPot, &M_p));
2450918dfc20SMatthew G. Knepley PetscCall(DMSwarmSetCellDMActive(sw, "space"));
2451918dfc20SMatthew G. Knepley
2452918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "E_field", NULL, NULL, (void **)&E));
2453918dfc20SMatthew G. Knepley PetscCall(PetscArrayzero(E, Np * dim));
2454*2a8381b2SBarry Smith ctx->validE = PETSC_TRUE;
2455918dfc20SMatthew G. Knepley
2456*2a8381b2SBarry Smith switch (ctx->em) {
2457918dfc20SMatthew G. Knepley case EM_COULOMB:
2458918dfc20SMatthew G. Knepley PetscCall(ComputeFieldAtParticles_Coulomb(snes, sw, E));
2459918dfc20SMatthew G. Knepley break;
2460f14fce1bSMatthew G. Knepley case EM_PRIMAL:
2461918dfc20SMatthew G. Knepley PetscCall(ComputeFieldAtParticles_Primal(snes, sw, M_p, E));
2462918dfc20SMatthew G. Knepley break;
2463918dfc20SMatthew G. Knepley case EM_MIXED:
2464918dfc20SMatthew G. Knepley PetscCall(ComputeFieldAtParticles_Mixed(snes, sw, M_p, E));
2465918dfc20SMatthew G. Knepley break;
2466f14fce1bSMatthew G. Knepley case EM_NONE:
2467918dfc20SMatthew G. Knepley break;
2468918dfc20SMatthew G. Knepley default:
2469*2a8381b2SBarry Smith SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No solver for electrostatic model %s", EMTypes[ctx->em]);
2470918dfc20SMatthew G. Knepley }
2471918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "E_field", NULL, NULL, (void **)&E));
2472918dfc20SMatthew G. Knepley PetscCall(MatDestroy(&M_p));
2473918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
2474918dfc20SMatthew G. Knepley }
2475918dfc20SMatthew G. Knepley
RHSFunction(TS ts,PetscReal t,Vec U,Vec G,PetscCtx ctx)2476*2a8381b2SBarry Smith static PetscErrorCode RHSFunction(TS ts, PetscReal t, Vec U, Vec G, PetscCtx ctx)
2477918dfc20SMatthew G. Knepley {
2478918dfc20SMatthew G. Knepley DM sw;
2479918dfc20SMatthew G. Knepley SNES snes = ((AppCtx *)ctx)->snes;
2480918dfc20SMatthew G. Knepley const PetscScalar *u;
2481918dfc20SMatthew G. Knepley PetscScalar *g;
2482918dfc20SMatthew G. Knepley PetscReal *E, m_p = 1., q_p = -1.;
2483918dfc20SMatthew G. Knepley PetscInt dim, d, Np, p;
2484918dfc20SMatthew G. Knepley
2485918dfc20SMatthew G. Knepley PetscFunctionBeginUser;
2486918dfc20SMatthew G. Knepley PetscCall(TSGetDM(ts, &sw));
2487918dfc20SMatthew G. Knepley PetscCall(ComputeFieldAtParticles(snes, sw));
2488918dfc20SMatthew G. Knepley
2489918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim));
2490918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(sw, &Np));
2491918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "E_field", NULL, NULL, (void **)&E));
2492918dfc20SMatthew G. Knepley PetscCall(VecGetArrayRead(U, &u));
2493918dfc20SMatthew G. Knepley PetscCall(VecGetArray(G, &g));
2494918dfc20SMatthew G. Knepley Np /= 2 * dim;
2495918dfc20SMatthew G. Knepley for (p = 0; p < Np; ++p) {
2496918dfc20SMatthew G. Knepley for (d = 0; d < dim; ++d) {
2497918dfc20SMatthew G. Knepley g[(p * 2 + 0) * dim + d] = u[(p * 2 + 1) * dim + d];
2498918dfc20SMatthew G. Knepley g[(p * 2 + 1) * dim + d] = q_p * E[p * dim + d] / m_p;
2499918dfc20SMatthew G. Knepley }
2500918dfc20SMatthew G. Knepley }
2501918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "E_field", NULL, NULL, (void **)&E));
2502918dfc20SMatthew G. Knepley PetscCall(VecRestoreArrayRead(U, &u));
2503918dfc20SMatthew G. Knepley PetscCall(VecRestoreArray(G, &g));
2504918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
2505918dfc20SMatthew G. Knepley }
2506918dfc20SMatthew G. Knepley
2507918dfc20SMatthew G. Knepley /* J_{ij} = dF_i/dx_j
2508918dfc20SMatthew G. Knepley J_p = ( 0 1)
2509918dfc20SMatthew G. Knepley (-w^2 0)
2510918dfc20SMatthew G. Knepley TODO Now there is another term with w^2 from the electric field. I think we will need to invert the operator.
2511918dfc20SMatthew G. Knepley Perhaps we can approximate the Jacobian using only the cellwise P-P gradient from Coulomb
2512918dfc20SMatthew G. Knepley */
RHSJacobian(TS ts,PetscReal t,Vec U,Mat J,Mat P,PetscCtx ctx)2513*2a8381b2SBarry Smith static PetscErrorCode RHSJacobian(TS ts, PetscReal t, Vec U, Mat J, Mat P, PetscCtx ctx)
2514918dfc20SMatthew G. Knepley {
2515918dfc20SMatthew G. Knepley DM sw;
2516918dfc20SMatthew G. Knepley const PetscReal *coords, *vel;
2517918dfc20SMatthew G. Knepley PetscInt dim, d, Np, p, rStart;
2518918dfc20SMatthew G. Knepley
2519918dfc20SMatthew G. Knepley PetscFunctionBeginUser;
2520918dfc20SMatthew G. Knepley PetscCall(TSGetDM(ts, &sw));
2521918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim));
2522918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(sw, &Np));
2523918dfc20SMatthew G. Knepley PetscCall(MatGetOwnershipRange(J, &rStart, NULL));
2524918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
2525918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "velocity", NULL, NULL, (void **)&vel));
2526918dfc20SMatthew G. Knepley Np /= 2 * dim;
2527918dfc20SMatthew G. Knepley for (p = 0; p < Np; ++p) {
2528f940b0e3Sdanofinn // TODO This is not right because dv/dx has the electric field in it
2529f940b0e3Sdanofinn PetscScalar vals[4] = {0., 1., -1., 0.};
2530918dfc20SMatthew G. Knepley
2531918dfc20SMatthew G. Knepley for (d = 0; d < dim; ++d) {
2532918dfc20SMatthew G. Knepley const PetscInt rows[2] = {(p * 2 + 0) * dim + d + rStart, (p * 2 + 1) * dim + d + rStart};
2533918dfc20SMatthew G. Knepley PetscCall(MatSetValues(J, 2, rows, 2, rows, vals, INSERT_VALUES));
2534918dfc20SMatthew G. Knepley }
2535918dfc20SMatthew G. Knepley }
2536918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
2537918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "velocity", NULL, NULL, (void **)&vel));
2538918dfc20SMatthew G. Knepley PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
2539918dfc20SMatthew G. Knepley PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
2540918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
2541918dfc20SMatthew G. Knepley }
2542918dfc20SMatthew G. Knepley
RHSFunctionX(TS ts,PetscReal t,Vec V,Vec Xres,void * Ctx)2543*2a8381b2SBarry Smith static PetscErrorCode RHSFunctionX(TS ts, PetscReal t, Vec V, Vec Xres, void *Ctx)
2544918dfc20SMatthew G. Knepley {
2545*2a8381b2SBarry Smith AppCtx *ctx = (AppCtx *)Ctx;
2546918dfc20SMatthew G. Knepley DM sw;
2547918dfc20SMatthew G. Knepley const PetscScalar *v;
2548918dfc20SMatthew G. Knepley PetscScalar *xres;
2549918dfc20SMatthew G. Knepley PetscInt Np, p, d, dim;
2550918dfc20SMatthew G. Knepley
2551918dfc20SMatthew G. Knepley PetscFunctionBeginUser;
2552*2a8381b2SBarry Smith PetscCall(PetscLogEventBegin(ctx->RhsXEvent, ts, 0, 0, 0));
2553918dfc20SMatthew G. Knepley PetscCall(TSGetDM(ts, &sw));
2554918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim));
2555918dfc20SMatthew G. Knepley PetscCall(VecGetLocalSize(Xres, &Np));
2556918dfc20SMatthew G. Knepley PetscCall(VecGetArrayRead(V, &v));
2557918dfc20SMatthew G. Knepley PetscCall(VecGetArray(Xres, &xres));
2558918dfc20SMatthew G. Knepley Np /= dim;
2559918dfc20SMatthew G. Knepley for (p = 0; p < Np; ++p) {
2560918dfc20SMatthew G. Knepley for (d = 0; d < dim; ++d) xres[p * dim + d] = v[p * dim + d];
2561918dfc20SMatthew G. Knepley }
2562918dfc20SMatthew G. Knepley PetscCall(VecRestoreArrayRead(V, &v));
2563918dfc20SMatthew G. Knepley PetscCall(VecRestoreArray(Xres, &xres));
2564*2a8381b2SBarry Smith PetscCall(PetscLogEventEnd(ctx->RhsXEvent, ts, 0, 0, 0));
2565918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
2566918dfc20SMatthew G. Knepley }
2567918dfc20SMatthew G. Knepley
RHSFunctionV(TS ts,PetscReal t,Vec X,Vec Vres,void * Ctx)2568*2a8381b2SBarry Smith static PetscErrorCode RHSFunctionV(TS ts, PetscReal t, Vec X, Vec Vres, void *Ctx)
2569918dfc20SMatthew G. Knepley {
2570918dfc20SMatthew G. Knepley DM sw;
2571*2a8381b2SBarry Smith AppCtx *ctx = (AppCtx *)Ctx;
2572918dfc20SMatthew G. Knepley SNES snes = ((AppCtx *)ctx)->snes;
2573918dfc20SMatthew G. Knepley const PetscScalar *x;
2574918dfc20SMatthew G. Knepley PetscScalar *vres;
2575918dfc20SMatthew G. Knepley PetscReal *E, m_p, q_p;
2576918dfc20SMatthew G. Knepley PetscInt Np, p, dim, d;
2577918dfc20SMatthew G. Knepley Parameter *param;
2578918dfc20SMatthew G. Knepley
2579918dfc20SMatthew G. Knepley PetscFunctionBeginUser;
2580*2a8381b2SBarry Smith PetscCall(PetscLogEventBegin(ctx->RhsVEvent, ts, 0, 0, 0));
2581918dfc20SMatthew G. Knepley PetscCall(TSGetDM(ts, &sw));
2582918dfc20SMatthew G. Knepley PetscCall(ComputeFieldAtParticles(snes, sw));
2583918dfc20SMatthew G. Knepley
2584918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim));
2585918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "E_field", NULL, NULL, (void **)&E));
2586*2a8381b2SBarry Smith PetscCall(PetscBagGetData(ctx->bag, ¶m));
2587*2a8381b2SBarry Smith m_p = ctx->masses[0] * param->m0;
2588*2a8381b2SBarry Smith q_p = ctx->charges[0] * param->q0;
2589918dfc20SMatthew G. Knepley PetscCall(VecGetLocalSize(Vres, &Np));
2590918dfc20SMatthew G. Knepley PetscCall(VecGetArrayRead(X, &x));
2591918dfc20SMatthew G. Knepley PetscCall(VecGetArray(Vres, &vres));
2592918dfc20SMatthew G. Knepley Np /= dim;
2593918dfc20SMatthew G. Knepley for (p = 0; p < Np; ++p) {
2594918dfc20SMatthew G. Knepley for (d = 0; d < dim; ++d) vres[p * dim + d] = q_p * E[p * dim + d] / m_p;
2595918dfc20SMatthew G. Knepley }
2596918dfc20SMatthew G. Knepley PetscCall(VecRestoreArrayRead(X, &x));
2597918dfc20SMatthew G. Knepley /*
2598918dfc20SMatthew G. Knepley Synchronized, ordered output for parallel/sequential test cases.
2599918dfc20SMatthew G. Knepley In the 1D (on the 2D mesh) case, every y component should be zero.
2600918dfc20SMatthew G. Knepley */
2601*2a8381b2SBarry Smith if (ctx->checkVRes) {
2602*2a8381b2SBarry Smith PetscBool pr = ctx->checkVRes > 1 ? PETSC_TRUE : PETSC_FALSE;
2603918dfc20SMatthew G. Knepley PetscInt step;
2604918dfc20SMatthew G. Knepley
2605918dfc20SMatthew G. Knepley PetscCall(TSGetStepNumber(ts, &step));
2606918dfc20SMatthew G. Knepley if (pr) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "step: %" PetscInt_FMT "\n", step));
2607918dfc20SMatthew G. Knepley for (PetscInt p = 0; p < Np; ++p) {
2608918dfc20SMatthew G. Knepley if (pr) PetscCall(PetscSynchronizedPrintf(PETSC_COMM_WORLD, "Residual: %.12g %.12g\n", (double)PetscRealPart(vres[p * dim + 0]), (double)PetscRealPart(vres[p * dim + 1])));
2609918dfc20SMatthew G. Knepley 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]));
2610918dfc20SMatthew G. Knepley }
2611918dfc20SMatthew G. Knepley if (pr) PetscCall(PetscSynchronizedFlush(PETSC_COMM_WORLD, PETSC_STDOUT));
2612918dfc20SMatthew G. Knepley }
2613918dfc20SMatthew G. Knepley PetscCall(VecRestoreArray(Vres, &vres));
2614918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "E_field", NULL, NULL, (void **)&E));
2615*2a8381b2SBarry Smith PetscCall(PetscLogEventEnd(ctx->RhsVEvent, ts, 0, 0, 0));
2616918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
2617918dfc20SMatthew G. Knepley }
2618918dfc20SMatthew G. Knepley
2619f940b0e3Sdanofinn /* Discrete Gradients Formulation: S, F, gradF (G) */
RHSJacobianS(TS ts,PetscReal t,Vec U,Mat S,PetscCtx ctx)2620*2a8381b2SBarry Smith PetscErrorCode RHSJacobianS(TS ts, PetscReal t, Vec U, Mat S, PetscCtx ctx)
2621f940b0e3Sdanofinn {
2622f940b0e3Sdanofinn PetscScalar vals[4] = {0., 1., -1., 0.};
2623f940b0e3Sdanofinn DM sw;
2624f940b0e3Sdanofinn PetscInt dim, d, Np, p, rStart;
2625f940b0e3Sdanofinn
2626f940b0e3Sdanofinn PetscFunctionBeginUser;
2627f940b0e3Sdanofinn PetscCall(TSGetDM(ts, &sw));
2628f940b0e3Sdanofinn PetscCall(DMGetDimension(sw, &dim));
2629f940b0e3Sdanofinn PetscCall(VecGetLocalSize(U, &Np));
2630f940b0e3Sdanofinn PetscCall(MatGetOwnershipRange(S, &rStart, NULL));
2631f940b0e3Sdanofinn Np /= 2 * dim;
2632f940b0e3Sdanofinn for (p = 0; p < Np; ++p) {
2633f940b0e3Sdanofinn for (d = 0; d < dim; ++d) {
2634f940b0e3Sdanofinn const PetscInt rows[2] = {(p * 2 + 0) * dim + d + rStart, (p * 2 + 1) * dim + d + rStart};
2635f940b0e3Sdanofinn PetscCall(MatSetValues(S, 2, rows, 2, rows, vals, INSERT_VALUES));
2636f940b0e3Sdanofinn }
2637f940b0e3Sdanofinn }
2638f940b0e3Sdanofinn PetscCall(MatAssemblyBegin(S, MAT_FINAL_ASSEMBLY));
2639f940b0e3Sdanofinn PetscCall(MatAssemblyEnd(S, MAT_FINAL_ASSEMBLY));
2640f940b0e3Sdanofinn PetscFunctionReturn(PETSC_SUCCESS);
2641f940b0e3Sdanofinn }
2642f940b0e3Sdanofinn
RHSObjectiveF(TS ts,PetscReal t,Vec U,PetscScalar * F,void * Ctx)2643*2a8381b2SBarry Smith PetscErrorCode RHSObjectiveF(TS ts, PetscReal t, Vec U, PetscScalar *F, void *Ctx)
2644f940b0e3Sdanofinn {
2645*2a8381b2SBarry Smith AppCtx *ctx = (AppCtx *)Ctx;
2646f940b0e3Sdanofinn DM sw;
2647f940b0e3Sdanofinn Vec phi;
2648f940b0e3Sdanofinn const PetscScalar *u;
2649f940b0e3Sdanofinn PetscInt dim, Np, cStart, cEnd;
2650f940b0e3Sdanofinn PetscReal *vel, *coords, m_p = 1.;
2651f940b0e3Sdanofinn
2652f940b0e3Sdanofinn PetscFunctionBeginUser;
2653f940b0e3Sdanofinn PetscCall(TSGetDM(ts, &sw));
2654f940b0e3Sdanofinn PetscCall(DMGetDimension(sw, &dim));
2655*2a8381b2SBarry Smith PetscCall(DMPlexGetHeightStratum(ctx->dmPot, 0, &cStart, &cEnd));
2656f940b0e3Sdanofinn
2657*2a8381b2SBarry Smith PetscCall(DMGetNamedGlobalVector(ctx->dmPot, "phi", &phi));
2658f940b0e3Sdanofinn PetscCall(VecViewFromOptions(phi, NULL, "-phi_view_dg"));
2659*2a8381b2SBarry Smith PetscCall(computeFieldEnergy(ctx->dmPot, phi, F));
2660*2a8381b2SBarry Smith PetscCall(DMRestoreNamedGlobalVector(ctx->dmPot, "phi", &phi));
2661f940b0e3Sdanofinn
2662f940b0e3Sdanofinn PetscCall(DMSwarmGetField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
2663f940b0e3Sdanofinn PetscCall(DMSwarmGetField(sw, "velocity", NULL, NULL, (void **)&vel));
2664f940b0e3Sdanofinn PetscCall(DMSwarmSortGetAccess(sw));
2665f940b0e3Sdanofinn PetscCall(VecGetArrayRead(U, &u));
2666f940b0e3Sdanofinn PetscCall(VecGetLocalSize(U, &Np));
2667f940b0e3Sdanofinn Np /= 2 * dim;
2668f940b0e3Sdanofinn for (PetscInt c = cStart; c < cEnd; ++c) {
2669f940b0e3Sdanofinn PetscInt *points;
2670f940b0e3Sdanofinn PetscInt Ncp;
2671f940b0e3Sdanofinn
2672f940b0e3Sdanofinn PetscCall(DMSwarmSortGetPointsPerCell(sw, c, &Ncp, &points));
2673f940b0e3Sdanofinn for (PetscInt cp = 0; cp < Ncp; ++cp) {
2674f940b0e3Sdanofinn const PetscInt p = points[cp];
2675f940b0e3Sdanofinn const PetscReal v2 = DMPlex_DotRealD_Internal(dim, &u[(p * 2 + 1) * dim], &u[(p * 2 + 1) * dim]);
2676f940b0e3Sdanofinn
2677f940b0e3Sdanofinn *F += 0.5 * m_p * v2;
2678f940b0e3Sdanofinn }
2679f940b0e3Sdanofinn PetscCall(DMSwarmSortRestorePointsPerCell(sw, c, &Ncp, &points));
2680f940b0e3Sdanofinn }
2681f940b0e3Sdanofinn PetscCall(VecRestoreArrayRead(U, &u));
2682f940b0e3Sdanofinn PetscCall(DMSwarmSortRestoreAccess(sw));
2683f940b0e3Sdanofinn PetscCall(DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
2684f940b0e3Sdanofinn PetscCall(DMSwarmRestoreField(sw, "velocity", NULL, NULL, (void **)&vel));
2685f940b0e3Sdanofinn PetscFunctionReturn(PETSC_SUCCESS);
2686f940b0e3Sdanofinn }
2687f940b0e3Sdanofinn
2688f940b0e3Sdanofinn /* dF/dx = q E dF/dv = v */
RHSFunctionG(TS ts,PetscReal t,Vec U,Vec G,PetscCtx ctx)2689*2a8381b2SBarry Smith PetscErrorCode RHSFunctionG(TS ts, PetscReal t, Vec U, Vec G, PetscCtx ctx)
2690f940b0e3Sdanofinn {
2691f940b0e3Sdanofinn DM sw;
2692f940b0e3Sdanofinn SNES snes = ((AppCtx *)ctx)->snes;
2693f940b0e3Sdanofinn const PetscReal *coords, *vel, *E;
2694f940b0e3Sdanofinn const PetscScalar *u;
2695f940b0e3Sdanofinn PetscScalar *g;
2696f940b0e3Sdanofinn PetscReal m_p = 1., q_p = -1.;
2697f940b0e3Sdanofinn PetscInt dim, d, Np, p;
2698f940b0e3Sdanofinn
2699f940b0e3Sdanofinn PetscFunctionBeginUser;
2700f940b0e3Sdanofinn PetscCall(TSGetDM(ts, &sw));
2701f940b0e3Sdanofinn PetscCall(DMGetDimension(sw, &dim));
2702f940b0e3Sdanofinn PetscCall(DMSwarmGetLocalSize(sw, &Np));
2703f940b0e3Sdanofinn PetscCall(VecGetArrayRead(U, &u));
2704f940b0e3Sdanofinn PetscCall(VecGetArray(G, &g));
2705f940b0e3Sdanofinn
2706f940b0e3Sdanofinn PetscLogEvent COMPUTEFIELD;
2707f940b0e3Sdanofinn PetscCall(PetscLogEventRegister("COMPFIELDATPART", TS_CLASSID, &COMPUTEFIELD));
2708f940b0e3Sdanofinn PetscCall(PetscLogEventBegin(COMPUTEFIELD, 0, 0, 0, 0));
2709f940b0e3Sdanofinn PetscCall(ComputeFieldAtParticles(snes, sw));
2710f940b0e3Sdanofinn PetscCall(PetscLogEventEnd(COMPUTEFIELD, 0, 0, 0, 0));
2711f940b0e3Sdanofinn PetscCall(DMSwarmGetField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
2712f940b0e3Sdanofinn PetscCall(DMSwarmGetField(sw, "velocity", NULL, NULL, (void **)&vel));
2713f940b0e3Sdanofinn PetscCall(DMSwarmGetField(sw, "E_field", NULL, NULL, (void **)&E));
2714f940b0e3Sdanofinn for (p = 0; p < Np; ++p) {
2715f940b0e3Sdanofinn for (d = 0; d < dim; ++d) {
2716f940b0e3Sdanofinn g[(p * 2 + 0) * dim + d] = -(q_p / m_p) * E[p * dim + d];
2717f940b0e3Sdanofinn g[(p * 2 + 1) * dim + d] = m_p * u[(p * 2 + 1) * dim + d];
2718f940b0e3Sdanofinn }
2719f940b0e3Sdanofinn }
2720f940b0e3Sdanofinn PetscCall(DMSwarmRestoreField(sw, "E_field", NULL, NULL, (void **)&E));
2721f940b0e3Sdanofinn PetscCall(DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
2722f940b0e3Sdanofinn PetscCall(DMSwarmRestoreField(sw, "velocity", NULL, NULL, (void **)&vel));
2723f940b0e3Sdanofinn PetscCall(VecRestoreArrayRead(U, &u));
2724f940b0e3Sdanofinn PetscCall(VecRestoreArray(G, &g));
2725f940b0e3Sdanofinn PetscFunctionReturn(PETSC_SUCCESS);
2726f940b0e3Sdanofinn }
2727f940b0e3Sdanofinn
CreateSolution(TS ts)2728918dfc20SMatthew G. Knepley static PetscErrorCode CreateSolution(TS ts)
2729918dfc20SMatthew G. Knepley {
2730918dfc20SMatthew G. Knepley DM sw;
2731918dfc20SMatthew G. Knepley Vec u;
2732918dfc20SMatthew G. Knepley PetscInt dim, Np;
2733918dfc20SMatthew G. Knepley
2734918dfc20SMatthew G. Knepley PetscFunctionBegin;
2735918dfc20SMatthew G. Knepley PetscCall(TSGetDM(ts, &sw));
2736918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim));
2737918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(sw, &Np));
2738918dfc20SMatthew G. Knepley PetscCall(VecCreate(PETSC_COMM_WORLD, &u));
2739918dfc20SMatthew G. Knepley PetscCall(VecSetBlockSize(u, dim));
2740918dfc20SMatthew G. Knepley PetscCall(VecSetSizes(u, 2 * Np * dim, PETSC_DECIDE));
2741918dfc20SMatthew G. Knepley PetscCall(VecSetUp(u));
2742918dfc20SMatthew G. Knepley PetscCall(TSSetSolution(ts, u));
2743918dfc20SMatthew G. Knepley PetscCall(VecDestroy(&u));
2744918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
2745918dfc20SMatthew G. Knepley }
2746918dfc20SMatthew G. Knepley
SetProblem(TS ts)2747918dfc20SMatthew G. Knepley static PetscErrorCode SetProblem(TS ts)
2748918dfc20SMatthew G. Knepley {
2749*2a8381b2SBarry Smith AppCtx *ctx;
2750918dfc20SMatthew G. Knepley DM sw;
2751918dfc20SMatthew G. Knepley
2752918dfc20SMatthew G. Knepley PetscFunctionBegin;
2753918dfc20SMatthew G. Knepley PetscCall(TSGetDM(ts, &sw));
2754*2a8381b2SBarry Smith PetscCall(DMGetApplicationContext(sw, &ctx));
2755918dfc20SMatthew G. Knepley // Define unified system for (X, V)
2756918dfc20SMatthew G. Knepley {
2757918dfc20SMatthew G. Knepley Mat J;
2758918dfc20SMatthew G. Knepley PetscInt dim, Np;
2759918dfc20SMatthew G. Knepley
2760918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim));
2761918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(sw, &Np));
2762918dfc20SMatthew G. Knepley PetscCall(MatCreate(PETSC_COMM_WORLD, &J));
2763918dfc20SMatthew G. Knepley PetscCall(MatSetSizes(J, 2 * Np * dim, 2 * Np * dim, PETSC_DECIDE, PETSC_DECIDE));
2764918dfc20SMatthew G. Knepley PetscCall(MatSetBlockSize(J, 2 * dim));
2765918dfc20SMatthew G. Knepley PetscCall(MatSetFromOptions(J));
2766918dfc20SMatthew G. Knepley PetscCall(MatSetUp(J));
2767*2a8381b2SBarry Smith PetscCall(TSSetRHSFunction(ts, NULL, RHSFunction, ctx));
2768*2a8381b2SBarry Smith PetscCall(TSSetRHSJacobian(ts, J, J, RHSJacobian, ctx));
2769918dfc20SMatthew G. Knepley PetscCall(MatDestroy(&J));
2770918dfc20SMatthew G. Knepley }
2771918dfc20SMatthew G. Knepley /* Define split system for X and V */
2772918dfc20SMatthew G. Knepley {
2773918dfc20SMatthew G. Knepley Vec u;
2774918dfc20SMatthew G. Knepley IS isx, isv, istmp;
2775918dfc20SMatthew G. Knepley const PetscInt *idx;
2776918dfc20SMatthew G. Knepley PetscInt dim, Np, rstart;
2777918dfc20SMatthew G. Knepley
2778918dfc20SMatthew G. Knepley PetscCall(TSGetSolution(ts, &u));
2779918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim));
2780918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(sw, &Np));
2781918dfc20SMatthew G. Knepley PetscCall(VecGetOwnershipRange(u, &rstart, NULL));
2782918dfc20SMatthew G. Knepley PetscCall(ISCreateStride(PETSC_COMM_WORLD, Np, (rstart / dim) + 0, 2, &istmp));
2783918dfc20SMatthew G. Knepley PetscCall(ISGetIndices(istmp, &idx));
2784918dfc20SMatthew G. Knepley PetscCall(ISCreateBlock(PETSC_COMM_WORLD, dim, Np, idx, PETSC_COPY_VALUES, &isx));
2785918dfc20SMatthew G. Knepley PetscCall(ISRestoreIndices(istmp, &idx));
2786918dfc20SMatthew G. Knepley PetscCall(ISDestroy(&istmp));
2787918dfc20SMatthew G. Knepley PetscCall(ISCreateStride(PETSC_COMM_WORLD, Np, (rstart / dim) + 1, 2, &istmp));
2788918dfc20SMatthew G. Knepley PetscCall(ISGetIndices(istmp, &idx));
2789918dfc20SMatthew G. Knepley PetscCall(ISCreateBlock(PETSC_COMM_WORLD, dim, Np, idx, PETSC_COPY_VALUES, &isv));
2790918dfc20SMatthew G. Knepley PetscCall(ISRestoreIndices(istmp, &idx));
2791918dfc20SMatthew G. Knepley PetscCall(ISDestroy(&istmp));
2792918dfc20SMatthew G. Knepley PetscCall(TSRHSSplitSetIS(ts, "position", isx));
2793918dfc20SMatthew G. Knepley PetscCall(TSRHSSplitSetIS(ts, "momentum", isv));
2794918dfc20SMatthew G. Knepley PetscCall(ISDestroy(&isx));
2795918dfc20SMatthew G. Knepley PetscCall(ISDestroy(&isv));
2796*2a8381b2SBarry Smith PetscCall(TSRHSSplitSetRHSFunction(ts, "position", NULL, RHSFunctionX, ctx));
2797*2a8381b2SBarry Smith PetscCall(TSRHSSplitSetRHSFunction(ts, "momentum", NULL, RHSFunctionV, ctx));
2798918dfc20SMatthew G. Knepley }
2799f940b0e3Sdanofinn // Define symplectic formulation U_t = S . G, where G = grad F
2800f940b0e3Sdanofinn {
2801*2a8381b2SBarry Smith PetscCall(TSDiscGradSetFormulation(ts, RHSJacobianS, RHSObjectiveF, RHSFunctionG, ctx));
2802f940b0e3Sdanofinn }
2803918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
2804918dfc20SMatthew G. Knepley }
2805918dfc20SMatthew G. Knepley
DMSwarmTSRedistribute(TS ts)2806918dfc20SMatthew G. Knepley static PetscErrorCode DMSwarmTSRedistribute(TS ts)
2807918dfc20SMatthew G. Knepley {
2808918dfc20SMatthew G. Knepley DM sw;
2809918dfc20SMatthew G. Knepley Vec u;
2810918dfc20SMatthew G. Knepley PetscReal t, maxt, dt;
2811918dfc20SMatthew G. Knepley PetscInt n, maxn;
2812918dfc20SMatthew G. Knepley
2813918dfc20SMatthew G. Knepley PetscFunctionBegin;
2814918dfc20SMatthew G. Knepley PetscCall(TSGetDM(ts, &sw));
2815918dfc20SMatthew G. Knepley PetscCall(TSGetTime(ts, &t));
2816918dfc20SMatthew G. Knepley PetscCall(TSGetMaxTime(ts, &maxt));
2817918dfc20SMatthew G. Knepley PetscCall(TSGetTimeStep(ts, &dt));
2818918dfc20SMatthew G. Knepley PetscCall(TSGetStepNumber(ts, &n));
2819918dfc20SMatthew G. Knepley PetscCall(TSGetMaxSteps(ts, &maxn));
2820918dfc20SMatthew G. Knepley
2821918dfc20SMatthew G. Knepley PetscCall(TSReset(ts));
2822918dfc20SMatthew G. Knepley PetscCall(TSSetDM(ts, sw));
2823918dfc20SMatthew G. Knepley PetscCall(TSSetFromOptions(ts));
2824918dfc20SMatthew G. Knepley PetscCall(TSSetTime(ts, t));
2825918dfc20SMatthew G. Knepley PetscCall(TSSetMaxTime(ts, maxt));
2826918dfc20SMatthew G. Knepley PetscCall(TSSetTimeStep(ts, dt));
2827918dfc20SMatthew G. Knepley PetscCall(TSSetStepNumber(ts, n));
2828918dfc20SMatthew G. Knepley PetscCall(TSSetMaxSteps(ts, maxn));
2829918dfc20SMatthew G. Knepley
2830918dfc20SMatthew G. Knepley PetscCall(CreateSolution(ts));
2831918dfc20SMatthew G. Knepley PetscCall(SetProblem(ts));
2832918dfc20SMatthew G. Knepley PetscCall(TSGetSolution(ts, &u));
2833918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
2834918dfc20SMatthew G. Knepley }
2835918dfc20SMatthew G. Knepley
line(PetscInt dim,PetscReal time,const PetscReal dummy[],PetscInt p,PetscScalar x[],void * Ctx)2836*2a8381b2SBarry Smith PetscErrorCode line(PetscInt dim, PetscReal time, const PetscReal dummy[], PetscInt p, PetscScalar x[], void *Ctx)
2837918dfc20SMatthew G. Knepley {
2838918dfc20SMatthew G. Knepley DM sw, cdm;
2839918dfc20SMatthew G. Knepley PetscInt Np;
2840918dfc20SMatthew G. Knepley PetscReal low[2], high[2];
2841*2a8381b2SBarry Smith AppCtx *ctx = (AppCtx *)Ctx;
2842918dfc20SMatthew G. Knepley
2843*2a8381b2SBarry Smith sw = ctx->swarm;
2844918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetCellDM(sw, &cdm));
2845918dfc20SMatthew G. Knepley // Get the bounding box so we can equally space the particles
2846918dfc20SMatthew G. Knepley PetscCall(DMGetLocalBoundingBox(cdm, low, high));
2847918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(sw, &Np));
2848918dfc20SMatthew G. Knepley // shift it by h/2 so nothing is initialized directly on a boundary
2849918dfc20SMatthew G. Knepley x[0] = ((high[0] - low[0]) / Np) * (p + 0.5);
2850918dfc20SMatthew G. Knepley x[1] = 0.;
2851918dfc20SMatthew G. Knepley return PETSC_SUCCESS;
2852918dfc20SMatthew G. Knepley }
2853918dfc20SMatthew G. Knepley
2854918dfc20SMatthew G. Knepley /*
2855918dfc20SMatthew G. Knepley InitializeSolveAndSwarm - Set the solution values to the swarm coordinates and velocities, and also possibly set the initial values.
2856918dfc20SMatthew G. Knepley
2857918dfc20SMatthew G. Knepley Input Parameters:
2858918dfc20SMatthew G. Knepley + ts - The TS
2859918dfc20SMatthew G. Knepley - useInitial - Flag to also set the initial conditions to the current coordinates and velocities and setup the problem
2860918dfc20SMatthew G. Knepley
2861918dfc20SMatthew G. Knepley Output Parameters:
2862918dfc20SMatthew G. Knepley . u - The initialized solution vector
2863918dfc20SMatthew G. Knepley
2864918dfc20SMatthew G. Knepley Level: advanced
2865918dfc20SMatthew G. Knepley
2866918dfc20SMatthew G. Knepley .seealso: InitializeSolve()
2867918dfc20SMatthew G. Knepley */
InitializeSolveAndSwarm(TS ts,PetscBool useInitial)2868918dfc20SMatthew G. Knepley static PetscErrorCode InitializeSolveAndSwarm(TS ts, PetscBool useInitial)
2869918dfc20SMatthew G. Knepley {
2870918dfc20SMatthew G. Knepley DM sw;
2871918dfc20SMatthew G. Knepley Vec u, gc, gv;
2872918dfc20SMatthew G. Knepley IS isx, isv;
2873918dfc20SMatthew G. Knepley PetscInt dim;
2874*2a8381b2SBarry Smith AppCtx *ctx;
2875918dfc20SMatthew G. Knepley
2876918dfc20SMatthew G. Knepley PetscFunctionBeginUser;
2877918dfc20SMatthew G. Knepley PetscCall(TSGetDM(ts, &sw));
2878*2a8381b2SBarry Smith PetscCall(DMGetApplicationContext(sw, &ctx));
2879918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim));
2880918dfc20SMatthew G. Knepley if (useInitial) {
2881918dfc20SMatthew G. Knepley PetscReal v0[2] = {1., 0.};
2882*2a8381b2SBarry Smith if (ctx->perturbed_weights) {
2883*2a8381b2SBarry Smith PetscCall(InitializeParticles_PerturbedWeights(sw, ctx));
2884918dfc20SMatthew G. Knepley } else {
2885918dfc20SMatthew G. Knepley PetscCall(DMSwarmComputeLocalSizeFromOptions(sw));
2886918dfc20SMatthew G. Knepley PetscCall(DMSwarmInitializeCoordinates(sw));
2887918dfc20SMatthew G. Knepley PetscCall(DMSwarmInitializeVelocitiesFromOptions(sw, v0));
2888918dfc20SMatthew G. Knepley }
2889918dfc20SMatthew G. Knepley PetscCall(DMSwarmMigrate(sw, PETSC_TRUE));
2890918dfc20SMatthew G. Knepley PetscCall(DMSwarmTSRedistribute(ts));
2891918dfc20SMatthew G. Knepley }
2892918dfc20SMatthew G. Knepley PetscCall(DMSetUp(sw));
2893918dfc20SMatthew G. Knepley PetscCall(TSGetSolution(ts, &u));
2894918dfc20SMatthew G. Knepley PetscCall(TSRHSSplitGetIS(ts, "position", &isx));
2895918dfc20SMatthew G. Knepley PetscCall(TSRHSSplitGetIS(ts, "momentum", &isv));
2896918dfc20SMatthew G. Knepley PetscCall(DMSwarmCreateGlobalVectorFromField(sw, DMSwarmPICField_coor, &gc));
2897918dfc20SMatthew G. Knepley PetscCall(DMSwarmCreateGlobalVectorFromField(sw, "velocity", &gv));
2898918dfc20SMatthew G. Knepley PetscCall(VecISCopy(u, isx, SCATTER_FORWARD, gc));
2899918dfc20SMatthew G. Knepley PetscCall(VecISCopy(u, isv, SCATTER_FORWARD, gv));
2900918dfc20SMatthew G. Knepley PetscCall(DMSwarmDestroyGlobalVectorFromField(sw, DMSwarmPICField_coor, &gc));
2901918dfc20SMatthew G. Knepley PetscCall(DMSwarmDestroyGlobalVectorFromField(sw, "velocity", &gv));
2902918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
2903918dfc20SMatthew G. Knepley }
2904918dfc20SMatthew G. Knepley
InitializeSolve(TS ts,Vec u)2905918dfc20SMatthew G. Knepley static PetscErrorCode InitializeSolve(TS ts, Vec u)
2906918dfc20SMatthew G. Knepley {
2907918dfc20SMatthew G. Knepley PetscFunctionBegin;
2908918dfc20SMatthew G. Knepley PetscCall(TSSetSolution(ts, u));
2909918dfc20SMatthew G. Knepley PetscCall(InitializeSolveAndSwarm(ts, PETSC_TRUE));
2910918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
2911918dfc20SMatthew G. Knepley }
2912918dfc20SMatthew G. Knepley
MigrateParticles(TS ts)2913918dfc20SMatthew G. Knepley static PetscErrorCode MigrateParticles(TS ts)
2914918dfc20SMatthew G. Knepley {
2915918dfc20SMatthew G. Knepley DM sw, cdm;
2916918dfc20SMatthew G. Knepley const PetscReal *L;
2917918dfc20SMatthew G. Knepley AppCtx *ctx;
2918918dfc20SMatthew G. Knepley
2919918dfc20SMatthew G. Knepley PetscFunctionBeginUser;
2920918dfc20SMatthew G. Knepley PetscCall(TSGetDM(ts, &sw));
2921918dfc20SMatthew G. Knepley PetscCall(DMGetApplicationContext(sw, &ctx));
2922918dfc20SMatthew G. Knepley PetscCall(DMViewFromOptions(sw, NULL, "-migrate_view_pre"));
2923918dfc20SMatthew G. Knepley {
2924918dfc20SMatthew G. Knepley Vec u, gc, gv, position, momentum;
2925918dfc20SMatthew G. Knepley IS isx, isv;
2926918dfc20SMatthew G. Knepley PetscReal *pos, *mom;
2927918dfc20SMatthew G. Knepley
2928918dfc20SMatthew G. Knepley PetscCall(TSGetSolution(ts, &u));
2929918dfc20SMatthew G. Knepley PetscCall(TSRHSSplitGetIS(ts, "position", &isx));
2930918dfc20SMatthew G. Knepley PetscCall(TSRHSSplitGetIS(ts, "momentum", &isv));
2931918dfc20SMatthew G. Knepley PetscCall(VecGetSubVector(u, isx, &position));
2932918dfc20SMatthew G. Knepley PetscCall(VecGetSubVector(u, isv, &momentum));
2933918dfc20SMatthew G. Knepley PetscCall(VecGetArray(position, &pos));
2934918dfc20SMatthew G. Knepley PetscCall(VecGetArray(momentum, &mom));
2935918dfc20SMatthew G. Knepley PetscCall(DMSwarmCreateGlobalVectorFromField(sw, DMSwarmPICField_coor, &gc));
2936918dfc20SMatthew G. Knepley PetscCall(DMSwarmCreateGlobalVectorFromField(sw, "velocity", &gv));
2937918dfc20SMatthew G. Knepley PetscCall(VecISCopy(u, isx, SCATTER_REVERSE, gc));
2938918dfc20SMatthew G. Knepley PetscCall(VecISCopy(u, isv, SCATTER_REVERSE, gv));
2939918dfc20SMatthew G. Knepley
2940918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetCellDM(sw, &cdm));
2941918dfc20SMatthew G. Knepley PetscCall(DMGetPeriodicity(cdm, NULL, NULL, &L));
2942918dfc20SMatthew G. Knepley PetscCheck(L, PetscObjectComm((PetscObject)cdm), PETSC_ERR_ARG_WRONG, "Mesh must be periodic");
2943918dfc20SMatthew G. Knepley if ((L[0] || L[1]) >= 0.) {
2944918dfc20SMatthew G. Knepley PetscReal *x, *v, upper[3], lower[3];
2945918dfc20SMatthew G. Knepley PetscInt Np, dim;
2946918dfc20SMatthew G. Knepley
2947918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(sw, &Np));
2948918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(cdm, &dim));
2949918dfc20SMatthew G. Knepley PetscCall(DMGetBoundingBox(cdm, lower, upper));
2950918dfc20SMatthew G. Knepley PetscCall(VecGetArray(gc, &x));
2951918dfc20SMatthew G. Knepley PetscCall(VecGetArray(gv, &v));
2952918dfc20SMatthew G. Knepley for (PetscInt p = 0; p < Np; ++p) {
2953918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) {
2954918dfc20SMatthew G. Knepley if (pos[p * dim + d] < lower[d]) {
2955918dfc20SMatthew G. Knepley x[p * dim + d] = pos[p * dim + d] + (upper[d] - lower[d]);
2956918dfc20SMatthew G. Knepley } else if (pos[p * dim + d] > upper[d]) {
2957918dfc20SMatthew G. Knepley x[p * dim + d] = pos[p * dim + d] - (upper[d] - lower[d]);
2958918dfc20SMatthew G. Knepley } else {
2959918dfc20SMatthew G. Knepley x[p * dim + d] = pos[p * dim + d];
2960918dfc20SMatthew G. Knepley }
2961918dfc20SMatthew G. Knepley 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]);
2962918dfc20SMatthew G. Knepley v[p * dim + d] = mom[p * dim + d];
2963918dfc20SMatthew G. Knepley }
2964918dfc20SMatthew G. Knepley }
2965918dfc20SMatthew G. Knepley PetscCall(VecRestoreArray(gc, &x));
2966918dfc20SMatthew G. Knepley PetscCall(VecRestoreArray(gv, &v));
2967918dfc20SMatthew G. Knepley }
2968918dfc20SMatthew G. Knepley PetscCall(VecRestoreArray(position, &pos));
2969918dfc20SMatthew G. Knepley PetscCall(VecRestoreArray(momentum, &mom));
2970918dfc20SMatthew G. Knepley PetscCall(VecRestoreSubVector(u, isx, &position));
2971918dfc20SMatthew G. Knepley PetscCall(VecRestoreSubVector(u, isv, &momentum));
2972918dfc20SMatthew G. Knepley PetscCall(DMSwarmDestroyGlobalVectorFromField(sw, "velocity", &gv));
2973918dfc20SMatthew G. Knepley PetscCall(DMSwarmDestroyGlobalVectorFromField(sw, DMSwarmPICField_coor, &gc));
2974918dfc20SMatthew G. Knepley }
2975918dfc20SMatthew G. Knepley PetscCall(DMSwarmMigrate(sw, PETSC_TRUE));
2976918dfc20SMatthew G. Knepley PetscInt step;
2977918dfc20SMatthew G. Knepley
2978918dfc20SMatthew G. Knepley PetscCall(TSGetStepNumber(ts, &step));
2979918dfc20SMatthew G. Knepley if (!(step % ctx->remapFreq)) {
2980918dfc20SMatthew G. Knepley // Monitor electric field before we destroy it
2981918dfc20SMatthew G. Knepley PetscReal ptime;
2982918dfc20SMatthew G. Knepley PetscInt step;
2983918dfc20SMatthew G. Knepley
2984918dfc20SMatthew G. Knepley PetscCall(TSGetStepNumber(ts, &step));
2985918dfc20SMatthew G. Knepley PetscCall(TSGetTime(ts, &ptime));
2986918dfc20SMatthew G. Knepley if (ctx->efield_monitor) PetscCall(MonitorEField(ts, step, ptime, NULL, ctx));
2987918dfc20SMatthew G. Knepley if (ctx->poisson_monitor) PetscCall(MonitorPoisson(ts, step, ptime, NULL, ctx));
2988918dfc20SMatthew G. Knepley PetscCall(DMSwarmRemap(sw));
2989918dfc20SMatthew G. Knepley ctx->validE = PETSC_FALSE;
2990918dfc20SMatthew G. Knepley }
2991918dfc20SMatthew G. Knepley // This MUST come last, since it recreates the subswarms and they must DMClone() the new swarm
2992918dfc20SMatthew G. Knepley PetscCall(DMSwarmTSRedistribute(ts));
2993918dfc20SMatthew G. Knepley PetscCall(InitializeSolveAndSwarm(ts, PETSC_FALSE));
2994918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
2995918dfc20SMatthew G. Knepley }
2996918dfc20SMatthew G. Knepley
main(int argc,char ** argv)2997918dfc20SMatthew G. Knepley int main(int argc, char **argv)
2998918dfc20SMatthew G. Knepley {
2999918dfc20SMatthew G. Knepley DM dm, sw;
3000918dfc20SMatthew G. Knepley TS ts;
3001918dfc20SMatthew G. Knepley Vec u;
3002918dfc20SMatthew G. Knepley PetscReal dt;
3003918dfc20SMatthew G. Knepley PetscInt maxn;
3004*2a8381b2SBarry Smith AppCtx ctx;
3005918dfc20SMatthew G. Knepley
3006918dfc20SMatthew G. Knepley PetscCall(PetscInitialize(&argc, &argv, NULL, help));
3007*2a8381b2SBarry Smith PetscCall(ProcessOptions(PETSC_COMM_WORLD, &ctx));
3008*2a8381b2SBarry Smith PetscCall(PetscBagCreate(PETSC_COMM_SELF, sizeof(Parameter), &ctx.bag));
3009*2a8381b2SBarry Smith PetscCall(CreateMesh(PETSC_COMM_WORLD, &ctx, &dm));
3010*2a8381b2SBarry Smith PetscCall(CreatePoisson(dm, &ctx));
3011*2a8381b2SBarry Smith PetscCall(CreateMomentFields(dm, &ctx));
3012*2a8381b2SBarry Smith PetscCall(CreateSwarm(dm, &ctx, &sw));
3013*2a8381b2SBarry Smith PetscCall(SetupParameters(PETSC_COMM_WORLD, &ctx));
3014*2a8381b2SBarry Smith PetscCall(InitializeConstants(sw, &ctx));
3015*2a8381b2SBarry Smith PetscCall(DMSetApplicationContext(sw, &ctx));
3016918dfc20SMatthew G. Knepley
3017918dfc20SMatthew G. Knepley PetscCall(TSCreate(PETSC_COMM_WORLD, &ts));
3018918dfc20SMatthew G. Knepley PetscCall(TSSetProblemType(ts, TS_NONLINEAR));
3019918dfc20SMatthew G. Knepley PetscCall(TSSetDM(ts, sw));
3020918dfc20SMatthew G. Knepley PetscCall(TSSetMaxTime(ts, 0.1));
3021918dfc20SMatthew G. Knepley PetscCall(TSSetTimeStep(ts, 0.00001));
3022918dfc20SMatthew G. Knepley PetscCall(TSSetMaxSteps(ts, 100));
3023918dfc20SMatthew G. Knepley PetscCall(TSSetExactFinalTime(ts, TS_EXACTFINALTIME_MATCHSTEP));
3024918dfc20SMatthew G. Knepley
3025*2a8381b2SBarry Smith if (ctx.efield_monitor) PetscCall(TSMonitorSet(ts, MonitorEField, &ctx, NULL));
3026*2a8381b2SBarry Smith if (ctx.moment_monitor) PetscCall(TSMonitorSet(ts, MonitorMoments, &ctx, NULL));
3027*2a8381b2SBarry Smith if (ctx.moment_field_monitor) PetscCall(TSMonitorSet(ts, MonitorMomentFields, &ctx, NULL));
3028*2a8381b2SBarry Smith if (ctx.initial_monitor) PetscCall(TSMonitorSet(ts, MonitorInitialConditions, &ctx, NULL));
3029*2a8381b2SBarry Smith if (ctx.positions_monitor) PetscCall(TSMonitorSet(ts, MonitorPositions_2D, &ctx, NULL));
3030*2a8381b2SBarry Smith if (ctx.poisson_monitor) PetscCall(TSMonitorSet(ts, MonitorPoisson, &ctx, NULL));
3031*2a8381b2SBarry Smith if (ctx.velocity_monitor >= 0) PetscCall(TSMonitorSet(ts, MonitorVelocity, &ctx, NULL));
3032918dfc20SMatthew G. Knepley
3033918dfc20SMatthew G. Knepley PetscCall(TSSetFromOptions(ts));
3034918dfc20SMatthew G. Knepley PetscCall(TSGetTimeStep(ts, &dt));
3035918dfc20SMatthew G. Knepley PetscCall(TSGetMaxSteps(ts, &maxn));
3036*2a8381b2SBarry Smith ctx.steps = maxn;
3037*2a8381b2SBarry Smith ctx.stepSize = dt;
3038*2a8381b2SBarry Smith PetscCall(SetupContext(dm, sw, &ctx));
3039918dfc20SMatthew G. Knepley PetscCall(TSSetComputeInitialCondition(ts, InitializeSolve));
3040918dfc20SMatthew G. Knepley PetscCall(TSSetPostStep(ts, MigrateParticles));
3041918dfc20SMatthew G. Knepley PetscCall(CreateSolution(ts));
3042918dfc20SMatthew G. Knepley PetscCall(TSGetSolution(ts, &u));
3043918dfc20SMatthew G. Knepley PetscCall(TSComputeInitialCondition(ts, u));
3044*2a8381b2SBarry Smith PetscCall(CheckNonNegativeWeights(sw, &ctx));
3045918dfc20SMatthew G. Knepley PetscCall(TSSolve(ts, NULL));
3046918dfc20SMatthew G. Knepley
3047*2a8381b2SBarry Smith if (ctx.checkLandau) {
3048918dfc20SMatthew G. Knepley // We should get a lookup table based on charge density and \hat k
3049918dfc20SMatthew G. Knepley const PetscReal gammaEx = -0.15336;
3050918dfc20SMatthew G. Knepley const PetscReal omegaEx = 1.4156;
3051918dfc20SMatthew G. Knepley const PetscReal tol = 1e-2;
3052918dfc20SMatthew G. Knepley
3053*2a8381b2SBarry Smith PetscCheck(PetscAbsReal((ctx.gamma - gammaEx) / gammaEx) < tol, PETSC_COMM_WORLD, PETSC_ERR_LIB, "Invalid Landau gamma %g != %g", ctx.gamma, gammaEx);
3054*2a8381b2SBarry Smith PetscCheck(PetscAbsReal((ctx.omega - omegaEx) / omegaEx) < tol, PETSC_COMM_WORLD, PETSC_ERR_LIB, "Invalid Landau omega %g != %g", ctx.omega, omegaEx);
3055918dfc20SMatthew G. Knepley }
3056918dfc20SMatthew G. Knepley
3057*2a8381b2SBarry Smith PetscCall(SNESDestroy(&ctx.snes));
3058*2a8381b2SBarry Smith PetscCall(DMDestroy(&ctx.dmN));
3059*2a8381b2SBarry Smith PetscCall(ISDestroy(&ctx.isN));
3060*2a8381b2SBarry Smith PetscCall(MatDestroy(&ctx.MN));
3061*2a8381b2SBarry Smith PetscCall(DMDestroy(&ctx.dmP));
3062*2a8381b2SBarry Smith PetscCall(ISDestroy(&ctx.isP));
3063*2a8381b2SBarry Smith PetscCall(MatDestroy(&ctx.MP));
3064*2a8381b2SBarry Smith PetscCall(DMDestroy(&ctx.dmE));
3065*2a8381b2SBarry Smith PetscCall(ISDestroy(&ctx.isE));
3066*2a8381b2SBarry Smith PetscCall(MatDestroy(&ctx.ME));
3067*2a8381b2SBarry Smith PetscCall(DMDestroy(&ctx.dmMom));
3068*2a8381b2SBarry Smith PetscCall(DMDestroy(&ctx.dmPot));
3069*2a8381b2SBarry Smith PetscCall(ISDestroy(&ctx.isPot));
3070*2a8381b2SBarry Smith PetscCall(MatDestroy(&ctx.M));
3071*2a8381b2SBarry Smith PetscCall(PetscFEGeomDestroy(&ctx.fegeom));
3072918dfc20SMatthew G. Knepley PetscCall(TSDestroy(&ts));
3073918dfc20SMatthew G. Knepley PetscCall(DMDestroy(&sw));
3074918dfc20SMatthew G. Knepley PetscCall(DMDestroy(&dm));
3075*2a8381b2SBarry Smith PetscCall(DestroyContext(&ctx));
3076918dfc20SMatthew G. Knepley PetscCall(PetscFinalize());
3077918dfc20SMatthew G. Knepley return 0;
3078918dfc20SMatthew G. Knepley }
3079918dfc20SMatthew G. Knepley
3080918dfc20SMatthew G. Knepley /*TEST
3081918dfc20SMatthew G. Knepley
3082918dfc20SMatthew G. Knepley build:
3083918dfc20SMatthew G. Knepley requires: !complex double
3084918dfc20SMatthew G. Knepley
3085918dfc20SMatthew G. Knepley # This tests that we can compute the correct decay rate and frequency
3086f940b0e3Sdanofinn # For gold runs, use -dm_plex_box_faces 160 -vdm_plex_box_faces 450 -remap_dm_plex_box_faces 80,150 -ts_max_steps 1000
3087f940b0e3Sdanofinn # -remap_freq 100 -emax_start_step 50 -emax_solve_step 100
3088f940b0e3Sdanofinn testset:
3089918dfc20SMatthew G. Knepley args: -cosine_coefficients 0.01 -charges -1. -perturbed_weights -total_weight 1. \
3090918dfc20SMatthew G. Knepley -dm_plex_dim 1 -dm_plex_box_faces 80 -dm_plex_box_lower 0. -dm_plex_box_upper 12.5664 \
3091918dfc20SMatthew G. Knepley -dm_plex_box_bd periodic -dm_plex_hash_location \
3092918dfc20SMatthew G. Knepley -vdm_plex_dim 1 -vdm_plex_box_faces 220 -vdm_plex_box_lower -6 -vdm_plex_box_upper 6 \
3093918dfc20SMatthew G. Knepley -vpetscspace_degree 2 -vdm_plex_hash_location \
3094f940b0e3Sdanofinn -remap_freq 1 -dm_swarm_remap_type pfak -remap_dm_plex_dim 2 -remap_dm_plex_simplex 0 \
3095918dfc20SMatthew G. Knepley -remap_dm_plex_box_faces 40,110 -remap_dm_plex_box_bd periodic,none \
3096918dfc20SMatthew G. Knepley -remap_dm_plex_box_lower 0.,-6. -remap_dm_plex_box_upper 12.5664,6. \
3097918dfc20SMatthew G. Knepley -remap_petscspace_degree 1 -remap_dm_plex_hash_location \
3098918dfc20SMatthew G. Knepley -ftop_ksp_type lsqr -ftop_pc_type none -ftop_ksp_rtol 1.e-14 -ptof_pc_type lu \
3099918dfc20SMatthew G. Knepley -em_type primal -petscspace_degree 1 -em_snes_atol 1.e-12 -em_snes_error_if_not_converged \
3100918dfc20SMatthew G. Knepley -em_ksp_error_if_not_converged -em_pc_type svd -em_proj_pc_type lu \
3101188af4bfSBarry Smith -ts_time_step 0.03 -ts_max_steps 2 -ts_max_time 100 \
3102918dfc20SMatthew G. Knepley -emax_tao_type brgn -emax_tao_max_it 100 -emax_tao_brgn_regularization_type l2pure \
3103918dfc20SMatthew G. Knepley -emax_tao_brgn_regularizer_weight 1e-5 -tao_brgn_subsolver_tao_bnk_ksp_rtol 1e-12 \
3104f940b0e3Sdanofinn -emax_start_step 1 -emax_solve_step 1 \
3105918dfc20SMatthew G. Knepley -output_step 1 -efield_monitor quiet
3106918dfc20SMatthew G. Knepley
3107f940b0e3Sdanofinn test:
3108f940b0e3Sdanofinn suffix: landau_damping_1d_bs
3109f940b0e3Sdanofinn args: -ts_type basicsymplectic -ts_basicsymplectic_type 1
3110f940b0e3Sdanofinn
3111f940b0e3Sdanofinn test:
3112f940b0e3Sdanofinn suffix: landau_damping_1d_dg
3113f940b0e3Sdanofinn args: -ts_type discgrad -ts_discgrad_type average -snes_type qn
3114f940b0e3Sdanofinn
3115918dfc20SMatthew G. Knepley TEST*/
3116