1*918dfc20SMatthew G. Knepley static char help[] = "Two-level system for Landau Damping using Vlasov-Poisson equations\n"; 2*918dfc20SMatthew G. Knepley 3*918dfc20SMatthew G. Knepley /* 4*918dfc20SMatthew G. Knepley Moment Equations: 5*918dfc20SMatthew G. Knepley 6*918dfc20SMatthew 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 7*918dfc20SMatthew G. Knepley 8*918dfc20SMatthew G. Knepley \int dx \phi_i n_f = \int dx \phi_i n_p 9*918dfc20SMatthew G. Knepley \int dx \phi_i n_f = \int dx \phi_i \int dv f 10*918dfc20SMatthew 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) 11*918dfc20SMatthew G. Knepley \int dx \phi_i n_f = \int dx \phi_i \sum_p w_p \delta(x - x_p) 12*918dfc20SMatthew G. Knepley M n_F = M_p w_p 13*918dfc20SMatthew G. Knepley 14*918dfc20SMatthew G. Knepley where 15*918dfc20SMatthew G. Knepley 16*918dfc20SMatthew G. Knepley (M_p){ip} = \phi_i(x_p) 17*918dfc20SMatthew G. Knepley 18*918dfc20SMatthew G. Knepley which is just a scaled version of the charge density. The second moment, momentum density, is given by 19*918dfc20SMatthew G. Knepley 20*918dfc20SMatthew G. Knepley \int dx \phi_i p_f = m \int dx \phi_i \int dv v f 21*918dfc20SMatthew G. Knepley \int dx \phi_i p_f = m \int dx \phi_i \sum_p w_p \delta(x - x_p) v_p 22*918dfc20SMatthew G. Knepley M p_F = M_p v_p w_p 23*918dfc20SMatthew G. Knepley 24*918dfc20SMatthew G. Knepley And finally the third moment, pressure, is given by 25*918dfc20SMatthew G. Knepley 26*918dfc20SMatthew G. Knepley \int dx \phi_i pr_f = m \int dx \phi_i \int dv (v - u)^2 f 27*918dfc20SMatthew 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 28*918dfc20SMatthew G. Knepley M pr_F = M_p (v_p - u)^2 w_p 29*918dfc20SMatthew G. Knepley = M_p (v_p - p_F(x_p) / m n_F(x_p))^2 w_p 30*918dfc20SMatthew 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 31*918dfc20SMatthew G. Knepley 32*918dfc20SMatthew G. Knepley Here we need all FEM basis functions \phi_i that see that particle p. 33*918dfc20SMatthew G. Knepley 34*918dfc20SMatthew 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" 35*918dfc20SMatthew G. Knepley According to Lukas, good damping results come at ~16k particles per cell 36*918dfc20SMatthew G. Knepley 37*918dfc20SMatthew G. Knepley Swarm CellDMs 38*918dfc20SMatthew G. Knepley ============= 39*918dfc20SMatthew G. Knepley Name: "space" 40*918dfc20SMatthew G. Knepley Fields: DMSwarmPICField_coor, "velocity" 41*918dfc20SMatthew G. Knepley Coordinates: DMSwarmPICField_coor 42*918dfc20SMatthew G. Knepley 43*918dfc20SMatthew G. Knepley Name: "velocity" 44*918dfc20SMatthew G. Knepley Fields: "w_q" 45*918dfc20SMatthew G. Knepley Coordinates: "velocity" 46*918dfc20SMatthew G. Knepley 47*918dfc20SMatthew G. Knepley Name: "moments" 48*918dfc20SMatthew G. Knepley Fields: "w_q" 49*918dfc20SMatthew G. Knepley Coordinates: DMSwarmPICField_coor 50*918dfc20SMatthew G. Knepley 51*918dfc20SMatthew G. Knepley Name: "moment fields" 52*918dfc20SMatthew G. Knepley Fields: "velocity" 53*918dfc20SMatthew G. Knepley Coordinates: DMSwarmPICField_coor 54*918dfc20SMatthew G. Knepley 55*918dfc20SMatthew G. Knepley To visualize the maximum electric field use 56*918dfc20SMatthew G. Knepley 57*918dfc20SMatthew G. Knepley -efield_monitor 58*918dfc20SMatthew G. Knepley 59*918dfc20SMatthew G. Knepley To monitor velocity moments of the distribution use 60*918dfc20SMatthew G. Knepley 61*918dfc20SMatthew G. Knepley -ptof_pc_type lu -moments_monitor 62*918dfc20SMatthew G. Knepley 63*918dfc20SMatthew G. Knepley To monitor the particle positions in phase space use 64*918dfc20SMatthew G. Knepley 65*918dfc20SMatthew G. Knepley -positions_monitor 66*918dfc20SMatthew G. Knepley 67*918dfc20SMatthew G. Knepley To monitor the charge density, E field, and potential use 68*918dfc20SMatthew G. Knepley 69*918dfc20SMatthew G. Knepley -poisson_monitor 70*918dfc20SMatthew G. Knepley 71*918dfc20SMatthew G. Knepley To monitor the remapping field use 72*918dfc20SMatthew G. Knepley 73*918dfc20SMatthew G. Knepley -remap_uf_view draw 74*918dfc20SMatthew G. Knepley 75*918dfc20SMatthew G. Knepley To visualize the swarm distribution use 76*918dfc20SMatthew G. Knepley 77*918dfc20SMatthew G. Knepley -ts_monitor_hg_swarm 78*918dfc20SMatthew G. Knepley 79*918dfc20SMatthew G. Knepley To visualize the particles, we can use 80*918dfc20SMatthew G. Knepley 81*918dfc20SMatthew G. Knepley -ts_monitor_sp_swarm -ts_monitor_sp_swarm_retain 0 -ts_monitor_sp_swarm_phase 1 -draw_size 500,500 82*918dfc20SMatthew G. Knepley */ 83*918dfc20SMatthew G. Knepley #include <petsctao.h> 84*918dfc20SMatthew G. Knepley #include <petscts.h> 85*918dfc20SMatthew G. Knepley #include <petscdmplex.h> 86*918dfc20SMatthew G. Knepley #include <petscdmswarm.h> 87*918dfc20SMatthew G. Knepley #include <petscfe.h> 88*918dfc20SMatthew G. Knepley #include <petscds.h> 89*918dfc20SMatthew G. Knepley #include <petscbag.h> 90*918dfc20SMatthew G. Knepley #include <petscdraw.h> 91*918dfc20SMatthew G. Knepley #include <petsc/private/petscfeimpl.h> /* For interpolation */ 92*918dfc20SMatthew G. Knepley #include <petsc/private/dmswarmimpl.h> /* For swarm debugging */ 93*918dfc20SMatthew G. Knepley #include "petscdm.h" 94*918dfc20SMatthew G. Knepley #include "petscdmlabel.h" 95*918dfc20SMatthew G. Knepley 96*918dfc20SMatthew G. Knepley PETSC_EXTERN PetscErrorCode stream(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *); 97*918dfc20SMatthew G. Knepley PETSC_EXTERN PetscErrorCode line(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *); 98*918dfc20SMatthew G. Knepley 99*918dfc20SMatthew G. Knepley const char *EMTypes[] = {"primal", "mixed", "coulomb", "none", "EMType", "EM_", NULL}; 100*918dfc20SMatthew G. Knepley typedef enum { 101*918dfc20SMatthew G. Knepley EMPRIMAL, 102*918dfc20SMatthew G. Knepley EM_MIXED, 103*918dfc20SMatthew G. Knepley EM_COULOMB, 104*918dfc20SMatthew G. Knepley EMNONE 105*918dfc20SMatthew G. Knepley } EMType; 106*918dfc20SMatthew G. Knepley 107*918dfc20SMatthew G. Knepley typedef enum { 108*918dfc20SMatthew G. Knepley V0, 109*918dfc20SMatthew G. Knepley X0, 110*918dfc20SMatthew G. Knepley T0, 111*918dfc20SMatthew G. Knepley M0, 112*918dfc20SMatthew G. Knepley Q0, 113*918dfc20SMatthew G. Knepley PHI0, 114*918dfc20SMatthew G. Knepley POISSON, 115*918dfc20SMatthew G. Knepley VLASOV, 116*918dfc20SMatthew G. Knepley SIGMA, 117*918dfc20SMatthew G. Knepley NUM_CONSTANTS 118*918dfc20SMatthew G. Knepley } ConstantType; 119*918dfc20SMatthew G. Knepley 120*918dfc20SMatthew G. Knepley typedef enum { 121*918dfc20SMatthew G. Knepley E_MONITOR_NONE, 122*918dfc20SMatthew G. Knepley E_MONITOR_FULL, 123*918dfc20SMatthew G. Knepley E_MONITOR_QUIET 124*918dfc20SMatthew G. Knepley } EMonitorType; 125*918dfc20SMatthew G. Knepley const char *const EMonitorTypes[] = {"NONE", "FULL", "QUIET", "EMonitorType", "E_MONITOR_", NULL}; 126*918dfc20SMatthew G. Knepley 127*918dfc20SMatthew G. Knepley typedef struct { 128*918dfc20SMatthew G. Knepley PetscScalar v0; /* Velocity scale, often the thermal velocity */ 129*918dfc20SMatthew G. Knepley PetscScalar t0; /* Time scale */ 130*918dfc20SMatthew G. Knepley PetscScalar x0; /* Space scale */ 131*918dfc20SMatthew G. Knepley PetscScalar m0; /* Mass scale */ 132*918dfc20SMatthew G. Knepley PetscScalar q0; /* Charge scale */ 133*918dfc20SMatthew G. Knepley PetscScalar kb; 134*918dfc20SMatthew G. Knepley PetscScalar epsi0; 135*918dfc20SMatthew G. Knepley PetscScalar phi0; /* Potential scale */ 136*918dfc20SMatthew G. Knepley PetscScalar poissonNumber; /* Non-Dimensional Poisson Number */ 137*918dfc20SMatthew G. Knepley PetscScalar vlasovNumber; /* Non-Dimensional Vlasov Number */ 138*918dfc20SMatthew G. Knepley PetscReal sigma; /* Nondimensional charge per length in x */ 139*918dfc20SMatthew G. Knepley } Parameter; 140*918dfc20SMatthew G. Knepley 141*918dfc20SMatthew G. Knepley typedef struct { 142*918dfc20SMatthew G. Knepley PetscBag bag; // Problem parameters 143*918dfc20SMatthew G. Knepley PetscBool error; // Flag for printing the error 144*918dfc20SMatthew G. Knepley PetscInt remapFreq; // Number of timesteps between remapping 145*918dfc20SMatthew G. Knepley EMonitorType efield_monitor; // Flag to show electric field monitor 146*918dfc20SMatthew G. Knepley PetscBool moment_monitor; // Flag to show distribution moment monitor 147*918dfc20SMatthew G. Knepley PetscBool moment_field_monitor; // Flag to show moment field monitor 148*918dfc20SMatthew G. Knepley PetscBool positions_monitor; // Flag to show particle positins at each time step 149*918dfc20SMatthew G. Knepley PetscBool poisson_monitor; // Flag to display charge, E field, and potential at each solve 150*918dfc20SMatthew G. Knepley PetscBool initial_monitor; // Flag to monitor the initial conditions 151*918dfc20SMatthew G. Knepley PetscInt velocity_monitor; // Cell to monitor the velocity distribution for 152*918dfc20SMatthew G. Knepley PetscBool perturbed_weights; // Uniformly sample x,v space with gaussian weights 153*918dfc20SMatthew G. Knepley PetscInt ostep; // Print the energy at each ostep time steps 154*918dfc20SMatthew G. Knepley PetscInt numParticles; 155*918dfc20SMatthew G. Knepley PetscReal timeScale; /* Nondimensionalizing time scale */ 156*918dfc20SMatthew G. Knepley PetscReal charges[2]; /* The charges of each species */ 157*918dfc20SMatthew G. Knepley PetscReal masses[2]; /* The masses of each species */ 158*918dfc20SMatthew G. Knepley PetscReal thermal_energy[2]; /* Thermal Energy (used to get other constants)*/ 159*918dfc20SMatthew G. Knepley PetscReal cosine_coefficients[2]; /*(alpha, k)*/ 160*918dfc20SMatthew G. Knepley PetscReal totalWeight; 161*918dfc20SMatthew G. Knepley PetscReal stepSize; 162*918dfc20SMatthew G. Knepley PetscInt steps; 163*918dfc20SMatthew G. Knepley PetscReal initVel; 164*918dfc20SMatthew G. Knepley EMType em; // Type of electrostatic model 165*918dfc20SMatthew G. Knepley SNES snes; // EM solver 166*918dfc20SMatthew G. Knepley DM dmMom; // The DM for moment fields 167*918dfc20SMatthew G. Knepley DM dmN; // The DM for number density fields 168*918dfc20SMatthew G. Knepley IS isN; // The IS mapping dmN into dmMom 169*918dfc20SMatthew G. Knepley Mat MN; // The finite element mass matrix for number density 170*918dfc20SMatthew G. Knepley DM dmP; // The DM for momentum density fields 171*918dfc20SMatthew G. Knepley IS isP; // The IS mapping dmP into dmMom 172*918dfc20SMatthew G. Knepley Mat MP; // The finite element mass matrix for momentum density 173*918dfc20SMatthew G. Knepley DM dmE; // The DM for energy density (pressure) fields 174*918dfc20SMatthew G. Knepley IS isE; // The IS mapping dmE into dmMom 175*918dfc20SMatthew G. Knepley Mat ME; // The finite element mass matrix for energy density (pressure) 176*918dfc20SMatthew G. Knepley DM dmPot; // The DM for potential 177*918dfc20SMatthew G. Knepley Mat fftPot; // Fourier Transform operator for the potential 178*918dfc20SMatthew G. Knepley Vec fftX, fftY; // FFT vectors with phases added (complex parts) 179*918dfc20SMatthew G. Knepley IS fftReal; // The indices for real parts 180*918dfc20SMatthew G. Knepley IS isPot; // The IS for potential, or NULL in primal 181*918dfc20SMatthew G. Knepley Mat M; // The finite element mass matrix for potential 182*918dfc20SMatthew G. Knepley PetscFEGeom *fegeom; // Geometric information for the DM cells 183*918dfc20SMatthew G. Knepley PetscDrawHG drawhgic_x; // Histogram of the particle weight in each X cell 184*918dfc20SMatthew G. Knepley PetscDrawHG drawhgic_v; // Histogram of the particle weight in each X cell 185*918dfc20SMatthew G. Knepley PetscDrawHG drawhgcell_v; // Histogram of the particle weight in a given cell 186*918dfc20SMatthew G. Knepley PetscBool validE; // Flag to indicate E-field in swarm is valid 187*918dfc20SMatthew G. Knepley PetscReal drawlgEmin; // The minimum lg(E) to plot 188*918dfc20SMatthew G. Knepley PetscDrawLG drawlgE; // Logarithm of maximum electric field 189*918dfc20SMatthew G. Knepley PetscDrawSP drawspE; // Electric field at particle positions 190*918dfc20SMatthew G. Knepley PetscDrawSP drawspX; // Particle positions 191*918dfc20SMatthew G. Knepley PetscViewer viewerRho; // Charge density viewer 192*918dfc20SMatthew G. Knepley PetscViewer viewerRhoHat; // Charge density Fourier Transform viewer 193*918dfc20SMatthew G. Knepley PetscViewer viewerPhi; // Potential viewer 194*918dfc20SMatthew G. Knepley PetscViewer viewerN; // Number density viewer 195*918dfc20SMatthew G. Knepley PetscViewer viewerP; // Momentum density viewer 196*918dfc20SMatthew G. Knepley PetscViewer viewerE; // Energy density (pressure) viewer 197*918dfc20SMatthew G. Knepley DM swarm; // The particle swarm 198*918dfc20SMatthew G. Knepley PetscRandom random; // Used for particle perturbations 199*918dfc20SMatthew G. Knepley PetscBool twostream; // Flag for activating 2-stream setup 200*918dfc20SMatthew G. Knepley PetscBool checkweights; // Check weight normalization 201*918dfc20SMatthew G. Knepley PetscInt checkVRes; // Flag to check/output velocity residuals for nightly tests 202*918dfc20SMatthew G. Knepley PetscBool checkLandau; // Check the Landau damping result 203*918dfc20SMatthew G. Knepley PetscReal gamma; // The damping rate for Landau damping 204*918dfc20SMatthew G. Knepley PetscReal omega; // The perturbed oscillation frequency for Landau damping 205*918dfc20SMatthew G. Knepley 206*918dfc20SMatthew G. Knepley PetscLogEvent RhsXEvent, RhsVEvent, ESolveEvent, ETabEvent; 207*918dfc20SMatthew G. Knepley } AppCtx; 208*918dfc20SMatthew G. Knepley 209*918dfc20SMatthew G. Knepley static PetscErrorCode ProcessOptions(MPI_Comm comm, AppCtx *options) 210*918dfc20SMatthew G. Knepley { 211*918dfc20SMatthew G. Knepley PetscFunctionBeginUser; 212*918dfc20SMatthew G. Knepley PetscInt d = 2; 213*918dfc20SMatthew G. Knepley PetscInt maxSpecies = 2; 214*918dfc20SMatthew G. Knepley options->error = PETSC_FALSE; 215*918dfc20SMatthew G. Knepley options->remapFreq = 1; 216*918dfc20SMatthew G. Knepley options->efield_monitor = E_MONITOR_NONE; 217*918dfc20SMatthew G. Knepley options->moment_monitor = PETSC_FALSE; 218*918dfc20SMatthew G. Knepley options->moment_field_monitor = PETSC_FALSE; 219*918dfc20SMatthew G. Knepley options->initial_monitor = PETSC_FALSE; 220*918dfc20SMatthew G. Knepley options->perturbed_weights = PETSC_FALSE; 221*918dfc20SMatthew G. Knepley options->poisson_monitor = PETSC_FALSE; 222*918dfc20SMatthew G. Knepley options->positions_monitor = PETSC_FALSE; 223*918dfc20SMatthew G. Knepley options->velocity_monitor = -1; 224*918dfc20SMatthew G. Knepley options->ostep = 100; 225*918dfc20SMatthew G. Knepley options->timeScale = 2.0e-14; 226*918dfc20SMatthew G. Knepley options->charges[0] = -1.0; 227*918dfc20SMatthew G. Knepley options->charges[1] = 1.0; 228*918dfc20SMatthew G. Knepley options->masses[0] = 1.0; 229*918dfc20SMatthew G. Knepley options->masses[1] = 1000.0; 230*918dfc20SMatthew G. Knepley options->thermal_energy[0] = 1.0; 231*918dfc20SMatthew G. Knepley options->thermal_energy[1] = 1.0; 232*918dfc20SMatthew G. Knepley options->cosine_coefficients[0] = 0.01; 233*918dfc20SMatthew G. Knepley options->cosine_coefficients[1] = 0.5; 234*918dfc20SMatthew G. Knepley options->initVel = 1; 235*918dfc20SMatthew G. Knepley options->totalWeight = 1.0; 236*918dfc20SMatthew G. Knepley options->drawhgic_x = NULL; 237*918dfc20SMatthew G. Knepley options->drawhgic_v = NULL; 238*918dfc20SMatthew G. Knepley options->drawhgcell_v = NULL; 239*918dfc20SMatthew G. Knepley options->drawlgEmin = -6; 240*918dfc20SMatthew G. Knepley options->drawlgE = NULL; 241*918dfc20SMatthew G. Knepley options->drawspE = NULL; 242*918dfc20SMatthew G. Knepley options->drawspX = NULL; 243*918dfc20SMatthew G. Knepley options->viewerRho = NULL; 244*918dfc20SMatthew G. Knepley options->viewerRhoHat = NULL; 245*918dfc20SMatthew G. Knepley options->viewerPhi = NULL; 246*918dfc20SMatthew G. Knepley options->viewerN = NULL; 247*918dfc20SMatthew G. Knepley options->viewerP = NULL; 248*918dfc20SMatthew G. Knepley options->viewerE = NULL; 249*918dfc20SMatthew G. Knepley options->em = EM_COULOMB; 250*918dfc20SMatthew G. Knepley options->snes = NULL; 251*918dfc20SMatthew G. Knepley options->dmMom = NULL; 252*918dfc20SMatthew G. Knepley options->dmN = NULL; 253*918dfc20SMatthew G. Knepley options->MN = NULL; 254*918dfc20SMatthew G. Knepley options->dmP = NULL; 255*918dfc20SMatthew G. Knepley options->MP = NULL; 256*918dfc20SMatthew G. Knepley options->dmE = NULL; 257*918dfc20SMatthew G. Knepley options->ME = NULL; 258*918dfc20SMatthew G. Knepley options->dmPot = NULL; 259*918dfc20SMatthew G. Knepley options->fftPot = NULL; 260*918dfc20SMatthew G. Knepley options->fftX = NULL; 261*918dfc20SMatthew G. Knepley options->fftY = NULL; 262*918dfc20SMatthew G. Knepley options->fftReal = NULL; 263*918dfc20SMatthew G. Knepley options->isPot = NULL; 264*918dfc20SMatthew G. Knepley options->M = NULL; 265*918dfc20SMatthew G. Knepley options->numParticles = 32768; 266*918dfc20SMatthew G. Knepley options->twostream = PETSC_FALSE; 267*918dfc20SMatthew G. Knepley options->checkweights = PETSC_FALSE; 268*918dfc20SMatthew G. Knepley options->checkVRes = 0; 269*918dfc20SMatthew G. Knepley options->checkLandau = PETSC_FALSE; 270*918dfc20SMatthew G. Knepley 271*918dfc20SMatthew G. Knepley PetscOptionsBegin(comm, "", "Landau Damping and Two Stream options", "DMSWARM"); 272*918dfc20SMatthew G. Knepley PetscCall(PetscOptionsBool("-error", "Flag to print the error", __FILE__, options->error, &options->error, NULL)); 273*918dfc20SMatthew G. Knepley PetscCall(PetscOptionsInt("-remap_freq", "Number", __FILE__, options->remapFreq, &options->remapFreq, NULL)); 274*918dfc20SMatthew 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)); 275*918dfc20SMatthew G. Knepley PetscCall(PetscOptionsReal("-efield_min_monitor", "Minimum E field to plot", __FILE__, options->drawlgEmin, &options->drawlgEmin, NULL)); 276*918dfc20SMatthew G. Knepley PetscCall(PetscOptionsBool("-moments_monitor", "Flag to show moments table", __FILE__, options->moment_monitor, &options->moment_monitor, NULL)); 277*918dfc20SMatthew G. Knepley PetscCall(PetscOptionsBool("-moment_field_monitor", "Flag to show moment fields", __FILE__, options->moment_field_monitor, &options->moment_field_monitor, NULL)); 278*918dfc20SMatthew G. Knepley PetscCall(PetscOptionsBool("-ics_monitor", "Flag to show initial condition histograms", __FILE__, options->initial_monitor, &options->initial_monitor, NULL)); 279*918dfc20SMatthew G. Knepley PetscCall(PetscOptionsBool("-positions_monitor", "The flag to show particle positions", __FILE__, options->positions_monitor, &options->positions_monitor, NULL)); 280*918dfc20SMatthew G. Knepley PetscCall(PetscOptionsBool("-poisson_monitor", "The flag to show charges, Efield and potential solve", __FILE__, options->poisson_monitor, &options->poisson_monitor, NULL)); 281*918dfc20SMatthew G. Knepley PetscCall(PetscOptionsInt("-velocity_monitor", "Cell to show velocity histograms", __FILE__, options->velocity_monitor, &options->velocity_monitor, NULL)); 282*918dfc20SMatthew G. Knepley PetscCall(PetscOptionsBool("-twostream", "Run two stream instability", __FILE__, options->twostream, &options->twostream, NULL)); 283*918dfc20SMatthew G. Knepley PetscCall(PetscOptionsBool("-perturbed_weights", "Flag to run uniform sampling with perturbed weights", __FILE__, options->perturbed_weights, &options->perturbed_weights, NULL)); 284*918dfc20SMatthew G. Knepley PetscCall(PetscOptionsBool("-check_weights", "Ensure all particle weights are positive", __FILE__, options->checkweights, &options->checkweights, NULL)); 285*918dfc20SMatthew G. Knepley PetscCall(PetscOptionsBool("-check_landau", "Check the decay from Landau damping", __FILE__, options->checkLandau, &options->checkLandau, NULL)); 286*918dfc20SMatthew G. Knepley PetscCall(PetscOptionsInt("-output_step", "Number of time steps between output", __FILE__, options->ostep, &options->ostep, NULL)); 287*918dfc20SMatthew G. Knepley PetscCall(PetscOptionsReal("-timeScale", "Nondimensionalizing time scale", __FILE__, options->timeScale, &options->timeScale, NULL)); 288*918dfc20SMatthew G. Knepley PetscCall(PetscOptionsInt("-check_vel_res", "Check particle velocity residuals for nightly tests", __FILE__, options->checkVRes, &options->checkVRes, NULL)); 289*918dfc20SMatthew G. Knepley PetscCall(PetscOptionsReal("-initial_velocity", "Initial velocity of perturbed particle", __FILE__, options->initVel, &options->initVel, NULL)); 290*918dfc20SMatthew G. Knepley PetscCall(PetscOptionsReal("-total_weight", "Total weight of all particles", __FILE__, options->totalWeight, &options->totalWeight, NULL)); 291*918dfc20SMatthew G. Knepley PetscCall(PetscOptionsRealArray("-cosine_coefficients", "Amplitude and frequency of cosine equation used in initialization", __FILE__, options->cosine_coefficients, &d, NULL)); 292*918dfc20SMatthew G. Knepley PetscCall(PetscOptionsRealArray("-charges", "Species charges", __FILE__, options->charges, &maxSpecies, NULL)); 293*918dfc20SMatthew G. Knepley PetscCall(PetscOptionsEnum("-em_type", "Type of electrostatic solver", __FILE__, EMTypes, (PetscEnum)options->em, (PetscEnum *)&options->em, NULL)); 294*918dfc20SMatthew G. Knepley PetscOptionsEnd(); 295*918dfc20SMatthew G. Knepley 296*918dfc20SMatthew G. Knepley PetscCall(PetscLogEventRegister("RhsX", TS_CLASSID, &options->RhsXEvent)); 297*918dfc20SMatthew G. Knepley PetscCall(PetscLogEventRegister("RhsV", TS_CLASSID, &options->RhsVEvent)); 298*918dfc20SMatthew G. Knepley PetscCall(PetscLogEventRegister("ESolve", TS_CLASSID, &options->ESolveEvent)); 299*918dfc20SMatthew G. Knepley PetscCall(PetscLogEventRegister("ETab", TS_CLASSID, &options->ETabEvent)); 300*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 301*918dfc20SMatthew G. Knepley } 302*918dfc20SMatthew G. Knepley 303*918dfc20SMatthew G. Knepley static PetscErrorCode SetupContext(DM dm, DM sw, AppCtx *user) 304*918dfc20SMatthew G. Knepley { 305*918dfc20SMatthew G. Knepley MPI_Comm comm; 306*918dfc20SMatthew G. Knepley 307*918dfc20SMatthew G. Knepley PetscFunctionBeginUser; 308*918dfc20SMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 309*918dfc20SMatthew G. Knepley if (user->efield_monitor) { 310*918dfc20SMatthew G. Knepley PetscDraw draw; 311*918dfc20SMatthew G. Knepley PetscDrawAxis axis; 312*918dfc20SMatthew G. Knepley 313*918dfc20SMatthew G. Knepley if (user->efield_monitor == E_MONITOR_FULL) { 314*918dfc20SMatthew G. Knepley PetscCall(PetscDrawCreate(comm, NULL, "Max Electric Field", 0, 300, 400, 300, &draw)); 315*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSetSave(draw, "ex2_Efield")); 316*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSetFromOptions(draw)); 317*918dfc20SMatthew G. Knepley } else { 318*918dfc20SMatthew G. Knepley PetscCall(PetscDrawOpenNull(comm, &draw)); 319*918dfc20SMatthew G. Knepley } 320*918dfc20SMatthew G. Knepley PetscCall(PetscDrawLGCreate(draw, 1, &user->drawlgE)); 321*918dfc20SMatthew G. Knepley PetscCall(PetscDrawDestroy(&draw)); 322*918dfc20SMatthew G. Knepley PetscCall(PetscDrawLGGetAxis(user->drawlgE, &axis)); 323*918dfc20SMatthew G. Knepley PetscCall(PetscDrawAxisSetLabels(axis, "Max Electric Field", "time", "E_max")); 324*918dfc20SMatthew G. Knepley PetscCall(PetscDrawLGSetLimits(user->drawlgE, 0., user->steps * user->stepSize, user->drawlgEmin, 0.)); 325*918dfc20SMatthew G. Knepley } 326*918dfc20SMatthew G. Knepley 327*918dfc20SMatthew G. Knepley if (user->initial_monitor) { 328*918dfc20SMatthew G. Knepley PetscDraw drawic_x, drawic_v; 329*918dfc20SMatthew G. Knepley PetscDrawAxis axis1, axis2; 330*918dfc20SMatthew G. Knepley PetscReal dmboxlower[2], dmboxupper[2]; 331*918dfc20SMatthew G. Knepley PetscInt dim, cStart, cEnd; 332*918dfc20SMatthew G. Knepley 333*918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim)); 334*918dfc20SMatthew G. Knepley PetscCall(DMGetBoundingBox(dm, dmboxlower, dmboxupper)); 335*918dfc20SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 336*918dfc20SMatthew G. Knepley 337*918dfc20SMatthew G. Knepley PetscCall(PetscDrawCreate(comm, NULL, "monitor_initial_conditions_x", 0, 300, 400, 300, &drawic_x)); 338*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSetSave(drawic_x, "ex2_ic_x")); 339*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSetFromOptions(drawic_x)); 340*918dfc20SMatthew G. Knepley PetscCall(PetscDrawHGCreate(drawic_x, (int)dim, &user->drawhgic_x)); 341*918dfc20SMatthew G. Knepley PetscCall(PetscDrawHGCalcStats(user->drawhgic_x, PETSC_TRUE)); 342*918dfc20SMatthew G. Knepley PetscCall(PetscDrawHGGetAxis(user->drawhgic_x, &axis1)); 343*918dfc20SMatthew G. Knepley PetscCall(PetscDrawHGSetNumberBins(user->drawhgic_x, (int)(cEnd - cStart))); 344*918dfc20SMatthew G. Knepley PetscCall(PetscDrawAxisSetLabels(axis1, "Initial X Distribution", "X", "weight")); 345*918dfc20SMatthew G. Knepley PetscCall(PetscDrawAxisSetLimits(axis1, dmboxlower[0], dmboxupper[0], 0, 0)); 346*918dfc20SMatthew G. Knepley PetscCall(PetscDrawDestroy(&drawic_x)); 347*918dfc20SMatthew G. Knepley 348*918dfc20SMatthew G. Knepley PetscCall(PetscDrawCreate(comm, NULL, "monitor_initial_conditions_v", 400, 300, 400, 300, &drawic_v)); 349*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSetSave(drawic_v, "ex9_ic_v")); 350*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSetFromOptions(drawic_v)); 351*918dfc20SMatthew G. Knepley PetscCall(PetscDrawHGCreate(drawic_v, (int)dim, &user->drawhgic_v)); 352*918dfc20SMatthew G. Knepley PetscCall(PetscDrawHGCalcStats(user->drawhgic_v, PETSC_TRUE)); 353*918dfc20SMatthew G. Knepley PetscCall(PetscDrawHGGetAxis(user->drawhgic_v, &axis2)); 354*918dfc20SMatthew G. Knepley PetscCall(PetscDrawHGSetNumberBins(user->drawhgic_v, 21)); 355*918dfc20SMatthew G. Knepley PetscCall(PetscDrawAxisSetLabels(axis2, "Initial V_x Distribution", "V", "weight")); 356*918dfc20SMatthew G. Knepley PetscCall(PetscDrawAxisSetLimits(axis2, -6, 6, 0, 0)); 357*918dfc20SMatthew G. Knepley PetscCall(PetscDrawDestroy(&drawic_v)); 358*918dfc20SMatthew G. Knepley } 359*918dfc20SMatthew G. Knepley 360*918dfc20SMatthew G. Knepley if (user->velocity_monitor >= 0) { 361*918dfc20SMatthew G. Knepley DM vdm; 362*918dfc20SMatthew G. Knepley DMSwarmCellDM celldm; 363*918dfc20SMatthew G. Knepley PetscDraw drawcell_v; 364*918dfc20SMatthew G. Knepley PetscDrawAxis axis; 365*918dfc20SMatthew G. Knepley PetscReal dmboxlower[2], dmboxupper[2]; 366*918dfc20SMatthew G. Knepley PetscInt dim; 367*918dfc20SMatthew G. Knepley char title[PETSC_MAX_PATH_LEN]; 368*918dfc20SMatthew G. Knepley 369*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetCellDMByName(sw, "velocity", &celldm)); 370*918dfc20SMatthew G. Knepley PetscCall(DMSwarmCellDMGetDM(celldm, &vdm)); 371*918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(vdm, &dim)); 372*918dfc20SMatthew G. Knepley PetscCall(DMGetBoundingBox(vdm, dmboxlower, dmboxupper)); 373*918dfc20SMatthew G. Knepley 374*918dfc20SMatthew G. Knepley PetscCall(PetscSNPrintf(title, PETSC_MAX_PATH_LEN, "Cell %" PetscInt_FMT ": Velocity Distribution", user->velocity_monitor)); 375*918dfc20SMatthew G. Knepley PetscCall(PetscDrawCreate(comm, NULL, title, 400, 300, 400, 300, &drawcell_v)); 376*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSetSave(drawcell_v, "ex2_cell_v")); 377*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSetFromOptions(drawcell_v)); 378*918dfc20SMatthew G. Knepley PetscCall(PetscDrawHGCreate(drawcell_v, (int)dim, &user->drawhgcell_v)); 379*918dfc20SMatthew G. Knepley PetscCall(PetscDrawHGCalcStats(user->drawhgcell_v, PETSC_TRUE)); 380*918dfc20SMatthew G. Knepley PetscCall(PetscDrawHGGetAxis(user->drawhgcell_v, &axis)); 381*918dfc20SMatthew G. Knepley PetscCall(PetscDrawHGSetNumberBins(user->drawhgcell_v, 21)); 382*918dfc20SMatthew G. Knepley PetscCall(PetscDrawAxisSetLabels(axis, "V_x Distribution", "V", "weight")); 383*918dfc20SMatthew G. Knepley PetscCall(PetscDrawAxisSetLimits(axis, dmboxlower[0], dmboxupper[0], 0, 0)); 384*918dfc20SMatthew G. Knepley PetscCall(PetscDrawDestroy(&drawcell_v)); 385*918dfc20SMatthew G. Knepley } 386*918dfc20SMatthew G. Knepley 387*918dfc20SMatthew G. Knepley if (user->positions_monitor) { 388*918dfc20SMatthew G. Knepley PetscDraw draw; 389*918dfc20SMatthew G. Knepley PetscDrawAxis axis; 390*918dfc20SMatthew G. Knepley 391*918dfc20SMatthew G. Knepley PetscCall(PetscDrawCreate(comm, NULL, "Particle Position", 0, 0, 400, 300, &draw)); 392*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSetSave(draw, "ex9_pos")); 393*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSetFromOptions(draw)); 394*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSPCreate(draw, 10, &user->drawspX)); 395*918dfc20SMatthew G. Knepley PetscCall(PetscDrawDestroy(&draw)); 396*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSPSetDimension(user->drawspX, 1)); 397*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSPGetAxis(user->drawspX, &axis)); 398*918dfc20SMatthew G. Knepley PetscCall(PetscDrawAxisSetLabels(axis, "Particles", "x", "v")); 399*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSPReset(user->drawspX)); 400*918dfc20SMatthew G. Knepley } 401*918dfc20SMatthew G. Knepley if (user->poisson_monitor) { 402*918dfc20SMatthew G. Knepley Vec rho, rhohat, phi; 403*918dfc20SMatthew G. Knepley PetscDraw draw; 404*918dfc20SMatthew G. Knepley PetscDrawAxis axis; 405*918dfc20SMatthew G. Knepley 406*918dfc20SMatthew G. Knepley PetscCall(PetscDrawCreate(comm, NULL, "Electric_Field", 0, 0, 400, 300, &draw)); 407*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSetFromOptions(draw)); 408*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSetSave(draw, "ex9_E_spatial")); 409*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSPCreate(draw, 10, &user->drawspE)); 410*918dfc20SMatthew G. Knepley PetscCall(PetscDrawDestroy(&draw)); 411*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSPSetDimension(user->drawspE, 1)); 412*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSPGetAxis(user->drawspE, &axis)); 413*918dfc20SMatthew G. Knepley PetscCall(PetscDrawAxisSetLabels(axis, "Particles", "x", "E")); 414*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSPReset(user->drawspE)); 415*918dfc20SMatthew G. Knepley 416*918dfc20SMatthew G. Knepley PetscCall(PetscViewerDrawOpen(comm, NULL, "Charge Density", 0, 0, 400, 300, &user->viewerRho)); 417*918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)user->viewerRho, "rho_")); 418*918dfc20SMatthew G. Knepley PetscCall(PetscViewerDrawGetDraw(user->viewerRho, 0, &draw)); 419*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSetSave(draw, "ex9_rho_spatial")); 420*918dfc20SMatthew G. Knepley PetscCall(PetscViewerSetFromOptions(user->viewerRho)); 421*918dfc20SMatthew G. Knepley PetscCall(DMGetNamedGlobalVector(user->dmPot, "rho", &rho)); 422*918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)rho, "charge_density")); 423*918dfc20SMatthew G. Knepley PetscCall(DMRestoreNamedGlobalVector(user->dmPot, "rho", &rho)); 424*918dfc20SMatthew G. Knepley 425*918dfc20SMatthew G. Knepley PetscInt dim, N; 426*918dfc20SMatthew G. Knepley 427*918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(user->dmPot, &dim)); 428*918dfc20SMatthew G. Knepley if (dim == 1) { 429*918dfc20SMatthew G. Knepley PetscCall(DMGetNamedGlobalVector(user->dmPot, "rhohat", &rhohat)); 430*918dfc20SMatthew G. Knepley PetscCall(VecGetSize(rhohat, &N)); 431*918dfc20SMatthew G. Knepley PetscCall(MatCreateFFT(comm, dim, &N, MATFFTW, &user->fftPot)); 432*918dfc20SMatthew G. Knepley PetscCall(DMRestoreNamedGlobalVector(user->dmPot, "rhohat", &rhohat)); 433*918dfc20SMatthew G. Knepley PetscCall(MatCreateVecs(user->fftPot, &user->fftX, &user->fftY)); 434*918dfc20SMatthew G. Knepley PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &user->fftReal)); 435*918dfc20SMatthew G. Knepley } 436*918dfc20SMatthew G. Knepley 437*918dfc20SMatthew G. Knepley PetscCall(PetscViewerDrawOpen(comm, NULL, "rhohat: Charge Density FT", 0, 0, 400, 300, &user->viewerRhoHat)); 438*918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)user->viewerRhoHat, "rhohat_")); 439*918dfc20SMatthew G. Knepley PetscCall(PetscViewerDrawGetDraw(user->viewerRhoHat, 0, &draw)); 440*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSetSave(draw, "ex9_rho_ft")); 441*918dfc20SMatthew G. Knepley PetscCall(PetscViewerSetFromOptions(user->viewerRhoHat)); 442*918dfc20SMatthew G. Knepley PetscCall(DMGetNamedGlobalVector(user->dmPot, "rhohat", &rhohat)); 443*918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)rhohat, "charge_density_ft")); 444*918dfc20SMatthew G. Knepley PetscCall(DMRestoreNamedGlobalVector(user->dmPot, "rhohat", &rhohat)); 445*918dfc20SMatthew G. Knepley 446*918dfc20SMatthew G. Knepley PetscCall(PetscViewerDrawOpen(comm, NULL, "Potential", 400, 0, 400, 300, &user->viewerPhi)); 447*918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)user->viewerPhi, "phi_")); 448*918dfc20SMatthew G. Knepley PetscCall(PetscViewerDrawGetDraw(user->viewerPhi, 0, &draw)); 449*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSetSave(draw, "ex9_phi_spatial")); 450*918dfc20SMatthew G. Knepley PetscCall(PetscViewerSetFromOptions(user->viewerPhi)); 451*918dfc20SMatthew G. Knepley PetscCall(DMGetNamedGlobalVector(user->dmPot, "phi", &phi)); 452*918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)phi, "potential")); 453*918dfc20SMatthew G. Knepley PetscCall(DMRestoreNamedGlobalVector(user->dmPot, "phi", &phi)); 454*918dfc20SMatthew G. Knepley } 455*918dfc20SMatthew G. Knepley if (user->moment_field_monitor) { 456*918dfc20SMatthew G. Knepley Vec n, p, e; 457*918dfc20SMatthew G. Knepley PetscDraw draw; 458*918dfc20SMatthew G. Knepley 459*918dfc20SMatthew G. Knepley PetscCall(PetscViewerDrawOpen(comm, NULL, "Number Density", 0, 800, 400, 300, &user->viewerN)); 460*918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)user->viewerN, "n_")); 461*918dfc20SMatthew G. Knepley PetscCall(PetscViewerDrawGetDraw(user->viewerN, 0, &draw)); 462*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSetSave(draw, "ex9_n_spatial")); 463*918dfc20SMatthew G. Knepley PetscCall(PetscViewerSetFromOptions(user->viewerN)); 464*918dfc20SMatthew G. Knepley PetscCall(DMGetNamedGlobalVector(user->dmN, "n", &n)); 465*918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)n, "Number Density")); 466*918dfc20SMatthew G. Knepley PetscCall(DMRestoreNamedGlobalVector(user->dmN, "n", &n)); 467*918dfc20SMatthew G. Knepley 468*918dfc20SMatthew G. Knepley PetscCall(PetscViewerDrawOpen(comm, NULL, "Momentum Density", 400, 800, 400, 300, &user->viewerP)); 469*918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)user->viewerP, "p_")); 470*918dfc20SMatthew G. Knepley PetscCall(PetscViewerDrawGetDraw(user->viewerP, 0, &draw)); 471*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSetSave(draw, "ex9_p_spatial")); 472*918dfc20SMatthew G. Knepley PetscCall(PetscViewerSetFromOptions(user->viewerP)); 473*918dfc20SMatthew G. Knepley PetscCall(DMGetNamedGlobalVector(user->dmP, "p", &p)); 474*918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)p, "Momentum Density")); 475*918dfc20SMatthew G. Knepley PetscCall(DMRestoreNamedGlobalVector(user->dmP, "p", &p)); 476*918dfc20SMatthew G. Knepley 477*918dfc20SMatthew G. Knepley PetscCall(PetscViewerDrawOpen(comm, NULL, "Emergy Density (Pressure)", 800, 800, 400, 300, &user->viewerE)); 478*918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)user->viewerE, "e_")); 479*918dfc20SMatthew G. Knepley PetscCall(PetscViewerDrawGetDraw(user->viewerE, 0, &draw)); 480*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSetSave(draw, "ex9_e_spatial")); 481*918dfc20SMatthew G. Knepley PetscCall(PetscViewerSetFromOptions(user->viewerE)); 482*918dfc20SMatthew G. Knepley PetscCall(DMGetNamedGlobalVector(user->dmE, "e", &e)); 483*918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)e, "Energy Density (Pressure)")); 484*918dfc20SMatthew G. Knepley PetscCall(DMRestoreNamedGlobalVector(user->dmE, "e", &e)); 485*918dfc20SMatthew G. Knepley } 486*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 487*918dfc20SMatthew G. Knepley } 488*918dfc20SMatthew G. Knepley 489*918dfc20SMatthew G. Knepley static PetscErrorCode DestroyContext(AppCtx *user) 490*918dfc20SMatthew G. Knepley { 491*918dfc20SMatthew G. Knepley PetscFunctionBeginUser; 492*918dfc20SMatthew G. Knepley PetscCall(PetscDrawHGDestroy(&user->drawhgic_x)); 493*918dfc20SMatthew G. Knepley PetscCall(PetscDrawHGDestroy(&user->drawhgic_v)); 494*918dfc20SMatthew G. Knepley PetscCall(PetscDrawHGDestroy(&user->drawhgcell_v)); 495*918dfc20SMatthew G. Knepley 496*918dfc20SMatthew G. Knepley PetscCall(PetscDrawLGDestroy(&user->drawlgE)); 497*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSPDestroy(&user->drawspE)); 498*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSPDestroy(&user->drawspX)); 499*918dfc20SMatthew G. Knepley PetscCall(PetscViewerDestroy(&user->viewerRho)); 500*918dfc20SMatthew G. Knepley PetscCall(PetscViewerDestroy(&user->viewerRhoHat)); 501*918dfc20SMatthew G. Knepley PetscCall(MatDestroy(&user->fftPot)); 502*918dfc20SMatthew G. Knepley PetscCall(VecDestroy(&user->fftX)); 503*918dfc20SMatthew G. Knepley PetscCall(VecDestroy(&user->fftY)); 504*918dfc20SMatthew G. Knepley PetscCall(ISDestroy(&user->fftReal)); 505*918dfc20SMatthew G. Knepley PetscCall(PetscViewerDestroy(&user->viewerPhi)); 506*918dfc20SMatthew G. Knepley PetscCall(PetscViewerDestroy(&user->viewerN)); 507*918dfc20SMatthew G. Knepley PetscCall(PetscViewerDestroy(&user->viewerP)); 508*918dfc20SMatthew G. Knepley PetscCall(PetscViewerDestroy(&user->viewerE)); 509*918dfc20SMatthew G. Knepley 510*918dfc20SMatthew G. Knepley PetscCall(PetscBagDestroy(&user->bag)); 511*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 512*918dfc20SMatthew G. Knepley } 513*918dfc20SMatthew G. Knepley 514*918dfc20SMatthew G. Knepley static PetscErrorCode CheckNonNegativeWeights(DM sw, AppCtx *user) 515*918dfc20SMatthew G. Knepley { 516*918dfc20SMatthew G. Knepley const PetscScalar *w; 517*918dfc20SMatthew G. Knepley PetscInt Np; 518*918dfc20SMatthew G. Knepley 519*918dfc20SMatthew G. Knepley PetscFunctionBeginUser; 520*918dfc20SMatthew G. Knepley if (!user->checkweights) PetscFunctionReturn(PETSC_SUCCESS); 521*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "w_q", NULL, NULL, (void **)&w)); 522*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(sw, &Np)); 523*918dfc20SMatthew 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]); 524*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "w_q", NULL, NULL, (void **)&w)); 525*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 526*918dfc20SMatthew G. Knepley } 527*918dfc20SMatthew G. Knepley 528*918dfc20SMatthew G. Knepley static PetscErrorCode computeVelocityFEMMoments(DM sw, PetscReal moments[], AppCtx *user) 529*918dfc20SMatthew G. Knepley { 530*918dfc20SMatthew G. Knepley DMSwarmCellDM celldm; 531*918dfc20SMatthew G. Knepley DM vdm; 532*918dfc20SMatthew G. Knepley Vec u[1]; 533*918dfc20SMatthew G. Knepley const char *fields[1] = {"w_q"}; 534*918dfc20SMatthew G. Knepley 535*918dfc20SMatthew G. Knepley PetscFunctionBegin; 536*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSetCellDMActive(sw, "velocity")); 537*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetCellDMActive(sw, &celldm)); 538*918dfc20SMatthew G. Knepley PetscCall(DMSwarmCellDMGetDM(celldm, &vdm)); 539*918dfc20SMatthew G. Knepley PetscCall(DMGetGlobalVector(vdm, &u[0])); 540*918dfc20SMatthew G. Knepley PetscCall(DMSwarmProjectFields(sw, vdm, 1, fields, u, SCATTER_FORWARD)); 541*918dfc20SMatthew G. Knepley PetscCall(DMPlexComputeMoments(vdm, u[0], moments)); 542*918dfc20SMatthew G. Knepley PetscCall(DMRestoreGlobalVector(vdm, &u[0])); 543*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSetCellDMActive(sw, "space")); 544*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 545*918dfc20SMatthew G. Knepley } 546*918dfc20SMatthew G. Knepley 547*918dfc20SMatthew 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[]) 548*918dfc20SMatthew G. Knepley { 549*918dfc20SMatthew G. Knepley f0[0] = 0.; 550*918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) f0[0] += PetscSqr(u_x[uOff_x[0] + d * dim + d]); 551*918dfc20SMatthew G. Knepley } 552*918dfc20SMatthew G. Knepley 553*918dfc20SMatthew G. Knepley typedef struct { 554*918dfc20SMatthew G. Knepley PetscInt s; // Starting sample (we ignore some in the beginning) 555*918dfc20SMatthew G. Knepley PetscInt e; // Ending sample 556*918dfc20SMatthew G. Knepley const PetscReal *t; // Time for each sample 557*918dfc20SMatthew G. Knepley const PetscReal *Emax; // Emax for each sample 558*918dfc20SMatthew G. Knepley } EmaxCtx; 559*918dfc20SMatthew G. Knepley 560*918dfc20SMatthew G. Knepley // Our model is E_max(t) = C e^{-gamma t} |cos(omega t - phi)| 561*918dfc20SMatthew G. Knepley static PetscErrorCode ComputeEmaxResidual(Tao tao, Vec x, Vec res, void *user) 562*918dfc20SMatthew G. Knepley { 563*918dfc20SMatthew G. Knepley EmaxCtx *ctx = (EmaxCtx *)user; 564*918dfc20SMatthew G. Knepley const PetscScalar *a; 565*918dfc20SMatthew G. Knepley PetscScalar *F; 566*918dfc20SMatthew G. Knepley PetscReal C, gamma, omega, phi; 567*918dfc20SMatthew G. Knepley 568*918dfc20SMatthew G. Knepley PetscFunctionBegin; 569*918dfc20SMatthew G. Knepley PetscCall(VecGetArrayRead(x, &a)); 570*918dfc20SMatthew G. Knepley PetscCall(VecGetArray(res, &F)); 571*918dfc20SMatthew G. Knepley C = PetscRealPart(a[0]); 572*918dfc20SMatthew G. Knepley gamma = PetscRealPart(a[1]); 573*918dfc20SMatthew G. Knepley omega = PetscRealPart(a[2]); 574*918dfc20SMatthew G. Knepley phi = PetscRealPart(a[3]); 575*918dfc20SMatthew G. Knepley PetscCall(VecRestoreArrayRead(x, &a)); 576*918dfc20SMatthew 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)); 577*918dfc20SMatthew G. Knepley PetscCall(VecRestoreArray(res, &F)); 578*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 579*918dfc20SMatthew G. Knepley } 580*918dfc20SMatthew G. Knepley 581*918dfc20SMatthew G. Knepley // The Jacobian of the residual J = dr(x)/dx 582*918dfc20SMatthew G. Knepley static PetscErrorCode ComputeEmaxJacobian(Tao tao, Vec x, Mat J, Mat Jpre, void *user) 583*918dfc20SMatthew G. Knepley { 584*918dfc20SMatthew G. Knepley EmaxCtx *ctx = (EmaxCtx *)user; 585*918dfc20SMatthew G. Knepley const PetscScalar *a; 586*918dfc20SMatthew G. Knepley PetscScalar *jac; 587*918dfc20SMatthew G. Knepley PetscReal C, gamma, omega, phi; 588*918dfc20SMatthew G. Knepley const PetscInt n = ctx->e - ctx->s; 589*918dfc20SMatthew G. Knepley 590*918dfc20SMatthew G. Knepley PetscFunctionBegin; 591*918dfc20SMatthew G. Knepley PetscCall(VecGetArrayRead(x, &a)); 592*918dfc20SMatthew G. Knepley C = PetscRealPart(a[0]); 593*918dfc20SMatthew G. Knepley gamma = PetscRealPart(a[1]); 594*918dfc20SMatthew G. Knepley omega = PetscRealPart(a[2]); 595*918dfc20SMatthew G. Knepley phi = PetscRealPart(a[3]); 596*918dfc20SMatthew G. Knepley PetscCall(VecRestoreArrayRead(x, &a)); 597*918dfc20SMatthew G. Knepley PetscCall(MatDenseGetArray(J, &jac)); 598*918dfc20SMatthew G. Knepley for (PetscInt i = 0; i < n; ++i) { 599*918dfc20SMatthew G. Knepley const PetscInt k = i + ctx->s; 600*918dfc20SMatthew G. Knepley 601*918dfc20SMatthew G. Knepley jac[i * 4 + 0] = -PetscExpReal(-gamma * ctx->t[k]) * PetscAbsReal(PetscCosReal(omega * ctx->t[k] - phi)); 602*918dfc20SMatthew G. Knepley jac[i * 4 + 1] = C * ctx->t[k] * PetscExpReal(-gamma * ctx->t[k]) * PetscAbsReal(PetscCosReal(omega * ctx->t[k] - phi)); 603*918dfc20SMatthew 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); 604*918dfc20SMatthew 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); 605*918dfc20SMatthew G. Knepley } 606*918dfc20SMatthew G. Knepley PetscCall(MatDenseRestoreArray(J, &jac)); 607*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 608*918dfc20SMatthew G. Knepley } 609*918dfc20SMatthew G. Knepley 610*918dfc20SMatthew G. Knepley // Our model is log_10 E_max(t) = log_10 C - gamma t log_10 e + log_10 |cos(omega t - phi)| 611*918dfc20SMatthew G. Knepley static PetscErrorCode ComputeLogEmaxResidual(Tao tao, Vec x, Vec res, void *user) 612*918dfc20SMatthew G. Knepley { 613*918dfc20SMatthew G. Knepley EmaxCtx *ctx = (EmaxCtx *)user; 614*918dfc20SMatthew G. Knepley const PetscScalar *a; 615*918dfc20SMatthew G. Knepley PetscScalar *F; 616*918dfc20SMatthew G. Knepley PetscReal C, gamma, omega, phi; 617*918dfc20SMatthew G. Knepley 618*918dfc20SMatthew G. Knepley PetscFunctionBegin; 619*918dfc20SMatthew G. Knepley PetscCall(VecGetArrayRead(x, &a)); 620*918dfc20SMatthew G. Knepley PetscCall(VecGetArray(res, &F)); 621*918dfc20SMatthew G. Knepley C = PetscRealPart(a[0]); 622*918dfc20SMatthew G. Knepley gamma = PetscRealPart(a[1]); 623*918dfc20SMatthew G. Knepley omega = PetscRealPart(a[2]); 624*918dfc20SMatthew G. Knepley phi = PetscRealPart(a[3]); 625*918dfc20SMatthew G. Knepley PetscCall(VecRestoreArrayRead(x, &a)); 626*918dfc20SMatthew G. Knepley for (PetscInt i = ctx->s; i < ctx->e; ++i) { 627*918dfc20SMatthew G. Knepley if (C < 0) { 628*918dfc20SMatthew G. Knepley F[i - ctx->s] = 1e10; 629*918dfc20SMatthew G. Knepley continue; 630*918dfc20SMatthew G. Knepley } 631*918dfc20SMatthew 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)))); 632*918dfc20SMatthew G. Knepley } 633*918dfc20SMatthew G. Knepley PetscCall(VecRestoreArray(res, &F)); 634*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 635*918dfc20SMatthew G. Knepley } 636*918dfc20SMatthew G. Knepley 637*918dfc20SMatthew G. Knepley // The Jacobian of the residual J = dr(x)/dx 638*918dfc20SMatthew G. Knepley static PetscErrorCode ComputeLogEmaxJacobian(Tao tao, Vec x, Mat J, Mat Jpre, void *user) 639*918dfc20SMatthew G. Knepley { 640*918dfc20SMatthew G. Knepley EmaxCtx *ctx = (EmaxCtx *)user; 641*918dfc20SMatthew G. Knepley const PetscScalar *a; 642*918dfc20SMatthew G. Knepley PetscScalar *jac; 643*918dfc20SMatthew G. Knepley PetscReal C, omega, phi; 644*918dfc20SMatthew G. Knepley const PetscInt n = ctx->e - ctx->s; 645*918dfc20SMatthew G. Knepley 646*918dfc20SMatthew G. Knepley PetscFunctionBegin; 647*918dfc20SMatthew G. Knepley PetscCall(VecGetArrayRead(x, &a)); 648*918dfc20SMatthew G. Knepley C = PetscRealPart(a[0]); 649*918dfc20SMatthew G. Knepley omega = PetscRealPart(a[2]); 650*918dfc20SMatthew G. Knepley phi = PetscRealPart(a[3]); 651*918dfc20SMatthew G. Knepley PetscCall(VecRestoreArrayRead(x, &a)); 652*918dfc20SMatthew G. Knepley PetscCall(MatDenseGetArray(J, &jac)); 653*918dfc20SMatthew G. Knepley for (PetscInt i = 0; i < n; ++i) { 654*918dfc20SMatthew G. Knepley const PetscInt k = i + ctx->s; 655*918dfc20SMatthew G. Knepley 656*918dfc20SMatthew G. Knepley jac[0 * n + i] = -1. / (PetscLog10Real(PETSC_E) * C); 657*918dfc20SMatthew G. Knepley jac[1 * n + i] = ctx->t[k] * PetscLog10Real(PETSC_E); 658*918dfc20SMatthew 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))); 659*918dfc20SMatthew 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))); 660*918dfc20SMatthew G. Knepley } 661*918dfc20SMatthew G. Knepley PetscCall(MatDenseRestoreArray(J, &jac)); 662*918dfc20SMatthew G. Knepley PetscCall(MatViewFromOptions(J, NULL, "-emax_jac_view")); 663*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 664*918dfc20SMatthew G. Knepley } 665*918dfc20SMatthew G. Knepley 666*918dfc20SMatthew G. Knepley static PetscErrorCode MonitorEField(TS ts, PetscInt step, PetscReal t, Vec U, void *ctx) 667*918dfc20SMatthew G. Knepley { 668*918dfc20SMatthew G. Knepley AppCtx *user = (AppCtx *)ctx; 669*918dfc20SMatthew G. Knepley DM sw; 670*918dfc20SMatthew G. Knepley PetscScalar intESq; 671*918dfc20SMatthew G. Knepley PetscReal *E, *x, *weight; 672*918dfc20SMatthew G. Knepley PetscReal Enorm = 0., lgEnorm, lgEmax, sum = 0., Emax = 0., chargesum = 0.; 673*918dfc20SMatthew G. Knepley PetscReal pmoments[4]; /* \int f, \int v f, \int v^2 f */ 674*918dfc20SMatthew G. Knepley PetscInt *species, dim, Np, gNp; 675*918dfc20SMatthew G. Knepley MPI_Comm comm; 676*918dfc20SMatthew G. Knepley PetscMPIInt rank; 677*918dfc20SMatthew G. Knepley 678*918dfc20SMatthew G. Knepley PetscFunctionBeginUser; 679*918dfc20SMatthew G. Knepley if (step < 0 || !user->validE) PetscFunctionReturn(PETSC_SUCCESS); 680*918dfc20SMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)ts, &comm)); 681*918dfc20SMatthew G. Knepley PetscCallMPI(MPI_Comm_rank(comm, &rank)); 682*918dfc20SMatthew G. Knepley PetscCall(TSGetDM(ts, &sw)); 683*918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim)); 684*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(sw, &Np)); 685*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetSize(sw, &gNp)); 686*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortGetAccess(sw)); 687*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&x)); 688*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "E_field", NULL, NULL, (void **)&E)); 689*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "species", NULL, NULL, (void **)&species)); 690*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "w_q", NULL, NULL, (void **)&weight)); 691*918dfc20SMatthew G. Knepley 692*918dfc20SMatthew G. Knepley for (PetscInt p = 0; p < Np; ++p) { 693*918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < 1; ++d) { 694*918dfc20SMatthew G. Knepley PetscReal temp = PetscAbsReal(E[p * dim + d]); 695*918dfc20SMatthew G. Knepley if (temp > Emax) Emax = temp; 696*918dfc20SMatthew G. Knepley } 697*918dfc20SMatthew G. Knepley Enorm += PetscSqrtReal(E[p * dim] * E[p * dim]); 698*918dfc20SMatthew G. Knepley sum += E[p * dim]; 699*918dfc20SMatthew G. Knepley chargesum += user->charges[0] * weight[p]; 700*918dfc20SMatthew G. Knepley } 701*918dfc20SMatthew G. Knepley PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &Emax, 1, MPIU_REAL, MPIU_MAX, comm)); 702*918dfc20SMatthew G. Knepley lgEnorm = Enorm != 0 ? PetscLog10Real(Enorm) : -16.; 703*918dfc20SMatthew G. Knepley lgEmax = Emax != 0 ? PetscLog10Real(Emax) : user->drawlgEmin; 704*918dfc20SMatthew G. Knepley 705*918dfc20SMatthew G. Knepley PetscDS ds; 706*918dfc20SMatthew G. Knepley Vec phi; 707*918dfc20SMatthew G. Knepley 708*918dfc20SMatthew G. Knepley PetscCall(DMGetNamedGlobalVector(user->dmPot, "phi", &phi)); 709*918dfc20SMatthew G. Knepley PetscCall(DMGetDS(user->dmPot, &ds)); 710*918dfc20SMatthew G. Knepley PetscCall(PetscDSSetObjective(ds, 0, &f0_grad_phi2)); 711*918dfc20SMatthew G. Knepley PetscCall(DMPlexComputeIntegralFEM(user->dmPot, phi, &intESq, user)); 712*918dfc20SMatthew G. Knepley PetscCall(DMRestoreNamedGlobalVector(user->dmPot, "phi", &phi)); 713*918dfc20SMatthew G. Knepley 714*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&x)); 715*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "w_q", NULL, NULL, (void **)&weight)); 716*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "E_field", NULL, NULL, (void **)&E)); 717*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "species", NULL, NULL, (void **)&species)); 718*918dfc20SMatthew G. Knepley PetscCall(PetscDrawLGAddPoint(user->drawlgE, &t, &lgEmax)); 719*918dfc20SMatthew G. Knepley if (user->efield_monitor == E_MONITOR_FULL) { 720*918dfc20SMatthew G. Knepley PetscDraw draw; 721*918dfc20SMatthew G. Knepley 722*918dfc20SMatthew G. Knepley PetscCall(PetscDrawLGDraw(user->drawlgE)); 723*918dfc20SMatthew G. Knepley PetscCall(PetscDrawLGGetDraw(user->drawlgE, &draw)); 724*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSave(draw)); 725*918dfc20SMatthew G. Knepley 726*918dfc20SMatthew G. Knepley PetscCall(DMSwarmComputeMoments(sw, "velocity", "w_q", pmoments)); 727*918dfc20SMatthew 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)); 728*918dfc20SMatthew G. Knepley PetscCall(DMViewFromOptions(sw, NULL, "-sw_efield_view")); 729*918dfc20SMatthew G. Knepley } 730*918dfc20SMatthew G. Knepley 731*918dfc20SMatthew G. Knepley // Compute decay rate and frequency 732*918dfc20SMatthew G. Knepley EmaxCtx ectx; 733*918dfc20SMatthew G. Knepley 734*918dfc20SMatthew G. Knepley ectx.s = 50; 735*918dfc20SMatthew G. Knepley PetscCall(PetscDrawLGGetData(user->drawlgE, NULL, &ectx.e, &ectx.t, &ectx.Emax)); 736*918dfc20SMatthew G. Knepley if (!rank && !(ectx.e % 100)) { 737*918dfc20SMatthew G. Knepley Tao tao; 738*918dfc20SMatthew G. Knepley Mat J; 739*918dfc20SMatthew G. Knepley Vec x, r; 740*918dfc20SMatthew G. Knepley PetscScalar *a; 741*918dfc20SMatthew G. Knepley PetscBool fitLog = PETSC_TRUE, debug = PETSC_FALSE; 742*918dfc20SMatthew G. Knepley 743*918dfc20SMatthew G. Knepley PetscCall(TaoCreate(PETSC_COMM_SELF, &tao)); 744*918dfc20SMatthew G. Knepley PetscCall(TaoSetOptionsPrefix(tao, "emax_")); 745*918dfc20SMatthew G. Knepley PetscCall(VecCreateSeq(PETSC_COMM_SELF, 4, &x)); 746*918dfc20SMatthew G. Knepley PetscCall(TaoSetSolution(tao, x)); 747*918dfc20SMatthew G. Knepley PetscCall(VecCreateSeq(PETSC_COMM_SELF, ectx.e - ectx.s, &r)); 748*918dfc20SMatthew G. Knepley if (fitLog) PetscCall(TaoSetResidualRoutine(tao, r, ComputeLogEmaxResidual, &ectx)); 749*918dfc20SMatthew G. Knepley else PetscCall(TaoSetResidualRoutine(tao, r, ComputeEmaxResidual, &ectx)); 750*918dfc20SMatthew G. Knepley PetscCall(VecDestroy(&r)); 751*918dfc20SMatthew G. Knepley PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, ectx.e - ectx.s, 4, NULL, &J)); 752*918dfc20SMatthew G. Knepley if (fitLog) PetscCall(TaoSetJacobianResidualRoutine(tao, J, J, ComputeLogEmaxJacobian, &ectx)); 753*918dfc20SMatthew G. Knepley else PetscCall(TaoSetJacobianResidualRoutine(tao, J, J, ComputeEmaxJacobian, &ectx)); 754*918dfc20SMatthew G. Knepley PetscCall(MatDestroy(&J)); 755*918dfc20SMatthew G. Knepley PetscCall(TaoSetFromOptions(tao)); 756*918dfc20SMatthew G. Knepley PetscCall(VecGetArray(x, &a)); 757*918dfc20SMatthew G. Knepley a[0] = 0.02; 758*918dfc20SMatthew G. Knepley a[1] = 0.15; 759*918dfc20SMatthew G. Knepley a[2] = 1.4; 760*918dfc20SMatthew G. Knepley a[3] = 0.45; 761*918dfc20SMatthew G. Knepley PetscCall(VecRestoreArray(x, &a)); 762*918dfc20SMatthew G. Knepley PetscCall(TaoSolve(tao)); 763*918dfc20SMatthew G. Knepley if (debug) { 764*918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, "t = [")); 765*918dfc20SMatthew G. Knepley for (PetscInt i = 0; i < ectx.e; ++i) { 766*918dfc20SMatthew G. Knepley if (i > 0) PetscCall(PetscPrintf(PETSC_COMM_SELF, ", ")); 767*918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, "%g", ectx.t[i])); 768*918dfc20SMatthew G. Knepley } 769*918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, "]\n")); 770*918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, "Emax = [")); 771*918dfc20SMatthew G. Knepley for (PetscInt i = 0; i < ectx.e; ++i) { 772*918dfc20SMatthew G. Knepley if (i > 0) PetscCall(PetscPrintf(PETSC_COMM_SELF, ", ")); 773*918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, "%g", ectx.Emax[i])); 774*918dfc20SMatthew G. Knepley } 775*918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, "]\n")); 776*918dfc20SMatthew G. Knepley } 777*918dfc20SMatthew G. Knepley PetscDraw draw; 778*918dfc20SMatthew G. Knepley PetscDrawAxis axis; 779*918dfc20SMatthew G. Knepley char title[PETSC_MAX_PATH_LEN]; 780*918dfc20SMatthew G. Knepley 781*918dfc20SMatthew G. Knepley PetscCall(VecGetArray(x, &a)); 782*918dfc20SMatthew G. Knepley user->gamma = a[1]; 783*918dfc20SMatthew G. Knepley user->omega = a[2]; 784*918dfc20SMatthew G. Knepley if (user->efield_monitor == E_MONITOR_FULL) { 785*918dfc20SMatthew 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])); 786*918dfc20SMatthew G. Knepley PetscCall(PetscDrawLGGetDraw(user->drawlgE, &draw)); 787*918dfc20SMatthew G. Knepley PetscCall(PetscSNPrintf(title, PETSC_MAX_PATH_LEN, "Max Electric Field gamma %.4g omega %.4g", a[1], a[2])); 788*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSetTitle(draw, title)); 789*918dfc20SMatthew G. Knepley PetscCall(PetscDrawLGGetAxis(user->drawlgE, &axis)); 790*918dfc20SMatthew G. Knepley PetscCall(PetscDrawAxisSetLabels(axis, title, "time", "E_max")); 791*918dfc20SMatthew G. Knepley } 792*918dfc20SMatthew G. Knepley PetscCall(VecRestoreArray(x, &a)); 793*918dfc20SMatthew G. Knepley PetscCall(VecDestroy(&x)); 794*918dfc20SMatthew G. Knepley PetscCall(TaoDestroy(&tao)); 795*918dfc20SMatthew G. Knepley } 796*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 797*918dfc20SMatthew G. Knepley } 798*918dfc20SMatthew G. Knepley 799*918dfc20SMatthew G. Knepley static PetscErrorCode MonitorMoments(TS ts, PetscInt step, PetscReal t, Vec U, void *ctx) 800*918dfc20SMatthew G. Knepley { 801*918dfc20SMatthew G. Knepley AppCtx *user = (AppCtx *)ctx; 802*918dfc20SMatthew G. Knepley DM sw; 803*918dfc20SMatthew G. Knepley PetscReal pmoments[4], fmoments[4]; /* \int f, \int v f, \int v^2 f */ 804*918dfc20SMatthew G. Knepley 805*918dfc20SMatthew G. Knepley PetscFunctionBeginUser; 806*918dfc20SMatthew G. Knepley if (step < 0) PetscFunctionReturn(PETSC_SUCCESS); 807*918dfc20SMatthew G. Knepley PetscCall(TSGetDM(ts, &sw)); 808*918dfc20SMatthew G. Knepley 809*918dfc20SMatthew G. Knepley PetscCall(DMSwarmComputeMoments(sw, "velocity", "w_q", pmoments)); 810*918dfc20SMatthew G. Knepley PetscCall(computeVelocityFEMMoments(sw, fmoments, user)); 811*918dfc20SMatthew G. Knepley 812*918dfc20SMatthew 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])); 813*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 814*918dfc20SMatthew G. Knepley } 815*918dfc20SMatthew G. Knepley 816*918dfc20SMatthew G. Knepley static void f0_pres(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[]) 817*918dfc20SMatthew G. Knepley { 818*918dfc20SMatthew G. Knepley const PetscReal v = a[0]; 819*918dfc20SMatthew G. Knepley const PetscReal n = u[0]; 820*918dfc20SMatthew G. Knepley const PetscReal p = u[1]; 821*918dfc20SMatthew G. Knepley 822*918dfc20SMatthew G. Knepley f1[0] = PetscSqr(v - p / n); 823*918dfc20SMatthew G. Knepley } 824*918dfc20SMatthew G. Knepley 825*918dfc20SMatthew G. Knepley static PetscErrorCode zero(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx) 826*918dfc20SMatthew G. Knepley { 827*918dfc20SMatthew G. Knepley u[0] = 0.0; 828*918dfc20SMatthew G. Knepley return PETSC_SUCCESS; 829*918dfc20SMatthew G. Knepley } 830*918dfc20SMatthew G. Knepley 831*918dfc20SMatthew G. Knepley /* 832*918dfc20SMatthew G. Knepley M_p w_p 833*918dfc20SMatthew G. Knepley - Make M_p with "moments" 834*918dfc20SMatthew G. Knepley - Get w_p from Swarm 835*918dfc20SMatthew G. Knepley M_p v_p w_p 836*918dfc20SMatthew G. Knepley - Get v_p from Swarm 837*918dfc20SMatthew G. Knepley - pointwise multiply v_p and w_p 838*918dfc20SMatthew 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 839*918dfc20SMatthew G. Knepley - ProjectField(sw, {n, p} U, {v_p} A, tmp_p) 840*918dfc20SMatthew G. Knepley - pointwise multiply tmp_p and w_p 841*918dfc20SMatthew G. Knepley 842*918dfc20SMatthew G. Knepley */ 843*918dfc20SMatthew G. Knepley static PetscErrorCode ComputeMomentFields(TS ts) 844*918dfc20SMatthew G. Knepley { 845*918dfc20SMatthew G. Knepley AppCtx *user; 846*918dfc20SMatthew G. Knepley DM sw; 847*918dfc20SMatthew G. Knepley KSP ksp; 848*918dfc20SMatthew G. Knepley Mat M_p; 849*918dfc20SMatthew G. Knepley Vec f, v, vf, vuf; 850*918dfc20SMatthew G. Knepley Vec m, n, nRhs, p, pRhs, e, eRhs; 851*918dfc20SMatthew G. Knepley PetscReal dt; 852*918dfc20SMatthew G. Knepley PetscInt Nts; 853*918dfc20SMatthew G. Knepley 854*918dfc20SMatthew G. Knepley PetscFunctionBegin; 855*918dfc20SMatthew G. Knepley PetscCall(TSGetStepNumber(ts, &Nts)); 856*918dfc20SMatthew G. Knepley PetscCall(TSGetTimeStep(ts, &dt)); 857*918dfc20SMatthew G. Knepley PetscCall(TSGetDM(ts, &sw)); 858*918dfc20SMatthew G. Knepley PetscCall(DMGetApplicationContext(sw, (void *)&user)); 859*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSetCellDMActive(sw, "moment fields")); 860*918dfc20SMatthew G. Knepley PetscCall(DMSwarmMigrate(sw, PETSC_FALSE)); 861*918dfc20SMatthew G. Knepley // TODO Will have to create different M_p in higher dimensions for velocity 862*918dfc20SMatthew G. Knepley PetscCall(DMCreateMassMatrix(sw, user->dmN, &M_p)); 863*918dfc20SMatthew G. Knepley PetscCall(DMSwarmCreateGlobalVectorFromField(sw, "w_q", &f)); 864*918dfc20SMatthew G. Knepley PetscCall(DMSwarmCreateGlobalVectorFromField(sw, "velocity", &v)); 865*918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)f, "particle weight")); 866*918dfc20SMatthew G. Knepley 867*918dfc20SMatthew G. Knepley PetscCall(DMGetGlobalVector(user->dmN, &nRhs)); 868*918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)nRhs, "Weak number density")); 869*918dfc20SMatthew G. Knepley PetscCall(DMGetNamedGlobalVector(user->dmN, "n", &n)); 870*918dfc20SMatthew G. Knepley PetscCall(DMGetGlobalVector(user->dmP, &pRhs)); 871*918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)pRhs, "Weak momentum density")); 872*918dfc20SMatthew G. Knepley PetscCall(DMGetNamedGlobalVector(user->dmP, "p", &p)); 873*918dfc20SMatthew G. Knepley PetscCall(DMGetGlobalVector(user->dmE, &eRhs)); 874*918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)eRhs, "Weak energy density (pressure)")); 875*918dfc20SMatthew G. Knepley PetscCall(DMGetNamedGlobalVector(user->dmE, "e", &e)); 876*918dfc20SMatthew G. Knepley 877*918dfc20SMatthew G. Knepley PetscCall(MatViewFromOptions(M_p, NULL, "-mp_view")); 878*918dfc20SMatthew G. Knepley PetscCall(MatViewFromOptions(user->MN, NULL, "-mn_view")); 879*918dfc20SMatthew G. Knepley PetscCall(MatViewFromOptions(user->MP, NULL, "-mp_view")); 880*918dfc20SMatthew G. Knepley PetscCall(MatViewFromOptions(user->ME, NULL, "-me_view")); 881*918dfc20SMatthew G. Knepley PetscCall(VecViewFromOptions(f, NULL, "-weights_view")); 882*918dfc20SMatthew G. Knepley 883*918dfc20SMatthew G. Knepley PetscCall(VecDuplicate(f, &vf)); 884*918dfc20SMatthew G. Knepley PetscCall(VecDuplicate(f, &vuf)); 885*918dfc20SMatthew G. Knepley 886*918dfc20SMatthew G. Knepley PetscCall(MatMultTranspose(M_p, f, nRhs)); 887*918dfc20SMatthew G. Knepley 888*918dfc20SMatthew G. Knepley PetscCall(VecPointwiseMult(vf, f, v)); 889*918dfc20SMatthew G. Knepley PetscCall(MatMultTranspose(M_p, vf, pRhs)); 890*918dfc20SMatthew G. Knepley PetscCall(VecDestroy(&vf)); 891*918dfc20SMatthew G. Knepley PetscCall(DMSwarmDestroyGlobalVectorFromField(sw, "velocity", &v)); 892*918dfc20SMatthew G. Knepley PetscCall(DMSwarmDestroyGlobalVectorFromField(sw, "w_q", &f)); 893*918dfc20SMatthew G. Knepley 894*918dfc20SMatthew G. Knepley PetscPointFn *funcs[1] = {f0_pres}; 895*918dfc20SMatthew G. Knepley 896*918dfc20SMatthew G. Knepley PetscCall(DMGetGlobalVector(user->dmMom, &m)); 897*918dfc20SMatthew G. Knepley PetscCall(VecISCopy(m, user->isN, SCATTER_FORWARD, n)); 898*918dfc20SMatthew G. Knepley PetscCall(VecISCopy(m, user->isP, SCATTER_FORWARD, p)); 899*918dfc20SMatthew G. Knepley PetscCall(DMProjectField(sw, 0., m, funcs, INSERT_VALUES, vuf)); 900*918dfc20SMatthew G. Knepley PetscCall(DMRestoreGlobalVector(user->dmMom, &m)); 901*918dfc20SMatthew G. Knepley PetscCall(DMSwarmCreateGlobalVectorFromField(sw, "w_q", &f)); 902*918dfc20SMatthew G. Knepley PetscCall(VecPointwiseMult(vuf, f, vuf)); 903*918dfc20SMatthew G. Knepley PetscCall(DMSwarmDestroyGlobalVectorFromField(sw, "w_q", &f)); 904*918dfc20SMatthew G. Knepley PetscCall(MatMultTranspose(M_p, vuf, eRhs)); 905*918dfc20SMatthew G. Knepley PetscCall(VecDestroy(&vuf)); 906*918dfc20SMatthew G. Knepley 907*918dfc20SMatthew G. Knepley PetscCall(MatDestroy(&M_p)); 908*918dfc20SMatthew G. Knepley 909*918dfc20SMatthew G. Knepley PetscCall(KSPCreate(PetscObjectComm((PetscObject)sw), &ksp)); 910*918dfc20SMatthew G. Knepley PetscCall(KSPSetOptionsPrefix(ksp, "mom_proj_")); 911*918dfc20SMatthew G. Knepley PetscCall(KSPSetOperators(ksp, user->MN, user->MN)); 912*918dfc20SMatthew G. Knepley PetscCall(KSPSetFromOptions(ksp)); 913*918dfc20SMatthew G. Knepley PetscCall(KSPSolve(ksp, nRhs, n)); 914*918dfc20SMatthew G. Knepley PetscCall(KSPSetOperators(ksp, user->MP, user->MP)); 915*918dfc20SMatthew G. Knepley PetscCall(KSPSetFromOptions(ksp)); 916*918dfc20SMatthew G. Knepley PetscCall(KSPSolve(ksp, pRhs, p)); 917*918dfc20SMatthew G. Knepley PetscCall(KSPSetOperators(ksp, user->ME, user->ME)); 918*918dfc20SMatthew G. Knepley PetscCall(KSPSetFromOptions(ksp)); 919*918dfc20SMatthew G. Knepley PetscCall(KSPSolve(ksp, eRhs, e)); 920*918dfc20SMatthew G. Knepley PetscCall(KSPDestroy(&ksp)); 921*918dfc20SMatthew G. Knepley 922*918dfc20SMatthew G. Knepley // Check moment residual 923*918dfc20SMatthew G. Knepley // TODO Fix global2local here 924*918dfc20SMatthew G. Knepley PetscSimplePointFn *exacts[3] = {zero, zero, zero}; 925*918dfc20SMatthew G. Knepley Vec mold, m_t, locF, phi; 926*918dfc20SMatthew G. Knepley PetscReal res[3]; 927*918dfc20SMatthew G. Knepley 928*918dfc20SMatthew G. Knepley PetscCall(DMGetNamedGlobalVector(user->dmMom, "mold", &mold)); 929*918dfc20SMatthew G. Knepley if (!Nts) PetscCall(VecSet(mold, 0.)); 930*918dfc20SMatthew G. Knepley 931*918dfc20SMatthew G. Knepley PetscCall(DMGetGlobalVector(user->dmMom, &m)); 932*918dfc20SMatthew G. Knepley PetscCall(DMGetGlobalVector(user->dmMom, &m_t)); 933*918dfc20SMatthew G. Knepley PetscCall(DMGetGlobalVector(user->dmMom, &locF)); 934*918dfc20SMatthew G. Knepley PetscCall(VecISCopy(m, user->isN, SCATTER_FORWARD, n)); 935*918dfc20SMatthew G. Knepley PetscCall(VecISCopy(m, user->isP, SCATTER_FORWARD, p)); 936*918dfc20SMatthew G. Knepley PetscCall(VecISCopy(m, user->isE, SCATTER_FORWARD, e)); 937*918dfc20SMatthew G. Knepley PetscCall(VecAXPBYPCZ(m_t, -1.0, 1.0, 0.0, mold, m)); 938*918dfc20SMatthew G. Knepley PetscCall(DMGetNamedGlobalVector(user->dmPot, "phi", &phi)); 939*918dfc20SMatthew G. Knepley PetscCall(DMSetAuxiliaryVec(user->dmMom, NULL, 0, 0, phi)); 940*918dfc20SMatthew G. Knepley PetscCall(DMPlexTSComputeIFunctionFEM(user->dmMom, PETSC_MIN_REAL, m, m_t, locF, user)); 941*918dfc20SMatthew G. Knepley PetscCall(DMSetAuxiliaryVec(user->dmMom, NULL, 0, 0, NULL)); 942*918dfc20SMatthew G. Knepley PetscCall(DMRestoreNamedGlobalVector(user->dmPot, "phi", &phi)); 943*918dfc20SMatthew G. Knepley PetscCall(VecViewFromOptions(locF, NULL, "-moment_residual_view")); 944*918dfc20SMatthew G. Knepley PetscCall(VecNorm(locF, NORM_2, &res[0])); 945*918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(PetscObjectComm((PetscObject)sw), "Moment Residual: %g\n", (double)res[0])); 946*918dfc20SMatthew G. Knepley PetscCall(DMComputeL2FieldDiff(user->dmMom, 0., exacts, NULL, locF, res)); 947*918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(PetscObjectComm((PetscObject)sw), "Moment Residuals: %g %g %g\n", (double)res[0], (double)res[1], (double)res[2])); 948*918dfc20SMatthew G. Knepley PetscCall(VecCopy(m, mold)); 949*918dfc20SMatthew G. Knepley PetscCall(DMRestoreGlobalVector(user->dmMom, &locF)); 950*918dfc20SMatthew G. Knepley PetscCall(DMRestoreGlobalVector(user->dmMom, &m)); 951*918dfc20SMatthew G. Knepley PetscCall(DMRestoreNamedGlobalVector(user->dmMom, "mold", &mold)); 952*918dfc20SMatthew G. Knepley 953*918dfc20SMatthew G. Knepley PetscCall(DMRestoreGlobalVector(user->dmN, &nRhs)); 954*918dfc20SMatthew G. Knepley PetscCall(DMRestoreGlobalVector(user->dmP, &pRhs)); 955*918dfc20SMatthew G. Knepley PetscCall(DMRestoreGlobalVector(user->dmE, &eRhs)); 956*918dfc20SMatthew G. Knepley PetscCall(DMRestoreNamedGlobalVector(user->dmN, "n", &n)); 957*918dfc20SMatthew G. Knepley PetscCall(DMRestoreNamedGlobalVector(user->dmP, "p", &p)); 958*918dfc20SMatthew G. Knepley PetscCall(DMRestoreNamedGlobalVector(user->dmE, "e", &e)); 959*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSetCellDMActive(sw, "space")); 960*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 961*918dfc20SMatthew G. Knepley } 962*918dfc20SMatthew G. Knepley 963*918dfc20SMatthew G. Knepley static PetscErrorCode MonitorMomentFields(TS ts, PetscInt step, PetscReal t, Vec U, void *ctx) 964*918dfc20SMatthew G. Knepley { 965*918dfc20SMatthew G. Knepley AppCtx *user = (AppCtx *)ctx; 966*918dfc20SMatthew G. Knepley Vec n, p, e; 967*918dfc20SMatthew G. Knepley 968*918dfc20SMatthew G. Knepley PetscFunctionBeginUser; 969*918dfc20SMatthew G. Knepley if (step < 0) PetscFunctionReturn(PETSC_SUCCESS); 970*918dfc20SMatthew G. Knepley PetscCall(ComputeMomentFields(ts)); 971*918dfc20SMatthew G. Knepley 972*918dfc20SMatthew G. Knepley PetscCall(DMGetNamedGlobalVector(user->dmN, "n", &n)); 973*918dfc20SMatthew G. Knepley PetscCall(VecView(n, user->viewerN)); 974*918dfc20SMatthew G. Knepley PetscCall(DMRestoreNamedGlobalVector(user->dmN, "n", &n)); 975*918dfc20SMatthew G. Knepley 976*918dfc20SMatthew G. Knepley PetscCall(DMGetNamedGlobalVector(user->dmP, "p", &p)); 977*918dfc20SMatthew G. Knepley PetscCall(VecView(p, user->viewerP)); 978*918dfc20SMatthew G. Knepley PetscCall(DMRestoreNamedGlobalVector(user->dmP, "p", &p)); 979*918dfc20SMatthew G. Knepley 980*918dfc20SMatthew G. Knepley PetscCall(DMGetNamedGlobalVector(user->dmE, "e", &e)); 981*918dfc20SMatthew G. Knepley PetscCall(VecView(e, user->viewerE)); 982*918dfc20SMatthew G. Knepley PetscCall(DMRestoreNamedGlobalVector(user->dmE, "e", &e)); 983*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 984*918dfc20SMatthew G. Knepley } 985*918dfc20SMatthew G. Knepley 986*918dfc20SMatthew G. Knepley PetscErrorCode MonitorInitialConditions(TS ts, PetscInt step, PetscReal t, Vec U, void *ctx) 987*918dfc20SMatthew G. Knepley { 988*918dfc20SMatthew G. Knepley AppCtx *user = (AppCtx *)ctx; 989*918dfc20SMatthew G. Knepley DM sw; 990*918dfc20SMatthew G. Knepley PetscDraw drawic_x, drawic_v; 991*918dfc20SMatthew G. Knepley PetscReal *weight, *pos, *vel; 992*918dfc20SMatthew G. Knepley PetscInt dim, Np; 993*918dfc20SMatthew G. Knepley 994*918dfc20SMatthew G. Knepley PetscFunctionBegin; 995*918dfc20SMatthew G. Knepley if (step < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates interpolated solution */ 996*918dfc20SMatthew G. Knepley if (step == 0) { 997*918dfc20SMatthew G. Knepley PetscCall(TSGetDM(ts, &sw)); 998*918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim)); 999*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(sw, &Np)); 1000*918dfc20SMatthew G. Knepley 1001*918dfc20SMatthew G. Knepley PetscCall(PetscDrawHGReset(user->drawhgic_x)); 1002*918dfc20SMatthew G. Knepley PetscCall(PetscDrawHGGetDraw(user->drawhgic_x, &drawic_x)); 1003*918dfc20SMatthew G. Knepley PetscCall(PetscDrawClear(drawic_x)); 1004*918dfc20SMatthew G. Knepley PetscCall(PetscDrawFlush(drawic_x)); 1005*918dfc20SMatthew G. Knepley 1006*918dfc20SMatthew G. Knepley PetscCall(PetscDrawHGReset(user->drawhgic_v)); 1007*918dfc20SMatthew G. Knepley PetscCall(PetscDrawHGGetDraw(user->drawhgic_v, &drawic_v)); 1008*918dfc20SMatthew G. Knepley PetscCall(PetscDrawClear(drawic_v)); 1009*918dfc20SMatthew G. Knepley PetscCall(PetscDrawFlush(drawic_v)); 1010*918dfc20SMatthew G. Knepley 1011*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&pos)); 1012*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "velocity", NULL, NULL, (void **)&vel)); 1013*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "w_q", NULL, NULL, (void **)&weight)); 1014*918dfc20SMatthew G. Knepley for (PetscInt p = 0; p < Np; ++p) { 1015*918dfc20SMatthew G. Knepley PetscCall(PetscDrawHGAddWeightedValue(user->drawhgic_x, pos[p * dim], weight[p])); 1016*918dfc20SMatthew G. Knepley PetscCall(PetscDrawHGAddWeightedValue(user->drawhgic_v, vel[p * dim], weight[p])); 1017*918dfc20SMatthew G. Knepley } 1018*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&pos)); 1019*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "velocity", NULL, NULL, (void **)&vel)); 1020*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "w_q", NULL, NULL, (void **)&weight)); 1021*918dfc20SMatthew G. Knepley 1022*918dfc20SMatthew G. Knepley PetscCall(PetscDrawHGDraw(user->drawhgic_x)); 1023*918dfc20SMatthew G. Knepley PetscCall(PetscDrawHGSave(user->drawhgic_x)); 1024*918dfc20SMatthew G. Knepley PetscCall(PetscDrawHGDraw(user->drawhgic_v)); 1025*918dfc20SMatthew G. Knepley PetscCall(PetscDrawHGSave(user->drawhgic_v)); 1026*918dfc20SMatthew G. Knepley } 1027*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1028*918dfc20SMatthew G. Knepley } 1029*918dfc20SMatthew G. Knepley 1030*918dfc20SMatthew G. Knepley // Right now, make the complete velocity histogram 1031*918dfc20SMatthew G. Knepley PetscErrorCode MonitorVelocity(TS ts, PetscInt step, PetscReal t, Vec U, void *ctx) 1032*918dfc20SMatthew G. Knepley { 1033*918dfc20SMatthew G. Knepley AppCtx *user = (AppCtx *)ctx; 1034*918dfc20SMatthew G. Knepley DM sw, dm; 1035*918dfc20SMatthew G. Knepley Vec ks; 1036*918dfc20SMatthew G. Knepley PetscProbFn *cdf; 1037*918dfc20SMatthew G. Knepley PetscDraw drawcell_v; 1038*918dfc20SMatthew G. Knepley PetscScalar *ksa; 1039*918dfc20SMatthew G. Knepley PetscReal *weight, *vel; 1040*918dfc20SMatthew G. Knepley PetscInt *pidx; 1041*918dfc20SMatthew G. Knepley PetscInt dim, Npc, cStart, cEnd, cell = user->velocity_monitor; 1042*918dfc20SMatthew G. Knepley 1043*918dfc20SMatthew G. Knepley PetscFunctionBegin; 1044*918dfc20SMatthew G. Knepley PetscCall(TSGetDM(ts, &sw)); 1045*918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim)); 1046*918dfc20SMatthew G. Knepley 1047*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetCellDM(sw, &dm)); 1048*918dfc20SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1049*918dfc20SMatthew G. Knepley PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &ks)); 1050*918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)ks, "KS Statistic by Cell")); 1051*918dfc20SMatthew G. Knepley PetscCall(VecSetSizes(ks, cEnd - cStart, PETSC_DETERMINE)); 1052*918dfc20SMatthew G. Knepley PetscCall(VecSetFromOptions(ks)); 1053*918dfc20SMatthew G. Knepley switch (dim) { 1054*918dfc20SMatthew G. Knepley case 1: 1055*918dfc20SMatthew G. Knepley //cdf = PetscCDFMaxwellBoltzmann1D; 1056*918dfc20SMatthew G. Knepley cdf = PetscCDFGaussian1D; 1057*918dfc20SMatthew G. Knepley break; 1058*918dfc20SMatthew G. Knepley case 2: 1059*918dfc20SMatthew G. Knepley cdf = PetscCDFMaxwellBoltzmann2D; 1060*918dfc20SMatthew G. Knepley break; 1061*918dfc20SMatthew G. Knepley case 3: 1062*918dfc20SMatthew G. Knepley cdf = PetscCDFMaxwellBoltzmann3D; 1063*918dfc20SMatthew G. Knepley break; 1064*918dfc20SMatthew G. Knepley default: 1065*918dfc20SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Dimension %" PetscInt_FMT " not supported", dim); 1066*918dfc20SMatthew G. Knepley } 1067*918dfc20SMatthew G. Knepley 1068*918dfc20SMatthew G. Knepley PetscCall(PetscDrawHGReset(user->drawhgcell_v)); 1069*918dfc20SMatthew G. Knepley PetscCall(PetscDrawHGGetDraw(user->drawhgcell_v, &drawcell_v)); 1070*918dfc20SMatthew G. Knepley PetscCall(PetscDrawClear(drawcell_v)); 1071*918dfc20SMatthew G. Knepley PetscCall(PetscDrawFlush(drawcell_v)); 1072*918dfc20SMatthew G. Knepley 1073*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "velocity", NULL, NULL, (void **)&vel)); 1074*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "w_q", NULL, NULL, (void **)&weight)); 1075*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortGetAccess(sw)); 1076*918dfc20SMatthew G. Knepley PetscCall(VecGetArrayWrite(ks, &ksa)); 1077*918dfc20SMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) { 1078*918dfc20SMatthew G. Knepley Vec cellv, cellw; 1079*918dfc20SMatthew G. Knepley PetscScalar *cella, *cellaw; 1080*918dfc20SMatthew G. Knepley PetscReal totWgt = 0.; 1081*918dfc20SMatthew G. Knepley 1082*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortGetPointsPerCell(sw, c, &Npc, &pidx)); 1083*918dfc20SMatthew G. Knepley PetscCall(VecCreate(PETSC_COMM_SELF, &cellv)); 1084*918dfc20SMatthew G. Knepley PetscCall(VecSetBlockSize(cellv, dim)); 1085*918dfc20SMatthew G. Knepley PetscCall(VecSetSizes(cellv, Npc * dim, Npc)); 1086*918dfc20SMatthew G. Knepley PetscCall(VecSetFromOptions(cellv)); 1087*918dfc20SMatthew G. Knepley PetscCall(VecCreate(PETSC_COMM_SELF, &cellw)); 1088*918dfc20SMatthew G. Knepley PetscCall(VecSetSizes(cellw, Npc, Npc)); 1089*918dfc20SMatthew G. Knepley PetscCall(VecSetFromOptions(cellw)); 1090*918dfc20SMatthew G. Knepley PetscCall(VecGetArrayWrite(cellv, &cella)); 1091*918dfc20SMatthew G. Knepley PetscCall(VecGetArrayWrite(cellw, &cellaw)); 1092*918dfc20SMatthew G. Knepley for (PetscInt q = 0; q < Npc; ++q) { 1093*918dfc20SMatthew G. Knepley const PetscInt p = pidx[q]; 1094*918dfc20SMatthew G. Knepley if (c == cell) PetscCall(PetscDrawHGAddWeightedValue(user->drawhgcell_v, vel[p * dim], weight[p])); 1095*918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) cella[q * dim + d] = vel[p * dim + d]; 1096*918dfc20SMatthew G. Knepley cellaw[q] = weight[p]; 1097*918dfc20SMatthew G. Knepley totWgt += weight[p]; 1098*918dfc20SMatthew G. Knepley } 1099*918dfc20SMatthew G. Knepley PetscCall(VecRestoreArrayWrite(cellv, &cella)); 1100*918dfc20SMatthew G. Knepley PetscCall(VecRestoreArrayWrite(cellw, &cellaw)); 1101*918dfc20SMatthew G. Knepley PetscCall(VecScale(cellw, 1. / totWgt)); 1102*918dfc20SMatthew G. Knepley PetscCall(PetscProbComputeKSStatisticWeighted(cellv, cellw, cdf, &ksa[c - cStart])); 1103*918dfc20SMatthew G. Knepley PetscCall(VecDestroy(&cellv)); 1104*918dfc20SMatthew G. Knepley PetscCall(VecDestroy(&cellw)); 1105*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(sw, c, &Npc, &pidx)); 1106*918dfc20SMatthew G. Knepley } 1107*918dfc20SMatthew G. Knepley PetscCall(VecRestoreArrayWrite(ks, &ksa)); 1108*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "velocity", NULL, NULL, (void **)&vel)); 1109*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "w_q", NULL, NULL, (void **)&weight)); 1110*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortRestoreAccess(sw)); 1111*918dfc20SMatthew G. Knepley 1112*918dfc20SMatthew G. Knepley PetscReal minalpha, maxalpha; 1113*918dfc20SMatthew G. Knepley PetscInt mincell, maxcell; 1114*918dfc20SMatthew G. Knepley 1115*918dfc20SMatthew G. Knepley PetscCall(VecFilter(ks, PETSC_SMALL)); 1116*918dfc20SMatthew G. Knepley PetscCall(VecMin(ks, &mincell, &minalpha)); 1117*918dfc20SMatthew G. Knepley PetscCall(VecMax(ks, &maxcell, &maxalpha)); 1118*918dfc20SMatthew 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)); 1119*918dfc20SMatthew G. Knepley PetscCall(VecViewFromOptions(ks, NULL, "-ks_view")); 1120*918dfc20SMatthew G. Knepley PetscCall(VecDestroy(&ks)); 1121*918dfc20SMatthew G. Knepley 1122*918dfc20SMatthew G. Knepley PetscCall(PetscDrawHGDraw(user->drawhgcell_v)); 1123*918dfc20SMatthew G. Knepley PetscCall(PetscDrawHGSave(user->drawhgcell_v)); 1124*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1125*918dfc20SMatthew G. Knepley } 1126*918dfc20SMatthew G. Knepley 1127*918dfc20SMatthew G. Knepley static PetscErrorCode MonitorPositions_2D(TS ts, PetscInt step, PetscReal t, Vec U, void *ctx) 1128*918dfc20SMatthew G. Knepley { 1129*918dfc20SMatthew G. Knepley AppCtx *user = (AppCtx *)ctx; 1130*918dfc20SMatthew G. Knepley DM dm, sw; 1131*918dfc20SMatthew G. Knepley PetscScalar *x, *v, *weight; 1132*918dfc20SMatthew G. Knepley PetscReal lower[3], upper[3], speed; 1133*918dfc20SMatthew G. Knepley const PetscInt *s; 1134*918dfc20SMatthew G. Knepley PetscInt dim, cStart, cEnd, c; 1135*918dfc20SMatthew G. Knepley 1136*918dfc20SMatthew G. Knepley PetscFunctionBeginUser; 1137*918dfc20SMatthew G. Knepley if (step > 0 && step % user->ostep == 0) { 1138*918dfc20SMatthew G. Knepley PetscCall(TSGetDM(ts, &sw)); 1139*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetCellDM(sw, &dm)); 1140*918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(dm, &dim)); 1141*918dfc20SMatthew G. Knepley PetscCall(DMGetBoundingBox(dm, lower, upper)); 1142*918dfc20SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1143*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&x)); 1144*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "velocity", NULL, NULL, (void **)&v)); 1145*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "w_q", NULL, NULL, (void **)&weight)); 1146*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "species", NULL, NULL, (void **)&s)); 1147*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortGetAccess(sw)); 1148*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSPReset(user->drawspX)); 1149*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSPSetLimits(user->drawspX, lower[0], upper[0], lower[1], upper[1])); 1150*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSPSetLimits(user->drawspX, lower[0], upper[0], -12, 12)); 1151*918dfc20SMatthew G. Knepley for (c = 0; c < cEnd - cStart; ++c) { 1152*918dfc20SMatthew G. Knepley PetscInt *pidx, Npc, q; 1153*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortGetPointsPerCell(sw, c, &Npc, &pidx)); 1154*918dfc20SMatthew G. Knepley for (q = 0; q < Npc; ++q) { 1155*918dfc20SMatthew G. Knepley const PetscInt p = pidx[q]; 1156*918dfc20SMatthew G. Knepley if (s[p] == 0) { 1157*918dfc20SMatthew G. Knepley speed = 0.; 1158*918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) speed += PetscSqr(v[p * dim + d]); 1159*918dfc20SMatthew G. Knepley speed = PetscSqrtReal(speed); 1160*918dfc20SMatthew G. Knepley if (dim == 1) { 1161*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSPAddPointColorized(user->drawspX, &x[p * dim], &v[p * dim], &speed)); 1162*918dfc20SMatthew G. Knepley } else { 1163*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSPAddPointColorized(user->drawspX, &x[p * dim], &x[p * dim + 1], &speed)); 1164*918dfc20SMatthew G. Knepley } 1165*918dfc20SMatthew G. Knepley } else if (s[p] == 1) { 1166*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSPAddPoint(user->drawspX, &x[p * dim], &v[p * dim])); 1167*918dfc20SMatthew G. Knepley } 1168*918dfc20SMatthew G. Knepley } 1169*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(sw, c, &Npc, &pidx)); 1170*918dfc20SMatthew G. Knepley } 1171*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSPDraw(user->drawspX, PETSC_TRUE)); 1172*918dfc20SMatthew G. Knepley PetscDraw draw; 1173*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSPGetDraw(user->drawspX, &draw)); 1174*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSave(draw)); 1175*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortRestoreAccess(sw)); 1176*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&x)); 1177*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "w_q", NULL, NULL, (void **)&weight)); 1178*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "velocity", NULL, NULL, (void **)&v)); 1179*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "species", NULL, NULL, (void **)&s)); 1180*918dfc20SMatthew G. Knepley } 1181*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1182*918dfc20SMatthew G. Knepley } 1183*918dfc20SMatthew G. Knepley 1184*918dfc20SMatthew G. Knepley static PetscErrorCode MonitorPoisson(TS ts, PetscInt step, PetscReal t, Vec U, void *ctx) 1185*918dfc20SMatthew G. Knepley { 1186*918dfc20SMatthew G. Knepley AppCtx *user = (AppCtx *)ctx; 1187*918dfc20SMatthew G. Knepley DM dm, sw; 1188*918dfc20SMatthew G. Knepley 1189*918dfc20SMatthew G. Knepley PetscFunctionBeginUser; 1190*918dfc20SMatthew G. Knepley if (step > 0 && step % user->ostep == 0) { 1191*918dfc20SMatthew G. Knepley PetscCall(TSGetDM(ts, &sw)); 1192*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetCellDM(sw, &dm)); 1193*918dfc20SMatthew G. Knepley 1194*918dfc20SMatthew G. Knepley if (user->validE) { 1195*918dfc20SMatthew G. Knepley PetscScalar *x, *E, *weight; 1196*918dfc20SMatthew G. Knepley PetscReal lower[3], upper[3], xval; 1197*918dfc20SMatthew G. Knepley PetscDraw draw; 1198*918dfc20SMatthew G. Knepley PetscInt dim, cStart, cEnd; 1199*918dfc20SMatthew G. Knepley 1200*918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(dm, &dim)); 1201*918dfc20SMatthew G. Knepley PetscCall(DMGetBoundingBox(dm, lower, upper)); 1202*918dfc20SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1203*918dfc20SMatthew G. Knepley 1204*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSPReset(user->drawspE)); 1205*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&x)); 1206*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "E_field", NULL, NULL, (void **)&E)); 1207*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "w_q", NULL, NULL, (void **)&weight)); 1208*918dfc20SMatthew G. Knepley 1209*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortGetAccess(sw)); 1210*918dfc20SMatthew G. Knepley for (PetscInt c = 0; c < cEnd - cStart; ++c) { 1211*918dfc20SMatthew G. Knepley PetscReal Eavg = 0.0; 1212*918dfc20SMatthew G. Knepley PetscInt *pidx, Npc; 1213*918dfc20SMatthew G. Knepley 1214*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortGetPointsPerCell(sw, c, &Npc, &pidx)); 1215*918dfc20SMatthew G. Knepley for (PetscInt q = 0; q < Npc; ++q) { 1216*918dfc20SMatthew G. Knepley const PetscInt p = pidx[q]; 1217*918dfc20SMatthew G. Knepley Eavg += E[p * dim]; 1218*918dfc20SMatthew G. Knepley } 1219*918dfc20SMatthew G. Knepley Eavg /= Npc; 1220*918dfc20SMatthew G. Knepley xval = (c + 0.5) * ((upper[0] - lower[0]) / (cEnd - cStart)); 1221*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSPAddPoint(user->drawspE, &xval, &Eavg)); 1222*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(sw, c, &Npc, &pidx)); 1223*918dfc20SMatthew G. Knepley } 1224*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSPDraw(user->drawspE, PETSC_TRUE)); 1225*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSPGetDraw(user->drawspE, &draw)); 1226*918dfc20SMatthew G. Knepley PetscCall(PetscDrawSave(draw)); 1227*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortRestoreAccess(sw)); 1228*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&x)); 1229*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "w_q", NULL, NULL, (void **)&weight)); 1230*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "E_field", NULL, NULL, (void **)&E)); 1231*918dfc20SMatthew G. Knepley } 1232*918dfc20SMatthew G. Knepley 1233*918dfc20SMatthew G. Knepley Vec rho, rhohat, phi; 1234*918dfc20SMatthew G. Knepley 1235*918dfc20SMatthew G. Knepley PetscCall(DMGetNamedGlobalVector(user->dmPot, "rho", &rho)); 1236*918dfc20SMatthew G. Knepley PetscCall(DMGetNamedGlobalVector(user->dmPot, "rhohat", &rhohat)); 1237*918dfc20SMatthew G. Knepley PetscCall(VecView(rho, user->viewerRho)); 1238*918dfc20SMatthew G. Knepley PetscCall(VecISCopy(user->fftX, user->fftReal, SCATTER_FORWARD, rho)); 1239*918dfc20SMatthew G. Knepley PetscCall(MatMult(user->fftPot, user->fftX, user->fftY)); 1240*918dfc20SMatthew G. Knepley PetscCall(VecFilter(user->fftY, PETSC_SMALL)); 1241*918dfc20SMatthew G. Knepley PetscCall(VecViewFromOptions(user->fftX, NULL, "-real_view")); 1242*918dfc20SMatthew G. Knepley PetscCall(VecViewFromOptions(user->fftY, NULL, "-fft_view")); 1243*918dfc20SMatthew G. Knepley PetscCall(VecISCopy(user->fftY, user->fftReal, SCATTER_REVERSE, rhohat)); 1244*918dfc20SMatthew G. Knepley PetscCall(VecSetValue(rhohat, 0, 0., INSERT_VALUES)); // Remove large DC component 1245*918dfc20SMatthew G. Knepley PetscCall(VecView(rhohat, user->viewerRhoHat)); 1246*918dfc20SMatthew G. Knepley PetscCall(DMRestoreNamedGlobalVector(user->dmPot, "rho", &rho)); 1247*918dfc20SMatthew G. Knepley PetscCall(DMRestoreNamedGlobalVector(user->dmPot, "rhohat", &rhohat)); 1248*918dfc20SMatthew G. Knepley 1249*918dfc20SMatthew G. Knepley PetscCall(DMGetNamedGlobalVector(user->dmPot, "phi", &phi)); 1250*918dfc20SMatthew G. Knepley PetscCall(VecView(phi, user->viewerPhi)); 1251*918dfc20SMatthew G. Knepley PetscCall(DMRestoreNamedGlobalVector(user->dmPot, "phi", &phi)); 1252*918dfc20SMatthew G. Knepley } 1253*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1254*918dfc20SMatthew G. Knepley } 1255*918dfc20SMatthew G. Knepley 1256*918dfc20SMatthew G. Knepley static PetscErrorCode SetupParameters(MPI_Comm comm, AppCtx *ctx) 1257*918dfc20SMatthew G. Knepley { 1258*918dfc20SMatthew G. Knepley PetscBag bag; 1259*918dfc20SMatthew G. Knepley Parameter *p; 1260*918dfc20SMatthew G. Knepley 1261*918dfc20SMatthew G. Knepley PetscFunctionBeginUser; 1262*918dfc20SMatthew G. Knepley /* setup PETSc parameter bag */ 1263*918dfc20SMatthew G. Knepley PetscCall(PetscBagGetData(ctx->bag, (void **)&p)); 1264*918dfc20SMatthew G. Knepley PetscCall(PetscBagSetName(ctx->bag, "par", "Vlasov-Poisson Parameters")); 1265*918dfc20SMatthew G. Knepley bag = ctx->bag; 1266*918dfc20SMatthew G. Knepley PetscCall(PetscBagRegisterScalar(bag, &p->v0, 1.0, "v0", "Velocity scale, m/s")); 1267*918dfc20SMatthew G. Knepley PetscCall(PetscBagRegisterScalar(bag, &p->t0, 1.0, "t0", "Time scale, s")); 1268*918dfc20SMatthew G. Knepley PetscCall(PetscBagRegisterScalar(bag, &p->x0, 1.0, "x0", "Space scale, m")); 1269*918dfc20SMatthew G. Knepley PetscCall(PetscBagRegisterScalar(bag, &p->v0, 1.0, "phi0", "Potential scale, kg*m^2/A*s^3")); 1270*918dfc20SMatthew G. Knepley PetscCall(PetscBagRegisterScalar(bag, &p->q0, 1.0, "q0", "Charge Scale, A*s")); 1271*918dfc20SMatthew G. Knepley PetscCall(PetscBagRegisterScalar(bag, &p->m0, 1.0, "m0", "Mass Scale, kg")); 1272*918dfc20SMatthew G. Knepley PetscCall(PetscBagRegisterScalar(bag, &p->epsi0, 1.0, "epsi0", "Permittivity of Free Space, kg")); 1273*918dfc20SMatthew G. Knepley PetscCall(PetscBagRegisterScalar(bag, &p->kb, 1.0, "kb", "Boltzmann Constant, m^2 kg/s^2 K^1")); 1274*918dfc20SMatthew G. Knepley 1275*918dfc20SMatthew G. Knepley PetscCall(PetscBagRegisterScalar(bag, &p->sigma, 1.0, "sigma", "Charge per unit area, C/m^3")); 1276*918dfc20SMatthew G. Knepley PetscCall(PetscBagRegisterScalar(bag, &p->poissonNumber, 1.0, "poissonNumber", "Non-Dimensional Poisson Number")); 1277*918dfc20SMatthew G. Knepley PetscCall(PetscBagRegisterScalar(bag, &p->vlasovNumber, 1.0, "vlasovNumber", "Non-Dimensional Vlasov Number")); 1278*918dfc20SMatthew G. Knepley PetscCall(PetscBagSetFromOptions(bag)); 1279*918dfc20SMatthew G. Knepley { 1280*918dfc20SMatthew G. Knepley PetscViewer viewer; 1281*918dfc20SMatthew G. Knepley PetscViewerFormat format; 1282*918dfc20SMatthew G. Knepley PetscBool flg; 1283*918dfc20SMatthew G. Knepley 1284*918dfc20SMatthew G. Knepley PetscCall(PetscOptionsCreateViewer(comm, NULL, NULL, "-param_view", &viewer, &format, &flg)); 1285*918dfc20SMatthew G. Knepley if (flg) { 1286*918dfc20SMatthew G. Knepley PetscCall(PetscViewerPushFormat(viewer, format)); 1287*918dfc20SMatthew G. Knepley PetscCall(PetscBagView(bag, viewer)); 1288*918dfc20SMatthew G. Knepley PetscCall(PetscViewerFlush(viewer)); 1289*918dfc20SMatthew G. Knepley PetscCall(PetscViewerPopFormat(viewer)); 1290*918dfc20SMatthew G. Knepley PetscCall(PetscViewerDestroy(&viewer)); 1291*918dfc20SMatthew G. Knepley } 1292*918dfc20SMatthew G. Knepley } 1293*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1294*918dfc20SMatthew G. Knepley } 1295*918dfc20SMatthew G. Knepley 1296*918dfc20SMatthew G. Knepley static PetscErrorCode CreateMesh(MPI_Comm comm, AppCtx *user, DM *dm) 1297*918dfc20SMatthew G. Knepley { 1298*918dfc20SMatthew G. Knepley PetscFunctionBeginUser; 1299*918dfc20SMatthew G. Knepley PetscCall(DMCreate(comm, dm)); 1300*918dfc20SMatthew G. Knepley PetscCall(DMSetType(*dm, DMPLEX)); 1301*918dfc20SMatthew G. Knepley PetscCall(DMSetFromOptions(*dm)); 1302*918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)*dm, "space")); 1303*918dfc20SMatthew G. Knepley PetscCall(DMViewFromOptions(*dm, NULL, "-dm_view")); 1304*918dfc20SMatthew G. Knepley 1305*918dfc20SMatthew G. Knepley // Cache the mesh geometry 1306*918dfc20SMatthew G. Knepley DMField coordField; 1307*918dfc20SMatthew G. Knepley IS cellIS; 1308*918dfc20SMatthew G. Knepley PetscQuadrature quad; 1309*918dfc20SMatthew G. Knepley PetscReal *wt, *pt; 1310*918dfc20SMatthew G. Knepley PetscInt cdim, cStart, cEnd; 1311*918dfc20SMatthew G. Knepley 1312*918dfc20SMatthew G. Knepley PetscCall(DMGetCoordinateField(*dm, &coordField)); 1313*918dfc20SMatthew G. Knepley PetscCheck(coordField, comm, PETSC_ERR_USER, "DM must have a coordinate field"); 1314*918dfc20SMatthew G. Knepley PetscCall(DMGetCoordinateDim(*dm, &cdim)); 1315*918dfc20SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(*dm, 0, &cStart, &cEnd)); 1316*918dfc20SMatthew G. Knepley PetscCall(ISCreateStride(PETSC_COMM_SELF, cEnd - cStart, cStart, 1, &cellIS)); 1317*918dfc20SMatthew G. Knepley PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, &quad)); 1318*918dfc20SMatthew G. Knepley PetscCall(PetscMalloc1(1, &wt)); 1319*918dfc20SMatthew G. Knepley PetscCall(PetscMalloc1(2, &pt)); 1320*918dfc20SMatthew G. Knepley wt[0] = 1.; 1321*918dfc20SMatthew G. Knepley pt[0] = -1.; 1322*918dfc20SMatthew G. Knepley pt[1] = -1.; 1323*918dfc20SMatthew G. Knepley PetscCall(PetscQuadratureSetData(quad, cdim, 1, 1, pt, wt)); 1324*918dfc20SMatthew G. Knepley PetscCall(DMFieldCreateFEGeom(coordField, cellIS, quad, PETSC_FEGEOM_BASIC, &user->fegeom)); 1325*918dfc20SMatthew G. Knepley PetscCall(PetscQuadratureDestroy(&quad)); 1326*918dfc20SMatthew G. Knepley PetscCall(ISDestroy(&cellIS)); 1327*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1328*918dfc20SMatthew G. Knepley } 1329*918dfc20SMatthew G. Knepley 1330*918dfc20SMatthew 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[]) 1331*918dfc20SMatthew G. Knepley { 1332*918dfc20SMatthew G. Knepley f0[0] = -constants[SIGMA]; 1333*918dfc20SMatthew G. Knepley } 1334*918dfc20SMatthew G. Knepley 1335*918dfc20SMatthew 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[]) 1336*918dfc20SMatthew G. Knepley { 1337*918dfc20SMatthew G. Knepley PetscInt d; 1338*918dfc20SMatthew G. Knepley for (d = 0; d < dim; ++d) f1[d] = u_x[d]; 1339*918dfc20SMatthew G. Knepley } 1340*918dfc20SMatthew G. Knepley 1341*918dfc20SMatthew 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[]) 1342*918dfc20SMatthew G. Knepley { 1343*918dfc20SMatthew G. Knepley PetscInt d; 1344*918dfc20SMatthew G. Knepley for (d = 0; d < dim; ++d) g3[d * dim + d] = 1.0; 1345*918dfc20SMatthew G. Knepley } 1346*918dfc20SMatthew G. Knepley 1347*918dfc20SMatthew G. Knepley /* 1348*918dfc20SMatthew G. Knepley / I -grad\ / q \ = /0\ 1349*918dfc20SMatthew G. Knepley \-div 0 / \phi/ \f/ 1350*918dfc20SMatthew G. Knepley */ 1351*918dfc20SMatthew 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[]) 1352*918dfc20SMatthew G. Knepley { 1353*918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) f0[d] += u[uOff[0] + d]; 1354*918dfc20SMatthew G. Knepley } 1355*918dfc20SMatthew G. Knepley 1356*918dfc20SMatthew 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[]) 1357*918dfc20SMatthew G. Knepley { 1358*918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) f1[d * dim + d] = u[uOff[1]]; 1359*918dfc20SMatthew G. Knepley } 1360*918dfc20SMatthew G. Knepley 1361*918dfc20SMatthew 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[]) 1362*918dfc20SMatthew G. Knepley { 1363*918dfc20SMatthew G. Knepley f0[0] += constants[SIGMA]; 1364*918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) f0[0] += u_x[uOff_x[0] + d * dim + d]; 1365*918dfc20SMatthew G. Knepley } 1366*918dfc20SMatthew G. Knepley 1367*918dfc20SMatthew G. Knepley /* Boundary residual. Dirichlet boundary for u means u_bdy=p*n */ 1368*918dfc20SMatthew 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[]) 1369*918dfc20SMatthew G. Knepley { 1370*918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) g0[d * dim + d] = 1.0; 1371*918dfc20SMatthew G. Knepley } 1372*918dfc20SMatthew G. Knepley 1373*918dfc20SMatthew 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[]) 1374*918dfc20SMatthew G. Knepley { 1375*918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) g2[d * dim + d] = 1.0; 1376*918dfc20SMatthew G. Knepley } 1377*918dfc20SMatthew G. Knepley 1378*918dfc20SMatthew 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[]) 1379*918dfc20SMatthew G. Knepley { 1380*918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) g1[d * dim + d] = 1.0; 1381*918dfc20SMatthew G. Knepley } 1382*918dfc20SMatthew G. Knepley 1383*918dfc20SMatthew G. Knepley static PetscErrorCode CreateFEM(DM dm, AppCtx *user) 1384*918dfc20SMatthew G. Knepley { 1385*918dfc20SMatthew G. Knepley PetscFE fephi, feq; 1386*918dfc20SMatthew G. Knepley PetscDS ds; 1387*918dfc20SMatthew G. Knepley PetscBool simplex; 1388*918dfc20SMatthew G. Knepley PetscInt dim; 1389*918dfc20SMatthew G. Knepley 1390*918dfc20SMatthew G. Knepley PetscFunctionBeginUser; 1391*918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(dm, &dim)); 1392*918dfc20SMatthew G. Knepley PetscCall(DMPlexIsSimplex(dm, &simplex)); 1393*918dfc20SMatthew G. Knepley if (user->em == EM_MIXED) { 1394*918dfc20SMatthew G. Knepley DMLabel label; 1395*918dfc20SMatthew G. Knepley const PetscInt id = 1; 1396*918dfc20SMatthew G. Knepley 1397*918dfc20SMatthew G. Knepley PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, dim, simplex, "field_", PETSC_DETERMINE, &feq)); 1398*918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)feq, "field")); 1399*918dfc20SMatthew G. Knepley PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "potential_", PETSC_DETERMINE, &fephi)); 1400*918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)fephi, "potential")); 1401*918dfc20SMatthew G. Knepley PetscCall(PetscFECopyQuadrature(feq, fephi)); 1402*918dfc20SMatthew G. Knepley PetscCall(DMSetField(dm, 0, NULL, (PetscObject)feq)); 1403*918dfc20SMatthew G. Knepley PetscCall(DMSetField(dm, 1, NULL, (PetscObject)fephi)); 1404*918dfc20SMatthew G. Knepley PetscCall(DMCreateDS(dm)); 1405*918dfc20SMatthew G. Knepley PetscCall(PetscFEDestroy(&fephi)); 1406*918dfc20SMatthew G. Knepley PetscCall(PetscFEDestroy(&feq)); 1407*918dfc20SMatthew G. Knepley 1408*918dfc20SMatthew G. Knepley PetscCall(DMGetLabel(dm, "marker", &label)); 1409*918dfc20SMatthew G. Knepley PetscCall(DMGetDS(dm, &ds)); 1410*918dfc20SMatthew G. Knepley 1411*918dfc20SMatthew G. Knepley PetscCall(PetscDSSetResidual(ds, 0, f0_q, f1_q)); 1412*918dfc20SMatthew G. Knepley PetscCall(PetscDSSetResidual(ds, 1, f0_phi_backgroundCharge, NULL)); 1413*918dfc20SMatthew G. Knepley PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_qq, NULL, NULL, NULL)); 1414*918dfc20SMatthew G. Knepley PetscCall(PetscDSSetJacobian(ds, 0, 1, NULL, NULL, g2_qphi, NULL)); 1415*918dfc20SMatthew G. Knepley PetscCall(PetscDSSetJacobian(ds, 1, 0, NULL, g1_phiq, NULL, NULL)); 1416*918dfc20SMatthew G. Knepley 1417*918dfc20SMatthew G. Knepley PetscCall(DMAddBoundary(dm, DM_BC_ESSENTIAL, "wall", label, 1, &id, 0, 0, NULL, (void (*)(void))zero, NULL, NULL, NULL)); 1418*918dfc20SMatthew G. Knepley 1419*918dfc20SMatthew G. Knepley } else { 1420*918dfc20SMatthew G. Knepley MatNullSpace nullsp; 1421*918dfc20SMatthew G. Knepley PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, NULL, PETSC_DETERMINE, &fephi)); 1422*918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)fephi, "potential")); 1423*918dfc20SMatthew G. Knepley PetscCall(DMSetField(dm, 0, NULL, (PetscObject)fephi)); 1424*918dfc20SMatthew G. Knepley PetscCall(DMCreateDS(dm)); 1425*918dfc20SMatthew G. Knepley PetscCall(DMGetDS(dm, &ds)); 1426*918dfc20SMatthew G. Knepley PetscCall(PetscDSSetResidual(ds, 0, ion_f0, laplacian_f1)); 1427*918dfc20SMatthew G. Knepley PetscCall(PetscDSSetJacobian(ds, 0, 0, NULL, NULL, NULL, laplacian_g3)); 1428*918dfc20SMatthew G. Knepley PetscCall(MatNullSpaceCreate(PetscObjectComm((PetscObject)dm), PETSC_TRUE, 0, NULL, &nullsp)); 1429*918dfc20SMatthew G. Knepley PetscCall(PetscObjectCompose((PetscObject)fephi, "nullspace", (PetscObject)nullsp)); 1430*918dfc20SMatthew G. Knepley PetscCall(MatNullSpaceDestroy(&nullsp)); 1431*918dfc20SMatthew G. Knepley PetscCall(PetscFEDestroy(&fephi)); 1432*918dfc20SMatthew G. Knepley } 1433*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1434*918dfc20SMatthew G. Knepley } 1435*918dfc20SMatthew G. Knepley 1436*918dfc20SMatthew G. Knepley static PetscErrorCode CreatePoisson(DM dm, AppCtx *user) 1437*918dfc20SMatthew G. Knepley { 1438*918dfc20SMatthew G. Knepley SNES snes; 1439*918dfc20SMatthew G. Knepley Mat J; 1440*918dfc20SMatthew G. Knepley MatNullSpace nullSpace; 1441*918dfc20SMatthew G. Knepley 1442*918dfc20SMatthew G. Knepley PetscFunctionBeginUser; 1443*918dfc20SMatthew G. Knepley PetscCall(CreateFEM(dm, user)); 1444*918dfc20SMatthew G. Knepley PetscCall(SNESCreate(PetscObjectComm((PetscObject)dm), &snes)); 1445*918dfc20SMatthew G. Knepley PetscCall(SNESSetOptionsPrefix(snes, "em_")); 1446*918dfc20SMatthew G. Knepley PetscCall(SNESSetDM(snes, dm)); 1447*918dfc20SMatthew G. Knepley PetscCall(DMPlexSetSNESLocalFEM(dm, PETSC_FALSE, user)); 1448*918dfc20SMatthew G. Knepley PetscCall(SNESSetFromOptions(snes)); 1449*918dfc20SMatthew G. Knepley 1450*918dfc20SMatthew G. Knepley PetscCall(DMCreateMatrix(dm, &J)); 1451*918dfc20SMatthew G. Knepley PetscCall(MatNullSpaceCreate(PetscObjectComm((PetscObject)dm), PETSC_TRUE, 0, NULL, &nullSpace)); 1452*918dfc20SMatthew G. Knepley PetscCall(MatSetNullSpace(J, nullSpace)); 1453*918dfc20SMatthew G. Knepley PetscCall(MatNullSpaceDestroy(&nullSpace)); 1454*918dfc20SMatthew G. Knepley PetscCall(SNESSetJacobian(snes, J, J, NULL, NULL)); 1455*918dfc20SMatthew G. Knepley PetscCall(MatDestroy(&J)); 1456*918dfc20SMatthew G. Knepley if (user->em == EM_MIXED) { 1457*918dfc20SMatthew G. Knepley const PetscInt potential = 1; 1458*918dfc20SMatthew G. Knepley 1459*918dfc20SMatthew G. Knepley PetscCall(DMCreateSubDM(dm, 1, &potential, &user->isPot, &user->dmPot)); 1460*918dfc20SMatthew G. Knepley } else { 1461*918dfc20SMatthew G. Knepley user->dmPot = dm; 1462*918dfc20SMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)user->dmPot)); 1463*918dfc20SMatthew G. Knepley } 1464*918dfc20SMatthew G. Knepley PetscCall(DMCreateMassMatrix(user->dmPot, user->dmPot, &user->M)); 1465*918dfc20SMatthew G. Knepley PetscCall(DMPlexCreateClosureIndex(dm, NULL)); 1466*918dfc20SMatthew G. Knepley user->snes = snes; 1467*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1468*918dfc20SMatthew G. Knepley } 1469*918dfc20SMatthew G. Knepley 1470*918dfc20SMatthew G. Knepley // Conservation of mass (m = 1.0) 1471*918dfc20SMatthew G. Knepley // n_t + 1/ m p_x = 0 1472*918dfc20SMatthew 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[]) 1473*918dfc20SMatthew G. Knepley { 1474*918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) f0[0] += u_t[uOff[0]] + u_x[uOff_x[1] + d * dim + d]; 1475*918dfc20SMatthew G. Knepley } 1476*918dfc20SMatthew G. Knepley 1477*918dfc20SMatthew G. Knepley // Conservation of momentum (m = 1, e = 1) 1478*918dfc20SMatthew G. Knepley // p_t + (u p)_x = -pr_x + e n E 1479*918dfc20SMatthew G. Knepley // p_t + (div u) p + u . grad p = -pr_x + e n E 1480*918dfc20SMatthew G. Knepley // p_t + (div p) p / n - (p . grad n) p / n^2 + p / n . grad p = -pr_x + e n E 1481*918dfc20SMatthew 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[]) 1482*918dfc20SMatthew G. Knepley { 1483*918dfc20SMatthew G. Knepley const PetscScalar n = u[uOff[0]]; 1484*918dfc20SMatthew G. Knepley 1485*918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) { 1486*918dfc20SMatthew G. Knepley PetscReal divp = 0.; 1487*918dfc20SMatthew G. Knepley 1488*918dfc20SMatthew G. Knepley f0[d] += u_t[uOff[1] + d]; 1489*918dfc20SMatthew G. Knepley for (PetscInt e = 0; e < dim; ++e) { 1490*918dfc20SMatthew G. Knepley f0[d] += u[uOff[1] + e] * u_x[uOff_x[1] + d * dim + e] / n; // p / n . grad p 1491*918dfc20SMatthew 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 1492*918dfc20SMatthew G. Knepley divp += u_x[uOff_x[1] + e * dim + e]; 1493*918dfc20SMatthew G. Knepley } 1494*918dfc20SMatthew G. Knepley f0[d] += divp * u[uOff[1] + d] / n; // (div p) p / n 1495*918dfc20SMatthew G. Knepley f0[d] += u_x[uOff_x[2] + d]; // pr_x 1496*918dfc20SMatthew G. Knepley f0[d] -= n * a[d]; // -e n E 1497*918dfc20SMatthew G. Knepley } 1498*918dfc20SMatthew G. Knepley } 1499*918dfc20SMatthew G. Knepley 1500*918dfc20SMatthew G. Knepley // Conservation of energy 1501*918dfc20SMatthew G. Knepley // pr_t + (u pr)_x = -3 pr u_x - q_x 1502*918dfc20SMatthew G. Knepley // pr_t + (div u) pr + u . grad pr = -3 pr (div u) - q_x 1503*918dfc20SMatthew G. Knepley // pr_t + 4 (div u) pr + u . grad pr = -q_x 1504*918dfc20SMatthew G. Knepley // pr_t + 4 div p pr / n - 4 (p . grad n) pr / n^2 + p . grad pr / n = -q_x 1505*918dfc20SMatthew 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[]) 1506*918dfc20SMatthew G. Knepley { 1507*918dfc20SMatthew G. Knepley const PetscScalar n = u[uOff[0]]; 1508*918dfc20SMatthew G. Knepley const PetscScalar pr = u[uOff[2]]; 1509*918dfc20SMatthew G. Knepley PetscReal divp = 0.; 1510*918dfc20SMatthew G. Knepley 1511*918dfc20SMatthew G. Knepley f0[0] += u_t[uOff[2]]; 1512*918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) { 1513*918dfc20SMatthew G. Knepley f0[0] += u[uOff[1] + d] * u_x[uOff_x[2] + d] / n; // p . grad pr / n 1514*918dfc20SMatthew 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 1515*918dfc20SMatthew G. Knepley divp += u_x[uOff_x[1] + d * dim + d]; 1516*918dfc20SMatthew G. Knepley } 1517*918dfc20SMatthew G. Knepley f0[0] += 4. * divp * pr / n; // 4 div p pr / n 1518*918dfc20SMatthew G. Knepley } 1519*918dfc20SMatthew G. Knepley 1520*918dfc20SMatthew G. Knepley static PetscErrorCode SetupMomentProblem(DM dm, AppCtx *ctx) 1521*918dfc20SMatthew G. Knepley { 1522*918dfc20SMatthew G. Knepley PetscDS ds; 1523*918dfc20SMatthew G. Knepley 1524*918dfc20SMatthew G. Knepley PetscFunctionBegin; 1525*918dfc20SMatthew G. Knepley PetscCall(DMGetDS(dm, &ds)); 1526*918dfc20SMatthew G. Knepley PetscCall(PetscDSSetResidual(ds, 0, f0_mass, NULL)); 1527*918dfc20SMatthew G. Knepley PetscCall(PetscDSSetResidual(ds, 1, f0_momentum, NULL)); 1528*918dfc20SMatthew G. Knepley PetscCall(PetscDSSetResidual(ds, 2, f0_energy, NULL)); 1529*918dfc20SMatthew G. Knepley //PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_mass_uu, NULL, NULL, NULL)); 1530*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1531*918dfc20SMatthew G. Knepley } 1532*918dfc20SMatthew G. Knepley 1533*918dfc20SMatthew G. Knepley static PetscErrorCode CreateMomentFields(DM odm, AppCtx *user) 1534*918dfc20SMatthew G. Knepley { 1535*918dfc20SMatthew G. Knepley DM dm; 1536*918dfc20SMatthew G. Knepley PetscFE fe; 1537*918dfc20SMatthew G. Knepley DMPolytopeType ct; 1538*918dfc20SMatthew G. Knepley PetscInt dim, cStart; 1539*918dfc20SMatthew G. Knepley 1540*918dfc20SMatthew G. Knepley PetscFunctionBeginUser; 1541*918dfc20SMatthew G. Knepley PetscCall(DMClone(odm, &dm)); 1542*918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(dm, &dim)); 1543*918dfc20SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, NULL)); 1544*918dfc20SMatthew G. Knepley PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 1545*918dfc20SMatthew G. Knepley PetscCall(PetscFECreateByCell(PETSC_COMM_SELF, dim, 1, ct, NULL, PETSC_DETERMINE, &fe)); 1546*918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)fe, "number density")); 1547*918dfc20SMatthew G. Knepley PetscCall(DMSetField(dm, 0, NULL, (PetscObject)fe)); 1548*918dfc20SMatthew G. Knepley PetscCall(PetscFEDestroy(&fe)); 1549*918dfc20SMatthew G. Knepley PetscCall(PetscFECreateByCell(PETSC_COMM_SELF, dim, dim, ct, NULL, PETSC_DETERMINE, &fe)); 1550*918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)fe, "momentum density")); 1551*918dfc20SMatthew G. Knepley PetscCall(DMSetField(dm, 1, NULL, (PetscObject)fe)); 1552*918dfc20SMatthew G. Knepley PetscCall(PetscFEDestroy(&fe)); 1553*918dfc20SMatthew G. Knepley PetscCall(PetscFECreateByCell(PETSC_COMM_SELF, dim, 1, ct, NULL, PETSC_DETERMINE, &fe)); 1554*918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)fe, "energy density")); 1555*918dfc20SMatthew G. Knepley PetscCall(DMSetField(dm, 2, NULL, (PetscObject)fe)); 1556*918dfc20SMatthew G. Knepley PetscCall(PetscFEDestroy(&fe)); 1557*918dfc20SMatthew G. Knepley PetscCall(DMCreateDS(dm)); 1558*918dfc20SMatthew G. Knepley PetscCall(SetupMomentProblem(dm, user)); 1559*918dfc20SMatthew G. Knepley user->dmMom = dm; 1560*918dfc20SMatthew G. Knepley PetscInt field; 1561*918dfc20SMatthew G. Knepley 1562*918dfc20SMatthew G. Knepley field = 0; 1563*918dfc20SMatthew G. Knepley PetscCall(DMCreateSubDM(user->dmMom, 1, &field, &user->isN, &user->dmN)); 1564*918dfc20SMatthew G. Knepley PetscCall(DMCreateMassMatrix(user->dmN, user->dmN, &user->MN)); 1565*918dfc20SMatthew G. Knepley field = 1; 1566*918dfc20SMatthew G. Knepley PetscCall(DMCreateSubDM(user->dmMom, 1, &field, &user->isP, &user->dmP)); 1567*918dfc20SMatthew G. Knepley PetscCall(DMCreateMassMatrix(user->dmP, user->dmP, &user->MP)); 1568*918dfc20SMatthew G. Knepley field = 2; 1569*918dfc20SMatthew G. Knepley PetscCall(DMCreateSubDM(user->dmMom, 1, &field, &user->isE, &user->dmE)); 1570*918dfc20SMatthew G. Knepley PetscCall(DMCreateMassMatrix(user->dmE, user->dmE, &user->ME)); 1571*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1572*918dfc20SMatthew G. Knepley } 1573*918dfc20SMatthew G. Knepley 1574*918dfc20SMatthew G. Knepley PetscErrorCode PetscPDFPertubedConstant2D(const PetscReal x[], const PetscReal dummy[], PetscReal p[]) 1575*918dfc20SMatthew G. Knepley { 1576*918dfc20SMatthew G. Knepley p[0] = (1 + 0.01 * PetscCosReal(0.5 * x[0])) / (2 * PETSC_PI); 1577*918dfc20SMatthew G. Knepley p[1] = (1 + 0.01 * PetscCosReal(0.5 * x[1])) / (2 * PETSC_PI); 1578*918dfc20SMatthew G. Knepley return PETSC_SUCCESS; 1579*918dfc20SMatthew G. Knepley } 1580*918dfc20SMatthew G. Knepley PetscErrorCode PetscPDFPertubedConstant1D(const PetscReal x[], const PetscReal dummy[], PetscReal p[]) 1581*918dfc20SMatthew G. Knepley { 1582*918dfc20SMatthew G. Knepley p[0] = (1. + 0.01 * PetscCosReal(0.5 * x[0])) / (2 * PETSC_PI); 1583*918dfc20SMatthew G. Knepley return PETSC_SUCCESS; 1584*918dfc20SMatthew G. Knepley } 1585*918dfc20SMatthew G. Knepley 1586*918dfc20SMatthew G. Knepley PetscErrorCode PetscPDFCosine1D(const PetscReal x[], const PetscReal scale[], PetscReal p[]) 1587*918dfc20SMatthew G. Knepley { 1588*918dfc20SMatthew G. Knepley const PetscReal alpha = scale ? scale[0] : 0.0; 1589*918dfc20SMatthew G. Knepley const PetscReal k = scale ? scale[1] : 1.; 1590*918dfc20SMatthew G. Knepley p[0] = (1 + alpha * PetscCosReal(k * x[0])); 1591*918dfc20SMatthew G. Knepley return PETSC_SUCCESS; 1592*918dfc20SMatthew G. Knepley } 1593*918dfc20SMatthew G. Knepley 1594*918dfc20SMatthew G. Knepley PetscErrorCode PetscPDFCosine2D(const PetscReal x[], const PetscReal scale[], PetscReal p[]) 1595*918dfc20SMatthew G. Knepley { 1596*918dfc20SMatthew G. Knepley const PetscReal alpha = scale ? scale[0] : 0.; 1597*918dfc20SMatthew G. Knepley const PetscReal k = scale ? scale[0] : 1.; 1598*918dfc20SMatthew G. Knepley p[0] = (1 + alpha * PetscCosReal(k * (x[0] + x[1]))); 1599*918dfc20SMatthew G. Knepley return PETSC_SUCCESS; 1600*918dfc20SMatthew G. Knepley } 1601*918dfc20SMatthew G. Knepley 1602*918dfc20SMatthew G. Knepley static PetscErrorCode CreateVelocityDM(DM sw, DM *vdm) 1603*918dfc20SMatthew G. Knepley { 1604*918dfc20SMatthew G. Knepley PetscFE fe; 1605*918dfc20SMatthew G. Knepley DMPolytopeType ct; 1606*918dfc20SMatthew G. Knepley PetscInt dim, cStart; 1607*918dfc20SMatthew G. Knepley const char *prefix = "v"; 1608*918dfc20SMatthew G. Knepley 1609*918dfc20SMatthew G. Knepley PetscFunctionBegin; 1610*918dfc20SMatthew G. Knepley PetscCall(DMCreate(PETSC_COMM_SELF, vdm)); 1611*918dfc20SMatthew G. Knepley PetscCall(DMSetType(*vdm, DMPLEX)); 1612*918dfc20SMatthew G. Knepley PetscCall(DMPlexSetOptionsPrefix(*vdm, prefix)); 1613*918dfc20SMatthew G. Knepley PetscCall(DMSetFromOptions(*vdm)); 1614*918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)*vdm, "velocity")); 1615*918dfc20SMatthew G. Knepley PetscCall(DMViewFromOptions(*vdm, NULL, "-dm_view")); 1616*918dfc20SMatthew G. Knepley 1617*918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(*vdm, &dim)); 1618*918dfc20SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(*vdm, 0, &cStart, NULL)); 1619*918dfc20SMatthew G. Knepley PetscCall(DMPlexGetCellType(*vdm, cStart, &ct)); 1620*918dfc20SMatthew G. Knepley PetscCall(PetscFECreateByCell(PETSC_COMM_SELF, dim, 1, ct, prefix, PETSC_DETERMINE, &fe)); 1621*918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)fe, "distribution")); 1622*918dfc20SMatthew G. Knepley PetscCall(DMSetField(*vdm, 0, NULL, (PetscObject)fe)); 1623*918dfc20SMatthew G. Knepley PetscCall(DMCreateDS(*vdm)); 1624*918dfc20SMatthew G. Knepley PetscCall(PetscFEDestroy(&fe)); 1625*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1626*918dfc20SMatthew G. Knepley } 1627*918dfc20SMatthew G. Knepley 1628*918dfc20SMatthew G. Knepley /* 1629*918dfc20SMatthew G. Knepley InitializeParticles_Centroid - Initialize a regular grid of particles. 1630*918dfc20SMatthew G. Knepley 1631*918dfc20SMatthew G. Knepley Input Parameters: 1632*918dfc20SMatthew G. Knepley + sw - The `DMSWARM` 1633*918dfc20SMatthew G. Knepley - force1D - Treat the spatial domain as 1D 1634*918dfc20SMatthew G. Knepley 1635*918dfc20SMatthew G. Knepley Notes: 1636*918dfc20SMatthew G. Knepley This functions sets the species, cellid, spatial coordinate, and velocity fields for all particles. 1637*918dfc20SMatthew G. Knepley 1638*918dfc20SMatthew G. Knepley It places one particle in the centroid of each cell in the implicit tensor product of the spatial 1639*918dfc20SMatthew G. Knepley and velocity meshes. 1640*918dfc20SMatthew G. Knepley */ 1641*918dfc20SMatthew G. Knepley static PetscErrorCode InitializeParticles_Centroid(DM sw) 1642*918dfc20SMatthew G. Knepley { 1643*918dfc20SMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)sw->data; 1644*918dfc20SMatthew G. Knepley DMSwarmCellDM celldm; 1645*918dfc20SMatthew G. Knepley DM xdm, vdm; 1646*918dfc20SMatthew G. Knepley PetscReal vmin[3], vmax[3]; 1647*918dfc20SMatthew G. Knepley PetscReal *x, *v; 1648*918dfc20SMatthew G. Knepley PetscInt *species, *cellid; 1649*918dfc20SMatthew G. Knepley PetscInt dim, xcStart, xcEnd, vcStart, vcEnd, Ns, Np, Npc, debug; 1650*918dfc20SMatthew G. Knepley PetscBool flg; 1651*918dfc20SMatthew G. Knepley MPI_Comm comm; 1652*918dfc20SMatthew G. Knepley const char *cellidname; 1653*918dfc20SMatthew G. Knepley 1654*918dfc20SMatthew G. Knepley PetscFunctionBegin; 1655*918dfc20SMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)sw, &comm)); 1656*918dfc20SMatthew G. Knepley 1657*918dfc20SMatthew G. Knepley PetscOptionsBegin(comm, "", "DMSwarm Options", "DMSWARM"); 1658*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetNumSpecies(sw, &Ns)); 1659*918dfc20SMatthew G. Knepley PetscCall(PetscOptionsInt("-dm_swarMNum_species", "The number of species", "DMSwarmSetNumSpecies", Ns, &Ns, &flg)); 1660*918dfc20SMatthew G. Knepley if (flg) PetscCall(DMSwarmSetNumSpecies(sw, Ns)); 1661*918dfc20SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_swarm_print_coords", "Debug output level for particle coordinate computations", "InitializeParticles", 0, &swarm->printCoords, NULL, 0)); 1662*918dfc20SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_swarm_print_weights", "Debug output level for particle weight computations", "InitializeWeights", 0, &swarm->printWeights, NULL, 0)); 1663*918dfc20SMatthew G. Knepley PetscOptionsEnd(); 1664*918dfc20SMatthew G. Knepley debug = swarm->printCoords; 1665*918dfc20SMatthew G. Knepley 1666*918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim)); 1667*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetCellDM(sw, &xdm)); 1668*918dfc20SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(xdm, 0, &xcStart, &xcEnd)); 1669*918dfc20SMatthew G. Knepley 1670*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetCellDMByName(sw, "velocity", &celldm)); 1671*918dfc20SMatthew G. Knepley PetscCall(DMSwarmCellDMGetDM(celldm, &vdm)); 1672*918dfc20SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(vdm, 0, &vcStart, &vcEnd)); 1673*918dfc20SMatthew G. Knepley 1674*918dfc20SMatthew G. Knepley // One particle per centroid on the tensor product grid 1675*918dfc20SMatthew G. Knepley Npc = (vcEnd - vcStart) * Ns; 1676*918dfc20SMatthew G. Knepley Np = (xcEnd - xcStart) * Npc; 1677*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSetLocalSizes(sw, Np, 0)); 1678*918dfc20SMatthew G. Knepley if (debug) { 1679*918dfc20SMatthew G. Knepley PetscInt gNp, gNc, Nc = xcEnd - xcStart; 1680*918dfc20SMatthew G. Knepley PetscCallMPI(MPIU_Allreduce(&Np, &gNp, 1, MPIU_INT, MPIU_SUM, comm)); 1681*918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(comm, "Global Np = %" PetscInt_FMT "\n", gNp)); 1682*918dfc20SMatthew G. Knepley PetscCallMPI(MPIU_Allreduce(&Nc, &gNc, 1, MPIU_INT, MPIU_SUM, comm)); 1683*918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(comm, "Global X-cells = %" PetscInt_FMT "\n", gNc)); 1684*918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(comm, "Global V-cells = %" PetscInt_FMT "\n", vcEnd - vcStart)); 1685*918dfc20SMatthew G. Knepley } 1686*918dfc20SMatthew G. Knepley 1687*918dfc20SMatthew G. Knepley // Set species and cellid 1688*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetCellDMActive(sw, &celldm)); 1689*918dfc20SMatthew G. Knepley PetscCall(DMSwarmCellDMGetCellID(celldm, &cellidname)); 1690*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "species", NULL, NULL, (void **)&species)); 1691*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, cellidname, NULL, NULL, (void **)&cellid)); 1692*918dfc20SMatthew G. Knepley for (PetscInt c = 0, p = 0; c < xcEnd - xcStart; ++c) { 1693*918dfc20SMatthew G. Knepley for (PetscInt s = 0; s < Ns; ++s) { 1694*918dfc20SMatthew G. Knepley for (PetscInt q = 0; q < Npc / Ns; ++q, ++p) { 1695*918dfc20SMatthew G. Knepley species[p] = s; 1696*918dfc20SMatthew G. Knepley cellid[p] = c; 1697*918dfc20SMatthew G. Knepley } 1698*918dfc20SMatthew G. Knepley } 1699*918dfc20SMatthew G. Knepley } 1700*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "species", NULL, NULL, (void **)&species)); 1701*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, cellidname, NULL, NULL, (void **)&cellid)); 1702*918dfc20SMatthew G. Knepley 1703*918dfc20SMatthew G. Knepley // Set particle coordinates 1704*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&x)); 1705*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "velocity", NULL, NULL, (void **)&v)); 1706*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortGetAccess(sw)); 1707*918dfc20SMatthew G. Knepley PetscCall(DMGetBoundingBox(vdm, vmin, vmax)); 1708*918dfc20SMatthew G. Knepley PetscCall(DMGetCoordinatesLocalSetUp(xdm)); 1709*918dfc20SMatthew G. Knepley for (PetscInt c = 0; c < xcEnd - xcStart; ++c) { 1710*918dfc20SMatthew G. Knepley const PetscInt cell = c + xcStart; 1711*918dfc20SMatthew G. Knepley PetscInt *pidx, Npc; 1712*918dfc20SMatthew G. Knepley PetscReal centroid[3], volume; 1713*918dfc20SMatthew G. Knepley 1714*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortGetPointsPerCell(sw, c, &Npc, &pidx)); 1715*918dfc20SMatthew G. Knepley PetscCall(DMPlexComputeCellGeometryFVM(xdm, cell, &volume, centroid, NULL)); 1716*918dfc20SMatthew G. Knepley for (PetscInt s = 0; s < Ns; ++s) { 1717*918dfc20SMatthew G. Knepley for (PetscInt q = 0; q < Npc / Ns; ++q) { 1718*918dfc20SMatthew G. Knepley const PetscInt p = pidx[q * Ns + s]; 1719*918dfc20SMatthew G. Knepley 1720*918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) { 1721*918dfc20SMatthew G. Knepley x[p * dim + d] = centroid[d]; 1722*918dfc20SMatthew G. Knepley v[p * dim + d] = vmin[0] + (q + 0.5) * ((vmax[0] - vmin[0]) / (Npc / Ns)); 1723*918dfc20SMatthew G. Knepley } 1724*918dfc20SMatthew G. Knepley if (debug > 1) { 1725*918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, "Particle %4" PetscInt_FMT " ", p)); 1726*918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, " x: (")); 1727*918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) { 1728*918dfc20SMatthew G. Knepley if (d > 0) PetscCall(PetscPrintf(PETSC_COMM_SELF, ", ")); 1729*918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, "%g", x[p * dim + d])); 1730*918dfc20SMatthew G. Knepley } 1731*918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, ") v:(")); 1732*918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) { 1733*918dfc20SMatthew G. Knepley if (d > 0) PetscCall(PetscPrintf(PETSC_COMM_SELF, ", ")); 1734*918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, "%g", v[p * dim + d])); 1735*918dfc20SMatthew G. Knepley } 1736*918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, ")\n")); 1737*918dfc20SMatthew G. Knepley } 1738*918dfc20SMatthew G. Knepley } 1739*918dfc20SMatthew G. Knepley } 1740*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(sw, c, &Npc, &pidx)); 1741*918dfc20SMatthew G. Knepley } 1742*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortRestoreAccess(sw)); 1743*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&x)); 1744*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "velocity", NULL, NULL, (void **)&v)); 1745*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1746*918dfc20SMatthew G. Knepley } 1747*918dfc20SMatthew G. Knepley 1748*918dfc20SMatthew G. Knepley /* 1749*918dfc20SMatthew G. Knepley InitializeWeights - Compute weight for each local particle 1750*918dfc20SMatthew G. Knepley 1751*918dfc20SMatthew G. Knepley Input Parameters: 1752*918dfc20SMatthew G. Knepley + sw - The `DMSwarm` 1753*918dfc20SMatthew G. Knepley . totalWeight - The sum of all particle weights 1754*918dfc20SMatthew G. Knepley . func - The PDF for the particle spatial distribution 1755*918dfc20SMatthew G. Knepley - param - The PDF parameters 1756*918dfc20SMatthew G. Knepley 1757*918dfc20SMatthew G. Knepley Notes: 1758*918dfc20SMatthew G. Knepley The PDF for velocity is assumed to be a Gaussian 1759*918dfc20SMatthew G. Knepley 1760*918dfc20SMatthew G. Knepley The particle weights are returned in the `w_q` field of `sw`. 1761*918dfc20SMatthew G. Knepley */ 1762*918dfc20SMatthew G. Knepley static PetscErrorCode InitializeWeights(DM sw, PetscReal totalWeight, PetscProbFn *func, const PetscReal param[]) 1763*918dfc20SMatthew G. Knepley { 1764*918dfc20SMatthew G. Knepley DM xdm, vdm; 1765*918dfc20SMatthew G. Knepley DMSwarmCellDM celldm; 1766*918dfc20SMatthew G. Knepley PetscScalar *weight; 1767*918dfc20SMatthew G. Knepley PetscQuadrature xquad; 1768*918dfc20SMatthew G. Knepley const PetscReal *xq, *xwq; 1769*918dfc20SMatthew G. Knepley const PetscInt order = 5; 1770*918dfc20SMatthew G. Knepley PetscReal xi0[3]; 1771*918dfc20SMatthew G. Knepley PetscReal xwtot = 0., pwtot = 0.; 1772*918dfc20SMatthew G. Knepley PetscInt xNq; 1773*918dfc20SMatthew G. Knepley PetscInt dim, Ns, xcStart, xcEnd, vcStart, vcEnd, debug = ((DM_Swarm *)sw->data)->printWeights; 1774*918dfc20SMatthew G. Knepley MPI_Comm comm; 1775*918dfc20SMatthew G. Knepley PetscMPIInt rank; 1776*918dfc20SMatthew G. Knepley 1777*918dfc20SMatthew G. Knepley PetscFunctionBegin; 1778*918dfc20SMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)sw, &comm)); 1779*918dfc20SMatthew G. Knepley PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1780*918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim)); 1781*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetCellDM(sw, &xdm)); 1782*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetNumSpecies(sw, &Ns)); 1783*918dfc20SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(xdm, 0, &xcStart, &xcEnd)); 1784*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetCellDMByName(sw, "velocity", &celldm)); 1785*918dfc20SMatthew G. Knepley PetscCall(DMSwarmCellDMGetDM(celldm, &vdm)); 1786*918dfc20SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(vdm, 0, &vcStart, &vcEnd)); 1787*918dfc20SMatthew G. Knepley 1788*918dfc20SMatthew G. Knepley // Setup Quadrature for spatial and velocity weight calculations 1789*918dfc20SMatthew G. Knepley PetscCall(PetscDTGaussTensorQuadrature(dim, 1, order, -1.0, 1.0, &xquad)); 1790*918dfc20SMatthew G. Knepley PetscCall(PetscQuadratureGetData(xquad, NULL, NULL, &xNq, &xq, &xwq)); 1791*918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) xi0[d] = -1.0; 1792*918dfc20SMatthew G. Knepley 1793*918dfc20SMatthew G. Knepley // Integrate the density function to get the weights of particles in each cell 1794*918dfc20SMatthew G. Knepley PetscCall(DMGetCoordinatesLocalSetUp(vdm)); 1795*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortGetAccess(sw)); 1796*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "w_q", NULL, NULL, (void **)&weight)); 1797*918dfc20SMatthew G. Knepley for (PetscInt c = xcStart; c < xcEnd; ++c) { 1798*918dfc20SMatthew G. Knepley PetscReal xv0[3], xJ[9], xinvJ[9], xdetJ, xqr[3], xden, xw = 0.; 1799*918dfc20SMatthew G. Knepley PetscInt *pidx, Npc; 1800*918dfc20SMatthew G. Knepley PetscInt xNc; 1801*918dfc20SMatthew G. Knepley const PetscScalar *xarray; 1802*918dfc20SMatthew G. Knepley PetscScalar *xcoords = NULL; 1803*918dfc20SMatthew G. Knepley PetscBool xisDG; 1804*918dfc20SMatthew G. Knepley 1805*918dfc20SMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(xdm, c, &xisDG, &xNc, &xarray, &xcoords)); 1806*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortGetPointsPerCell(sw, c, &Npc, &pidx)); 1807*918dfc20SMatthew 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); 1808*918dfc20SMatthew G. Knepley PetscCall(DMPlexComputeCellGeometryFEM(xdm, c, NULL, xv0, xJ, xinvJ, &xdetJ)); 1809*918dfc20SMatthew G. Knepley for (PetscInt q = 0; q < xNq; ++q) { 1810*918dfc20SMatthew G. Knepley // Transform quadrature points from ref space to real space 1811*918dfc20SMatthew G. Knepley CoordinatesRefToReal(dim, dim, xi0, xv0, xJ, &xq[q * dim], xqr); 1812*918dfc20SMatthew G. Knepley // Get probability density at quad point 1813*918dfc20SMatthew G. Knepley // No need to scale xqr since PDF will be periodic 1814*918dfc20SMatthew G. Knepley PetscCall((*func)(xqr, param, &xden)); 1815*918dfc20SMatthew G. Knepley xw += xden * (xwq[q] * xdetJ); 1816*918dfc20SMatthew G. Knepley } 1817*918dfc20SMatthew G. Knepley xwtot += xw; 1818*918dfc20SMatthew G. Knepley if (debug) { 1819*918dfc20SMatthew G. Knepley IS globalOrdering; 1820*918dfc20SMatthew G. Knepley const PetscInt *ordering; 1821*918dfc20SMatthew G. Knepley 1822*918dfc20SMatthew G. Knepley PetscCall(DMPlexGetCellNumbering(xdm, &globalOrdering)); 1823*918dfc20SMatthew G. Knepley PetscCall(ISGetIndices(globalOrdering, &ordering)); 1824*918dfc20SMatthew 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)); 1825*918dfc20SMatthew G. Knepley PetscCall(ISRestoreIndices(globalOrdering, &ordering)); 1826*918dfc20SMatthew G. Knepley } 1827*918dfc20SMatthew G. Knepley // Set weights to be Gaussian in velocity cells 1828*918dfc20SMatthew G. Knepley for (PetscInt vc = vcStart; vc < vcEnd; ++vc) { 1829*918dfc20SMatthew G. Knepley const PetscInt p = pidx[vc * Ns + 0]; 1830*918dfc20SMatthew G. Knepley PetscReal vw = 0.; 1831*918dfc20SMatthew G. Knepley PetscInt vNc; 1832*918dfc20SMatthew G. Knepley const PetscScalar *varray; 1833*918dfc20SMatthew G. Knepley PetscScalar *vcoords = NULL; 1834*918dfc20SMatthew G. Knepley PetscBool visDG; 1835*918dfc20SMatthew G. Knepley 1836*918dfc20SMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(vdm, vc, &visDG, &vNc, &varray, &vcoords)); 1837*918dfc20SMatthew G. Knepley // TODO: Fix 2 stream Ask Joe 1838*918dfc20SMatthew G. Knepley // Two stream function from 1/2pi v^2 e^(-v^2/2) 1839*918dfc20SMatthew 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.))); 1840*918dfc20SMatthew G. Knepley vw = 0.5 * (PetscErfReal(vcoords[1] / PetscSqrtReal(2.)) - PetscErfReal(vcoords[0] / PetscSqrtReal(2.))); 1841*918dfc20SMatthew G. Knepley 1842*918dfc20SMatthew G. Knepley weight[p] = totalWeight * vw * xw; 1843*918dfc20SMatthew G. Knepley pwtot += weight[p]; 1844*918dfc20SMatthew 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); 1845*918dfc20SMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(vdm, vc, &visDG, &vNc, &varray, &vcoords)); 1846*918dfc20SMatthew G. Knepley if (debug > 1) PetscCall(PetscPrintf(comm, "particle %" PetscInt_FMT ": %g, vw: %g xw: %g\n", p, weight[p], vw, xw)); 1847*918dfc20SMatthew G. Knepley } 1848*918dfc20SMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(xdm, c, &xisDG, &xNc, &xarray, &xcoords)); 1849*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(sw, c, &Npc, &pidx)); 1850*918dfc20SMatthew G. Knepley } 1851*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "w_q", NULL, NULL, (void **)&weight)); 1852*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortRestoreAccess(sw)); 1853*918dfc20SMatthew G. Knepley PetscCall(PetscQuadratureDestroy(&xquad)); 1854*918dfc20SMatthew G. Knepley 1855*918dfc20SMatthew G. Knepley if (debug) { 1856*918dfc20SMatthew G. Knepley PetscReal wtot[2] = {pwtot, xwtot}, gwtot[2]; 1857*918dfc20SMatthew G. Knepley 1858*918dfc20SMatthew G. Knepley PetscCall(PetscSynchronizedFlush(comm, NULL)); 1859*918dfc20SMatthew G. Knepley PetscCallMPI(MPIU_Allreduce(wtot, gwtot, 2, MPIU_REAL, MPIU_SUM, PETSC_COMM_WORLD)); 1860*918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(comm, "particle weight sum = %1.10f cell weight sum = %1.10f\n", (double)gwtot[0], (double)gwtot[1])); 1861*918dfc20SMatthew G. Knepley } 1862*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1863*918dfc20SMatthew G. Knepley } 1864*918dfc20SMatthew G. Knepley 1865*918dfc20SMatthew G. Knepley static PetscErrorCode InitializeParticles_PerturbedWeights(DM sw, AppCtx *user) 1866*918dfc20SMatthew G. Knepley { 1867*918dfc20SMatthew G. Knepley PetscReal scale[2] = {user->cosine_coefficients[0], user->cosine_coefficients[1]}; 1868*918dfc20SMatthew G. Knepley PetscInt dim; 1869*918dfc20SMatthew G. Knepley 1870*918dfc20SMatthew G. Knepley PetscFunctionBegin; 1871*918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim)); 1872*918dfc20SMatthew G. Knepley PetscCall(InitializeParticles_Centroid(sw)); 1873*918dfc20SMatthew G. Knepley PetscCall(InitializeWeights(sw, user->totalWeight, dim == 1 ? PetscPDFCosine1D : PetscPDFCosine2D, scale)); 1874*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1875*918dfc20SMatthew G. Knepley } 1876*918dfc20SMatthew G. Knepley 1877*918dfc20SMatthew G. Knepley static PetscErrorCode InitializeConstants(DM sw, AppCtx *user) 1878*918dfc20SMatthew G. Knepley { 1879*918dfc20SMatthew G. Knepley DM dm; 1880*918dfc20SMatthew G. Knepley PetscInt *species; 1881*918dfc20SMatthew G. Knepley PetscReal *weight, totalCharge = 0., totalWeight = 0., gmin[3], gmax[3], global_charge, global_weight; 1882*918dfc20SMatthew G. Knepley PetscInt Np, dim; 1883*918dfc20SMatthew G. Knepley 1884*918dfc20SMatthew G. Knepley PetscFunctionBegin; 1885*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetCellDM(sw, &dm)); 1886*918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim)); 1887*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(sw, &Np)); 1888*918dfc20SMatthew G. Knepley PetscCall(DMGetBoundingBox(dm, gmin, gmax)); 1889*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "w_q", NULL, NULL, (void **)&weight)); 1890*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "species", NULL, NULL, (void **)&species)); 1891*918dfc20SMatthew G. Knepley for (PetscInt p = 0; p < Np; ++p) { 1892*918dfc20SMatthew G. Knepley totalWeight += weight[p]; 1893*918dfc20SMatthew G. Knepley totalCharge += user->charges[species[p]] * weight[p]; 1894*918dfc20SMatthew G. Knepley } 1895*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "w_q", NULL, NULL, (void **)&weight)); 1896*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "species", NULL, NULL, (void **)&species)); 1897*918dfc20SMatthew G. Knepley { 1898*918dfc20SMatthew G. Knepley Parameter *param; 1899*918dfc20SMatthew G. Knepley PetscReal Area; 1900*918dfc20SMatthew G. Knepley 1901*918dfc20SMatthew G. Knepley PetscCall(PetscBagGetData(user->bag, (void **)¶m)); 1902*918dfc20SMatthew G. Knepley switch (dim) { 1903*918dfc20SMatthew G. Knepley case 1: 1904*918dfc20SMatthew G. Knepley Area = (gmax[0] - gmin[0]); 1905*918dfc20SMatthew G. Knepley break; 1906*918dfc20SMatthew G. Knepley case 2: 1907*918dfc20SMatthew G. Knepley Area = (gmax[0] - gmin[0]) * (gmax[1] - gmin[1]); 1908*918dfc20SMatthew G. Knepley break; 1909*918dfc20SMatthew G. Knepley case 3: 1910*918dfc20SMatthew G. Knepley Area = (gmax[0] - gmin[0]) * (gmax[1] - gmin[1]) * (gmax[2] - gmin[2]); 1911*918dfc20SMatthew G. Knepley break; 1912*918dfc20SMatthew G. Knepley default: 1913*918dfc20SMatthew G. Knepley SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Dimension %" PetscInt_FMT " not supported", dim); 1914*918dfc20SMatthew G. Knepley } 1915*918dfc20SMatthew G. Knepley PetscCallMPI(MPIU_Allreduce(&totalWeight, &global_weight, 1, MPIU_REAL, MPIU_SUM, PETSC_COMM_WORLD)); 1916*918dfc20SMatthew G. Knepley PetscCallMPI(MPIU_Allreduce(&totalCharge, &global_charge, 1, MPIU_REAL, MPIU_SUM, PETSC_COMM_WORLD)); 1917*918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_WORLD, "dim = %" PetscInt_FMT "\ttotalWeight = %f, user->charges[species[0]] = %f\ttotalCharge = %f, Total Area = %f\n", dim, (double)global_weight, (double)user->charges[0], (double)global_charge, (double)Area)); 1918*918dfc20SMatthew G. Knepley param->sigma = PetscAbsReal(global_charge / (Area)); 1919*918dfc20SMatthew G. Knepley 1920*918dfc20SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_WORLD, "sigma: %g\n", (double)param->sigma)); 1921*918dfc20SMatthew 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, 1922*918dfc20SMatthew G. Knepley (double)param->vlasovNumber)); 1923*918dfc20SMatthew G. Knepley } 1924*918dfc20SMatthew G. Knepley /* Setup Constants */ 1925*918dfc20SMatthew G. Knepley { 1926*918dfc20SMatthew G. Knepley PetscDS ds; 1927*918dfc20SMatthew G. Knepley Parameter *param; 1928*918dfc20SMatthew G. Knepley PetscCall(PetscBagGetData(user->bag, (void **)¶m)); 1929*918dfc20SMatthew G. Knepley PetscScalar constants[NUM_CONSTANTS]; 1930*918dfc20SMatthew G. Knepley constants[SIGMA] = param->sigma; 1931*918dfc20SMatthew G. Knepley constants[V0] = param->v0; 1932*918dfc20SMatthew G. Knepley constants[T0] = param->t0; 1933*918dfc20SMatthew G. Knepley constants[X0] = param->x0; 1934*918dfc20SMatthew G. Knepley constants[M0] = param->m0; 1935*918dfc20SMatthew G. Knepley constants[Q0] = param->q0; 1936*918dfc20SMatthew G. Knepley constants[PHI0] = param->phi0; 1937*918dfc20SMatthew G. Knepley constants[POISSON] = param->poissonNumber; 1938*918dfc20SMatthew G. Knepley constants[VLASOV] = param->vlasovNumber; 1939*918dfc20SMatthew G. Knepley PetscCall(DMGetDS(dm, &ds)); 1940*918dfc20SMatthew G. Knepley PetscCall(PetscDSSetConstants(ds, NUM_CONSTANTS, constants)); 1941*918dfc20SMatthew G. Knepley } 1942*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1943*918dfc20SMatthew G. Knepley } 1944*918dfc20SMatthew G. Knepley 1945*918dfc20SMatthew G. Knepley static PetscErrorCode CreateSwarm(DM dm, AppCtx *user, DM *sw) 1946*918dfc20SMatthew G. Knepley { 1947*918dfc20SMatthew G. Knepley DMSwarmCellDM celldm; 1948*918dfc20SMatthew G. Knepley DM vdm; 1949*918dfc20SMatthew G. Knepley PetscReal v0[2] = {1., 0.}; 1950*918dfc20SMatthew G. Knepley PetscInt dim; 1951*918dfc20SMatthew G. Knepley 1952*918dfc20SMatthew G. Knepley PetscFunctionBeginUser; 1953*918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(dm, &dim)); 1954*918dfc20SMatthew G. Knepley PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), sw)); 1955*918dfc20SMatthew G. Knepley PetscCall(DMSetType(*sw, DMSWARM)); 1956*918dfc20SMatthew G. Knepley PetscCall(DMSetDimension(*sw, dim)); 1957*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSetType(*sw, DMSWARM_PIC)); 1958*918dfc20SMatthew G. Knepley PetscCall(DMSetApplicationContext(*sw, user)); 1959*918dfc20SMatthew G. Knepley 1960*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRegisterPetscDatatypeField(*sw, "w_q", 1, PETSC_SCALAR)); 1961*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRegisterPetscDatatypeField(*sw, "velocity", dim, PETSC_REAL)); 1962*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRegisterPetscDatatypeField(*sw, "species", 1, PETSC_INT)); 1963*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRegisterPetscDatatypeField(*sw, "E_field", dim, PETSC_REAL)); 1964*918dfc20SMatthew G. Knepley 1965*918dfc20SMatthew G. Knepley const char *fieldnames[2] = {DMSwarmPICField_coor, "velocity"}; 1966*918dfc20SMatthew G. Knepley 1967*918dfc20SMatthew G. Knepley PetscCall(DMSwarmCellDMCreate(dm, 2, fieldnames, 1, fieldnames, &celldm)); 1968*918dfc20SMatthew G. Knepley PetscCall(DMSwarmAddCellDM(*sw, celldm)); 1969*918dfc20SMatthew G. Knepley PetscCall(DMSwarmCellDMDestroy(&celldm)); 1970*918dfc20SMatthew G. Knepley 1971*918dfc20SMatthew G. Knepley const char *vfieldnames[2] = {"w_q"}; 1972*918dfc20SMatthew G. Knepley 1973*918dfc20SMatthew G. Knepley PetscCall(CreateVelocityDM(*sw, &vdm)); 1974*918dfc20SMatthew G. Knepley PetscCall(DMSwarmCellDMCreate(vdm, 1, vfieldnames, 1, &fieldnames[1], &celldm)); 1975*918dfc20SMatthew G. Knepley PetscCall(DMSwarmAddCellDM(*sw, celldm)); 1976*918dfc20SMatthew G. Knepley PetscCall(DMSwarmCellDMDestroy(&celldm)); 1977*918dfc20SMatthew G. Knepley PetscCall(DMDestroy(&vdm)); 1978*918dfc20SMatthew G. Knepley 1979*918dfc20SMatthew G. Knepley DM mdm; 1980*918dfc20SMatthew G. Knepley 1981*918dfc20SMatthew G. Knepley PetscCall(DMClone(dm, &mdm)); 1982*918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)mdm, "moments")); 1983*918dfc20SMatthew G. Knepley PetscCall(DMCopyDisc(dm, mdm)); 1984*918dfc20SMatthew G. Knepley PetscCall(DMSwarmCellDMCreate(mdm, 1, vfieldnames, 1, fieldnames, &celldm)); 1985*918dfc20SMatthew G. Knepley PetscCall(DMDestroy(&mdm)); 1986*918dfc20SMatthew G. Knepley PetscCall(DMSwarmAddCellDM(*sw, celldm)); 1987*918dfc20SMatthew G. Knepley PetscCall(DMSwarmCellDMDestroy(&celldm)); 1988*918dfc20SMatthew G. Knepley 1989*918dfc20SMatthew G. Knepley DM mfdm; 1990*918dfc20SMatthew G. Knepley 1991*918dfc20SMatthew G. Knepley PetscCall(DMClone(dm, &mfdm)); 1992*918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)mfdm, "moment fields")); 1993*918dfc20SMatthew G. Knepley PetscCall(DMCopyDisc(dm, mfdm)); 1994*918dfc20SMatthew G. Knepley PetscCall(DMSwarmCellDMCreate(mfdm, 1, &fieldnames[1], 1, fieldnames, &celldm)); 1995*918dfc20SMatthew G. Knepley PetscCall(DMDestroy(&mfdm)); 1996*918dfc20SMatthew G. Knepley PetscCall(DMSwarmAddCellDM(*sw, celldm)); 1997*918dfc20SMatthew G. Knepley PetscCall(DMSwarmCellDMDestroy(&celldm)); 1998*918dfc20SMatthew G. Knepley 1999*918dfc20SMatthew G. Knepley PetscCall(DMSetFromOptions(*sw)); 2000*918dfc20SMatthew G. Knepley PetscCall(DMSetUp(*sw)); 2001*918dfc20SMatthew G. Knepley 2002*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSetCellDMActive(*sw, "space")); 2003*918dfc20SMatthew G. Knepley user->swarm = *sw; 2004*918dfc20SMatthew G. Knepley // TODO: This is redundant init since it is done in InitializeSolveAndSwarm, however DMSetUp() requires the local size be set 2005*918dfc20SMatthew G. Knepley if (user->perturbed_weights) { 2006*918dfc20SMatthew G. Knepley PetscCall(InitializeParticles_PerturbedWeights(*sw, user)); 2007*918dfc20SMatthew G. Knepley } else { 2008*918dfc20SMatthew G. Knepley PetscCall(DMSwarmComputeLocalSizeFromOptions(*sw)); 2009*918dfc20SMatthew G. Knepley PetscCall(DMSwarmInitializeCoordinates(*sw)); 2010*918dfc20SMatthew G. Knepley PetscCall(DMSwarmInitializeVelocitiesFromOptions(*sw, v0)); 2011*918dfc20SMatthew G. Knepley } 2012*918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)*sw, "Particles")); 2013*918dfc20SMatthew G. Knepley PetscCall(DMViewFromOptions(*sw, NULL, "-sw_view")); 2014*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 2015*918dfc20SMatthew G. Knepley } 2016*918dfc20SMatthew G. Knepley 2017*918dfc20SMatthew G. Knepley static PetscErrorCode ComputeFieldAtParticles_Coulomb(SNES snes, DM sw, PetscReal E[]) 2018*918dfc20SMatthew G. Knepley { 2019*918dfc20SMatthew G. Knepley AppCtx *user; 2020*918dfc20SMatthew G. Knepley PetscReal *coords; 2021*918dfc20SMatthew G. Knepley PetscInt *species, dim, Np, Ns; 2022*918dfc20SMatthew G. Knepley PetscMPIInt size; 2023*918dfc20SMatthew G. Knepley 2024*918dfc20SMatthew G. Knepley PetscFunctionBegin; 2025*918dfc20SMatthew G. Knepley PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)snes), &size)); 2026*918dfc20SMatthew G. Knepley PetscCheck(size == 1, PetscObjectComm((PetscObject)snes), PETSC_ERR_SUP, "Coulomb code only works in serial"); 2027*918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim)); 2028*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(sw, &Np)); 2029*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetNumSpecies(sw, &Ns)); 2030*918dfc20SMatthew G. Knepley PetscCall(DMGetApplicationContext(sw, (void *)&user)); 2031*918dfc20SMatthew G. Knepley 2032*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&coords)); 2033*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "species", NULL, NULL, (void **)&species)); 2034*918dfc20SMatthew G. Knepley for (PetscInt p = 0; p < Np; ++p) { 2035*918dfc20SMatthew G. Knepley PetscReal *pcoord = &coords[p * dim]; 2036*918dfc20SMatthew G. Knepley PetscReal pE[3] = {0., 0., 0.}; 2037*918dfc20SMatthew G. Knepley 2038*918dfc20SMatthew G. Knepley /* Calculate field at particle p due to particle q */ 2039*918dfc20SMatthew G. Knepley for (PetscInt q = 0; q < Np; ++q) { 2040*918dfc20SMatthew G. Knepley PetscReal *qcoord = &coords[q * dim]; 2041*918dfc20SMatthew G. Knepley PetscReal rpq[3], r, r3, q_q; 2042*918dfc20SMatthew G. Knepley 2043*918dfc20SMatthew G. Knepley if (p == q) continue; 2044*918dfc20SMatthew G. Knepley q_q = user->charges[species[q]] * 1.; 2045*918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) rpq[d] = pcoord[d] - qcoord[d]; 2046*918dfc20SMatthew G. Knepley r = DMPlex_NormD_Internal(dim, rpq); 2047*918dfc20SMatthew G. Knepley if (r < PETSC_SQRT_MACHINE_EPSILON) continue; 2048*918dfc20SMatthew G. Knepley r3 = PetscPowRealInt(r, 3); 2049*918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) pE[d] += q_q * rpq[d] / r3; 2050*918dfc20SMatthew G. Knepley } 2051*918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) E[p * dim + d] = pE[d]; 2052*918dfc20SMatthew G. Knepley } 2053*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "species", NULL, NULL, (void **)&species)); 2054*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&coords)); 2055*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 2056*918dfc20SMatthew G. Knepley } 2057*918dfc20SMatthew G. Knepley 2058*918dfc20SMatthew G. Knepley static PetscErrorCode ComputeFieldAtParticles_Primal(SNES snes, DM sw, Mat M_p, PetscReal E[]) 2059*918dfc20SMatthew G. Knepley { 2060*918dfc20SMatthew G. Knepley DM dm; 2061*918dfc20SMatthew G. Knepley AppCtx *user; 2062*918dfc20SMatthew G. Knepley PetscDS ds; 2063*918dfc20SMatthew G. Knepley PetscFE fe; 2064*918dfc20SMatthew G. Knepley KSP ksp; 2065*918dfc20SMatthew G. Knepley Vec rhoRhs; // Weak charge density, \int phi_i rho 2066*918dfc20SMatthew G. Knepley Vec rho; // Charge density, M^{-1} rhoRhs 2067*918dfc20SMatthew G. Knepley Vec phi, locPhi; // Potential 2068*918dfc20SMatthew G. Knepley Vec f; // Particle weights 2069*918dfc20SMatthew G. Knepley PetscReal *coords; 2070*918dfc20SMatthew G. Knepley PetscInt dim, cStart, cEnd, Np; 2071*918dfc20SMatthew G. Knepley 2072*918dfc20SMatthew G. Knepley PetscFunctionBegin; 2073*918dfc20SMatthew G. Knepley PetscCall(DMGetApplicationContext(sw, (void *)&user)); 2074*918dfc20SMatthew G. Knepley PetscCall(PetscLogEventBegin(user->ESolveEvent, snes, sw, 0, 0)); 2075*918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim)); 2076*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(sw, &Np)); 2077*918dfc20SMatthew G. Knepley 2078*918dfc20SMatthew G. Knepley PetscCall(SNESGetDM(snes, &dm)); 2079*918dfc20SMatthew G. Knepley PetscCall(DMGetGlobalVector(dm, &rhoRhs)); 2080*918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)rhoRhs, "Weak charge density")); 2081*918dfc20SMatthew G. Knepley PetscCall(DMGetNamedGlobalVector(user->dmPot, "rho", &rho)); 2082*918dfc20SMatthew G. Knepley PetscCall(DMSwarmCreateGlobalVectorFromField(sw, "w_q", &f)); 2083*918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)f, "particle weight")); 2084*918dfc20SMatthew G. Knepley 2085*918dfc20SMatthew G. Knepley PetscCall(MatViewFromOptions(M_p, NULL, "-mp_view")); 2086*918dfc20SMatthew G. Knepley PetscCall(MatViewFromOptions(user->M, NULL, "-m_view")); 2087*918dfc20SMatthew G. Knepley PetscCall(VecViewFromOptions(f, NULL, "-weights_view")); 2088*918dfc20SMatthew G. Knepley 2089*918dfc20SMatthew G. Knepley PetscCall(MatMultTranspose(M_p, f, rhoRhs)); 2090*918dfc20SMatthew G. Knepley PetscCall(DMSwarmDestroyGlobalVectorFromField(sw, "w_q", &f)); 2091*918dfc20SMatthew G. Knepley 2092*918dfc20SMatthew G. Knepley PetscCall(KSPCreate(PetscObjectComm((PetscObject)dm), &ksp)); 2093*918dfc20SMatthew G. Knepley PetscCall(KSPSetOptionsPrefix(ksp, "em_proj_")); 2094*918dfc20SMatthew G. Knepley PetscCall(KSPSetOperators(ksp, user->M, user->M)); 2095*918dfc20SMatthew G. Knepley PetscCall(KSPSetFromOptions(ksp)); 2096*918dfc20SMatthew G. Knepley PetscCall(KSPSolve(ksp, rhoRhs, rho)); 2097*918dfc20SMatthew G. Knepley 2098*918dfc20SMatthew G. Knepley PetscCall(VecScale(rhoRhs, -1.0)); 2099*918dfc20SMatthew G. Knepley 2100*918dfc20SMatthew G. Knepley PetscCall(VecViewFromOptions(rhoRhs, NULL, "-rho_view")); 2101*918dfc20SMatthew G. Knepley PetscCall(DMRestoreNamedGlobalVector(user->dmPot, "rho", &rho)); 2102*918dfc20SMatthew G. Knepley PetscCall(KSPDestroy(&ksp)); 2103*918dfc20SMatthew G. Knepley 2104*918dfc20SMatthew G. Knepley PetscCall(DMGetNamedGlobalVector(user->dmPot, "phi", &phi)); 2105*918dfc20SMatthew G. Knepley PetscCall(VecSet(phi, 0.0)); 2106*918dfc20SMatthew G. Knepley PetscCall(SNESSolve(snes, rhoRhs, phi)); 2107*918dfc20SMatthew G. Knepley PetscCall(DMRestoreGlobalVector(dm, &rhoRhs)); 2108*918dfc20SMatthew G. Knepley PetscCall(VecViewFromOptions(phi, NULL, "-phi_view")); 2109*918dfc20SMatthew G. Knepley 2110*918dfc20SMatthew G. Knepley PetscCall(DMGetLocalVector(dm, &locPhi)); 2111*918dfc20SMatthew G. Knepley PetscCall(DMGlobalToLocalBegin(dm, phi, INSERT_VALUES, locPhi)); 2112*918dfc20SMatthew G. Knepley PetscCall(DMGlobalToLocalEnd(dm, phi, INSERT_VALUES, locPhi)); 2113*918dfc20SMatthew G. Knepley PetscCall(DMRestoreNamedGlobalVector(user->dmPot, "phi", &phi)); 2114*918dfc20SMatthew G. Knepley PetscCall(PetscLogEventEnd(user->ESolveEvent, snes, sw, 0, 0)); 2115*918dfc20SMatthew G. Knepley 2116*918dfc20SMatthew G. Knepley PetscCall(DMGetDS(dm, &ds)); 2117*918dfc20SMatthew G. Knepley PetscCall(PetscDSGetDiscretization(ds, 0, (PetscObject *)&fe)); 2118*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortGetAccess(sw)); 2119*918dfc20SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 2120*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&coords)); 2121*918dfc20SMatthew G. Knepley 2122*918dfc20SMatthew G. Knepley PetscCall(PetscLogEventBegin(user->ETabEvent, snes, sw, 0, 0)); 2123*918dfc20SMatthew G. Knepley PetscTabulation tab; 2124*918dfc20SMatthew G. Knepley PetscReal *pcoord, *refcoord; 2125*918dfc20SMatthew G. Knepley PetscFEGeom *chunkgeom = NULL; 2126*918dfc20SMatthew G. Knepley PetscInt maxNcp = 0; 2127*918dfc20SMatthew G. Knepley 2128*918dfc20SMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) { 2129*918dfc20SMatthew G. Knepley PetscInt Ncp; 2130*918dfc20SMatthew G. Knepley 2131*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortGetNumberOfPointsPerCell(sw, c, &Ncp)); 2132*918dfc20SMatthew G. Knepley maxNcp = PetscMax(maxNcp, Ncp); 2133*918dfc20SMatthew G. Knepley } 2134*918dfc20SMatthew G. Knepley PetscCall(DMGetWorkArray(dm, maxNcp * dim, MPIU_REAL, &refcoord)); 2135*918dfc20SMatthew G. Knepley PetscCall(DMGetWorkArray(dm, maxNcp * dim, MPIU_REAL, &pcoord)); 2136*918dfc20SMatthew G. Knepley // This can raise an FP_INEXACT in the dgemm inside 2137*918dfc20SMatthew G. Knepley PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 2138*918dfc20SMatthew G. Knepley PetscCall(PetscFECreateTabulation(fe, 1, maxNcp, refcoord, 1, &tab)); 2139*918dfc20SMatthew G. Knepley PetscCall(PetscFPTrapPop()); 2140*918dfc20SMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) { 2141*918dfc20SMatthew G. Knepley PetscScalar *clPhi = NULL; 2142*918dfc20SMatthew G. Knepley PetscInt *points; 2143*918dfc20SMatthew G. Knepley PetscInt Ncp; 2144*918dfc20SMatthew G. Knepley 2145*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortGetPointsPerCell(sw, c, &Ncp, &points)); 2146*918dfc20SMatthew G. Knepley for (PetscInt cp = 0; cp < Ncp; ++cp) 2147*918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) pcoord[cp * dim + d] = coords[points[cp] * dim + d]; 2148*918dfc20SMatthew G. Knepley { 2149*918dfc20SMatthew G. Knepley PetscCall(PetscFEGeomGetChunk(user->fegeom, c - cStart, c - cStart + 1, &chunkgeom)); 2150*918dfc20SMatthew G. Knepley for (PetscInt i = 0; i < Ncp; ++i) { 2151*918dfc20SMatthew G. Knepley const PetscReal x0[3] = {-1., -1., -1.}; 2152*918dfc20SMatthew G. Knepley CoordinatesRealToRef(dim, dim, x0, chunkgeom->v, chunkgeom->invJ, &pcoord[dim * i], &refcoord[dim * i]); 2153*918dfc20SMatthew G. Knepley } 2154*918dfc20SMatthew G. Knepley } 2155*918dfc20SMatthew G. Knepley PetscCall(PetscFEComputeTabulation(fe, Ncp, refcoord, 1, tab)); 2156*918dfc20SMatthew G. Knepley PetscCall(DMPlexVecGetClosure(dm, NULL, locPhi, c, NULL, &clPhi)); 2157*918dfc20SMatthew G. Knepley for (PetscInt cp = 0; cp < Ncp; ++cp) { 2158*918dfc20SMatthew G. Knepley const PetscReal *basisDer = tab->T[1]; 2159*918dfc20SMatthew G. Knepley const PetscInt p = points[cp]; 2160*918dfc20SMatthew G. Knepley 2161*918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) E[p * dim + d] = 0.; 2162*918dfc20SMatthew G. Knepley PetscCall(PetscFEFreeInterpolateGradient_Static(fe, basisDer, clPhi, dim, chunkgeom->invJ, NULL, cp, &E[p * dim])); 2163*918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) E[p * dim + d] *= -1.0; 2164*918dfc20SMatthew G. Knepley } 2165*918dfc20SMatthew G. Knepley PetscCall(DMPlexVecRestoreClosure(dm, NULL, locPhi, c, NULL, &clPhi)); 2166*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(sw, c, &Ncp, &points)); 2167*918dfc20SMatthew G. Knepley } 2168*918dfc20SMatthew G. Knepley PetscCall(DMRestoreWorkArray(dm, maxNcp * dim, MPIU_REAL, &pcoord)); 2169*918dfc20SMatthew G. Knepley PetscCall(DMRestoreWorkArray(dm, maxNcp * dim, MPIU_REAL, &refcoord)); 2170*918dfc20SMatthew G. Knepley PetscCall(PetscTabulationDestroy(&tab)); 2171*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&coords)); 2172*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortRestoreAccess(sw)); 2173*918dfc20SMatthew G. Knepley PetscCall(DMRestoreLocalVector(dm, &locPhi)); 2174*918dfc20SMatthew G. Knepley PetscCall(PetscFEGeomRestoreChunk(user->fegeom, 0, 1, &chunkgeom)); 2175*918dfc20SMatthew G. Knepley PetscCall(PetscLogEventEnd(user->ETabEvent, snes, sw, 0, 0)); 2176*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 2177*918dfc20SMatthew G. Knepley } 2178*918dfc20SMatthew G. Knepley 2179*918dfc20SMatthew G. Knepley static PetscErrorCode ComputeFieldAtParticles_Mixed(SNES snes, DM sw, Mat M_p, PetscReal E[]) 2180*918dfc20SMatthew G. Knepley { 2181*918dfc20SMatthew G. Knepley DM dm; 2182*918dfc20SMatthew G. Knepley AppCtx *user; 2183*918dfc20SMatthew G. Knepley PetscDS ds; 2184*918dfc20SMatthew G. Knepley PetscFE fe; 2185*918dfc20SMatthew G. Knepley KSP ksp; 2186*918dfc20SMatthew G. Knepley Vec rhoRhs, rhoRhsFull; // Weak charge density, \int phi_i rho, and embedding in mixed problem 2187*918dfc20SMatthew G. Knepley Vec rho; // Charge density, M^{-1} rhoRhs 2188*918dfc20SMatthew G. Knepley Vec phi, locPhi, phiFull; // Potential and embedding in mixed problem 2189*918dfc20SMatthew G. Knepley Vec f; // Particle weights 2190*918dfc20SMatthew G. Knepley PetscReal *coords; 2191*918dfc20SMatthew G. Knepley PetscInt dim, cStart, cEnd, Np; 2192*918dfc20SMatthew G. Knepley 2193*918dfc20SMatthew G. Knepley PetscFunctionBegin; 2194*918dfc20SMatthew G. Knepley PetscCall(DMGetApplicationContext(sw, &user)); 2195*918dfc20SMatthew G. Knepley PetscCall(PetscLogEventBegin(user->ESolveEvent, snes, sw, 0, 0)); 2196*918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim)); 2197*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(sw, &Np)); 2198*918dfc20SMatthew G. Knepley 2199*918dfc20SMatthew G. Knepley PetscCall(SNESGetDM(snes, &dm)); 2200*918dfc20SMatthew G. Knepley PetscCall(DMGetGlobalVector(user->dmPot, &rhoRhs)); 2201*918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)rhoRhs, "Weak charge density")); 2202*918dfc20SMatthew G. Knepley PetscCall(DMGetGlobalVector(dm, &rhoRhsFull)); 2203*918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)rhoRhsFull, "Weak charge density")); 2204*918dfc20SMatthew G. Knepley PetscCall(DMGetNamedGlobalVector(user->dmPot, "rho", &rho)); 2205*918dfc20SMatthew G. Knepley PetscCall(DMSwarmCreateGlobalVectorFromField(sw, "w_q", &f)); 2206*918dfc20SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)f, "particle weight")); 2207*918dfc20SMatthew G. Knepley 2208*918dfc20SMatthew G. Knepley PetscCall(MatViewFromOptions(M_p, NULL, "-mp_view")); 2209*918dfc20SMatthew G. Knepley PetscCall(MatViewFromOptions(user->M, NULL, "-m_view")); 2210*918dfc20SMatthew G. Knepley PetscCall(VecViewFromOptions(f, NULL, "-weights_view")); 2211*918dfc20SMatthew G. Knepley 2212*918dfc20SMatthew G. Knepley PetscCall(MatMultTranspose(M_p, f, rhoRhs)); 2213*918dfc20SMatthew G. Knepley PetscCall(DMSwarmDestroyGlobalVectorFromField(sw, "w_q", &f)); 2214*918dfc20SMatthew G. Knepley 2215*918dfc20SMatthew G. Knepley PetscCall(KSPCreate(PetscObjectComm((PetscObject)dm), &ksp)); 2216*918dfc20SMatthew G. Knepley PetscCall(KSPSetOptionsPrefix(ksp, "em_proj")); 2217*918dfc20SMatthew G. Knepley PetscCall(KSPSetOperators(ksp, user->M, user->M)); 2218*918dfc20SMatthew G. Knepley PetscCall(KSPSetFromOptions(ksp)); 2219*918dfc20SMatthew G. Knepley PetscCall(KSPSolve(ksp, rhoRhs, rho)); 2220*918dfc20SMatthew G. Knepley 2221*918dfc20SMatthew G. Knepley PetscCall(VecISCopy(rhoRhsFull, user->isPot, SCATTER_FORWARD, rhoRhs)); 2222*918dfc20SMatthew G. Knepley //PetscCall(VecScale(rhoRhsFull, -1.0)); 2223*918dfc20SMatthew G. Knepley 2224*918dfc20SMatthew G. Knepley PetscCall(VecViewFromOptions(rhoRhs, NULL, "-rho_view")); 2225*918dfc20SMatthew G. Knepley PetscCall(VecViewFromOptions(rhoRhsFull, NULL, "-rho_full_view")); 2226*918dfc20SMatthew G. Knepley PetscCall(DMRestoreNamedGlobalVector(user->dmPot, "rho", &rho)); 2227*918dfc20SMatthew G. Knepley PetscCall(DMRestoreGlobalVector(user->dmPot, &rhoRhs)); 2228*918dfc20SMatthew G. Knepley PetscCall(KSPDestroy(&ksp)); 2229*918dfc20SMatthew G. Knepley 2230*918dfc20SMatthew G. Knepley PetscCall(DMGetGlobalVector(dm, &phiFull)); 2231*918dfc20SMatthew G. Knepley PetscCall(DMGetNamedGlobalVector(user->dmPot, "phi", &phi)); 2232*918dfc20SMatthew G. Knepley PetscCall(VecSet(phiFull, 0.0)); 2233*918dfc20SMatthew G. Knepley PetscCall(SNESSolve(snes, rhoRhsFull, phiFull)); 2234*918dfc20SMatthew G. Knepley PetscCall(DMRestoreGlobalVector(dm, &rhoRhsFull)); 2235*918dfc20SMatthew G. Knepley PetscCall(VecViewFromOptions(phi, NULL, "-phi_view")); 2236*918dfc20SMatthew G. Knepley 2237*918dfc20SMatthew G. Knepley PetscCall(VecISCopy(phiFull, user->isPot, SCATTER_REVERSE, phi)); 2238*918dfc20SMatthew G. Knepley PetscCall(DMRestoreNamedGlobalVector(user->dmPot, "phi", &phi)); 2239*918dfc20SMatthew G. Knepley 2240*918dfc20SMatthew G. Knepley PetscCall(DMGetLocalVector(dm, &locPhi)); 2241*918dfc20SMatthew G. Knepley PetscCall(DMGlobalToLocalBegin(dm, phiFull, INSERT_VALUES, locPhi)); 2242*918dfc20SMatthew G. Knepley PetscCall(DMGlobalToLocalEnd(dm, phiFull, INSERT_VALUES, locPhi)); 2243*918dfc20SMatthew G. Knepley PetscCall(DMRestoreGlobalVector(dm, &phiFull)); 2244*918dfc20SMatthew G. Knepley PetscCall(PetscLogEventEnd(user->ESolveEvent, snes, sw, 0, 0)); 2245*918dfc20SMatthew G. Knepley 2246*918dfc20SMatthew G. Knepley PetscCall(DMGetDS(dm, &ds)); 2247*918dfc20SMatthew G. Knepley PetscCall(PetscDSGetDiscretization(ds, 0, (PetscObject *)&fe)); 2248*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortGetAccess(sw)); 2249*918dfc20SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 2250*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&coords)); 2251*918dfc20SMatthew G. Knepley 2252*918dfc20SMatthew G. Knepley PetscCall(PetscLogEventBegin(user->ETabEvent, snes, sw, 0, 0)); 2253*918dfc20SMatthew G. Knepley PetscTabulation tab; 2254*918dfc20SMatthew G. Knepley PetscReal *pcoord, *refcoord; 2255*918dfc20SMatthew G. Knepley PetscFEGeom *chunkgeom = NULL; 2256*918dfc20SMatthew G. Knepley PetscInt maxNcp = 0; 2257*918dfc20SMatthew G. Knepley 2258*918dfc20SMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) { 2259*918dfc20SMatthew G. Knepley PetscInt Ncp; 2260*918dfc20SMatthew G. Knepley 2261*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortGetNumberOfPointsPerCell(sw, c, &Ncp)); 2262*918dfc20SMatthew G. Knepley maxNcp = PetscMax(maxNcp, Ncp); 2263*918dfc20SMatthew G. Knepley } 2264*918dfc20SMatthew G. Knepley PetscCall(DMGetWorkArray(dm, maxNcp * dim, MPIU_REAL, &refcoord)); 2265*918dfc20SMatthew G. Knepley PetscCall(DMGetWorkArray(dm, maxNcp * dim, MPIU_REAL, &pcoord)); 2266*918dfc20SMatthew G. Knepley PetscCall(PetscFECreateTabulation(fe, 1, maxNcp, refcoord, 1, &tab)); 2267*918dfc20SMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) { 2268*918dfc20SMatthew G. Knepley PetscScalar *clPhi = NULL; 2269*918dfc20SMatthew G. Knepley PetscInt *points; 2270*918dfc20SMatthew G. Knepley PetscInt Ncp; 2271*918dfc20SMatthew G. Knepley 2272*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortGetPointsPerCell(sw, c, &Ncp, &points)); 2273*918dfc20SMatthew G. Knepley for (PetscInt cp = 0; cp < Ncp; ++cp) 2274*918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) pcoord[cp * dim + d] = coords[points[cp] * dim + d]; 2275*918dfc20SMatthew G. Knepley { 2276*918dfc20SMatthew G. Knepley PetscCall(PetscFEGeomGetChunk(user->fegeom, c - cStart, c - cStart + 1, &chunkgeom)); 2277*918dfc20SMatthew G. Knepley for (PetscInt i = 0; i < Ncp; ++i) { 2278*918dfc20SMatthew G. Knepley const PetscReal x0[3] = {-1., -1., -1.}; 2279*918dfc20SMatthew G. Knepley CoordinatesRealToRef(dim, dim, x0, chunkgeom->v, chunkgeom->invJ, &pcoord[dim * i], &refcoord[dim * i]); 2280*918dfc20SMatthew G. Knepley } 2281*918dfc20SMatthew G. Knepley } 2282*918dfc20SMatthew G. Knepley PetscCall(PetscFEComputeTabulation(fe, Ncp, refcoord, 1, tab)); 2283*918dfc20SMatthew G. Knepley PetscCall(DMPlexVecGetClosure(dm, NULL, locPhi, c, NULL, &clPhi)); 2284*918dfc20SMatthew G. Knepley for (PetscInt cp = 0; cp < Ncp; ++cp) { 2285*918dfc20SMatthew G. Knepley const PetscInt p = points[cp]; 2286*918dfc20SMatthew G. Knepley 2287*918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) E[p * dim + d] = 0.; 2288*918dfc20SMatthew G. Knepley PetscCall(PetscFEInterpolateAtPoints_Static(fe, tab, clPhi, chunkgeom, cp, &E[p * dim])); 2289*918dfc20SMatthew G. Knepley PetscCall(PetscFEPushforward(fe, chunkgeom, 1, &E[p * dim])); 2290*918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) E[p * dim + d] *= -1.0; 2291*918dfc20SMatthew G. Knepley } 2292*918dfc20SMatthew G. Knepley PetscCall(DMPlexVecRestoreClosure(dm, NULL, locPhi, c, NULL, &clPhi)); 2293*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(sw, c, &Ncp, &points)); 2294*918dfc20SMatthew G. Knepley } 2295*918dfc20SMatthew G. Knepley PetscCall(DMRestoreWorkArray(dm, maxNcp * dim, MPIU_REAL, &pcoord)); 2296*918dfc20SMatthew G. Knepley PetscCall(DMRestoreWorkArray(dm, maxNcp * dim, MPIU_REAL, &refcoord)); 2297*918dfc20SMatthew G. Knepley PetscCall(PetscTabulationDestroy(&tab)); 2298*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&coords)); 2299*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSortRestoreAccess(sw)); 2300*918dfc20SMatthew G. Knepley PetscCall(DMRestoreLocalVector(dm, &locPhi)); 2301*918dfc20SMatthew G. Knepley PetscCall(PetscFEGeomRestoreChunk(user->fegeom, 0, 1, &chunkgeom)); 2302*918dfc20SMatthew G. Knepley PetscCall(PetscLogEventEnd(user->ETabEvent, snes, sw, 0, 0)); 2303*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 2304*918dfc20SMatthew G. Knepley } 2305*918dfc20SMatthew G. Knepley 2306*918dfc20SMatthew G. Knepley static PetscErrorCode ComputeFieldAtParticles(SNES snes, DM sw) 2307*918dfc20SMatthew G. Knepley { 2308*918dfc20SMatthew G. Knepley AppCtx *user; 2309*918dfc20SMatthew G. Knepley Mat M_p; 2310*918dfc20SMatthew G. Knepley PetscReal *E; 2311*918dfc20SMatthew G. Knepley PetscInt dim, Np; 2312*918dfc20SMatthew G. Knepley 2313*918dfc20SMatthew G. Knepley PetscFunctionBegin; 2314*918dfc20SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2315*918dfc20SMatthew G. Knepley PetscValidHeaderSpecific(sw, DM_CLASSID, 2); 2316*918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim)); 2317*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(sw, &Np)); 2318*918dfc20SMatthew G. Knepley PetscCall(DMGetApplicationContext(sw, &user)); 2319*918dfc20SMatthew G. Knepley 2320*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSetCellDMActive(sw, "moments")); 2321*918dfc20SMatthew G. Knepley // TODO: Could share sort context with space cellDM 2322*918dfc20SMatthew G. Knepley PetscCall(DMSwarmMigrate(sw, PETSC_FALSE)); 2323*918dfc20SMatthew G. Knepley PetscCall(DMCreateMassMatrix(sw, user->dmPot, &M_p)); 2324*918dfc20SMatthew G. Knepley PetscCall(DMSwarmSetCellDMActive(sw, "space")); 2325*918dfc20SMatthew G. Knepley 2326*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "E_field", NULL, NULL, (void **)&E)); 2327*918dfc20SMatthew G. Knepley PetscCall(PetscArrayzero(E, Np * dim)); 2328*918dfc20SMatthew G. Knepley user->validE = PETSC_TRUE; 2329*918dfc20SMatthew G. Knepley 2330*918dfc20SMatthew G. Knepley switch (user->em) { 2331*918dfc20SMatthew G. Knepley case EM_COULOMB: 2332*918dfc20SMatthew G. Knepley PetscCall(ComputeFieldAtParticles_Coulomb(snes, sw, E)); 2333*918dfc20SMatthew G. Knepley break; 2334*918dfc20SMatthew G. Knepley case EMPRIMAL: 2335*918dfc20SMatthew G. Knepley PetscCall(ComputeFieldAtParticles_Primal(snes, sw, M_p, E)); 2336*918dfc20SMatthew G. Knepley break; 2337*918dfc20SMatthew G. Knepley case EM_MIXED: 2338*918dfc20SMatthew G. Knepley PetscCall(ComputeFieldAtParticles_Mixed(snes, sw, M_p, E)); 2339*918dfc20SMatthew G. Knepley break; 2340*918dfc20SMatthew G. Knepley case EMNONE: 2341*918dfc20SMatthew G. Knepley break; 2342*918dfc20SMatthew G. Knepley default: 2343*918dfc20SMatthew G. Knepley SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No solver for electrostatic model %s", EMTypes[user->em]); 2344*918dfc20SMatthew G. Knepley } 2345*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "E_field", NULL, NULL, (void **)&E)); 2346*918dfc20SMatthew G. Knepley PetscCall(MatDestroy(&M_p)); 2347*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 2348*918dfc20SMatthew G. Knepley } 2349*918dfc20SMatthew G. Knepley 2350*918dfc20SMatthew G. Knepley static PetscErrorCode RHSFunction(TS ts, PetscReal t, Vec U, Vec G, void *ctx) 2351*918dfc20SMatthew G. Knepley { 2352*918dfc20SMatthew G. Knepley DM sw; 2353*918dfc20SMatthew G. Knepley SNES snes = ((AppCtx *)ctx)->snes; 2354*918dfc20SMatthew G. Knepley const PetscScalar *u; 2355*918dfc20SMatthew G. Knepley PetscScalar *g; 2356*918dfc20SMatthew G. Knepley PetscReal *E, m_p = 1., q_p = -1.; 2357*918dfc20SMatthew G. Knepley PetscInt dim, d, Np, p; 2358*918dfc20SMatthew G. Knepley 2359*918dfc20SMatthew G. Knepley PetscFunctionBeginUser; 2360*918dfc20SMatthew G. Knepley PetscCall(TSGetDM(ts, &sw)); 2361*918dfc20SMatthew G. Knepley PetscCall(ComputeFieldAtParticles(snes, sw)); 2362*918dfc20SMatthew G. Knepley 2363*918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim)); 2364*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(sw, &Np)); 2365*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "E_field", NULL, NULL, (void **)&E)); 2366*918dfc20SMatthew G. Knepley PetscCall(VecGetArrayRead(U, &u)); 2367*918dfc20SMatthew G. Knepley PetscCall(VecGetArray(G, &g)); 2368*918dfc20SMatthew G. Knepley Np /= 2 * dim; 2369*918dfc20SMatthew G. Knepley for (p = 0; p < Np; ++p) { 2370*918dfc20SMatthew G. Knepley for (d = 0; d < dim; ++d) { 2371*918dfc20SMatthew G. Knepley g[(p * 2 + 0) * dim + d] = u[(p * 2 + 1) * dim + d]; 2372*918dfc20SMatthew G. Knepley g[(p * 2 + 1) * dim + d] = q_p * E[p * dim + d] / m_p; 2373*918dfc20SMatthew G. Knepley } 2374*918dfc20SMatthew G. Knepley } 2375*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "E_field", NULL, NULL, (void **)&E)); 2376*918dfc20SMatthew G. Knepley PetscCall(VecRestoreArrayRead(U, &u)); 2377*918dfc20SMatthew G. Knepley PetscCall(VecRestoreArray(G, &g)); 2378*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 2379*918dfc20SMatthew G. Knepley } 2380*918dfc20SMatthew G. Knepley 2381*918dfc20SMatthew G. Knepley /* J_{ij} = dF_i/dx_j 2382*918dfc20SMatthew G. Knepley J_p = ( 0 1) 2383*918dfc20SMatthew G. Knepley (-w^2 0) 2384*918dfc20SMatthew G. Knepley TODO Now there is another term with w^2 from the electric field. I think we will need to invert the operator. 2385*918dfc20SMatthew G. Knepley Perhaps we can approximate the Jacobian using only the cellwise P-P gradient from Coulomb 2386*918dfc20SMatthew G. Knepley */ 2387*918dfc20SMatthew G. Knepley static PetscErrorCode RHSJacobian(TS ts, PetscReal t, Vec U, Mat J, Mat P, void *ctx) 2388*918dfc20SMatthew G. Knepley { 2389*918dfc20SMatthew G. Knepley DM sw; 2390*918dfc20SMatthew G. Knepley const PetscReal *coords, *vel; 2391*918dfc20SMatthew G. Knepley PetscInt dim, d, Np, p, rStart; 2392*918dfc20SMatthew G. Knepley 2393*918dfc20SMatthew G. Knepley PetscFunctionBeginUser; 2394*918dfc20SMatthew G. Knepley PetscCall(TSGetDM(ts, &sw)); 2395*918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim)); 2396*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(sw, &Np)); 2397*918dfc20SMatthew G. Knepley PetscCall(MatGetOwnershipRange(J, &rStart, NULL)); 2398*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&coords)); 2399*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "velocity", NULL, NULL, (void **)&vel)); 2400*918dfc20SMatthew G. Knepley Np /= 2 * dim; 2401*918dfc20SMatthew G. Knepley for (p = 0; p < Np; ++p) { 2402*918dfc20SMatthew G. Knepley const PetscReal x0 = coords[p * dim + 0]; 2403*918dfc20SMatthew G. Knepley const PetscReal vy0 = vel[p * dim + 1]; 2404*918dfc20SMatthew G. Knepley const PetscReal omega = vy0 / x0; 2405*918dfc20SMatthew G. Knepley PetscScalar vals[4] = {0., 1., -PetscSqr(omega), 0.}; 2406*918dfc20SMatthew G. Knepley 2407*918dfc20SMatthew G. Knepley for (d = 0; d < dim; ++d) { 2408*918dfc20SMatthew G. Knepley const PetscInt rows[2] = {(p * 2 + 0) * dim + d + rStart, (p * 2 + 1) * dim + d + rStart}; 2409*918dfc20SMatthew G. Knepley PetscCall(MatSetValues(J, 2, rows, 2, rows, vals, INSERT_VALUES)); 2410*918dfc20SMatthew G. Knepley } 2411*918dfc20SMatthew G. Knepley } 2412*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&coords)); 2413*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "velocity", NULL, NULL, (void **)&vel)); 2414*918dfc20SMatthew G. Knepley PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 2415*918dfc20SMatthew G. Knepley PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 2416*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 2417*918dfc20SMatthew G. Knepley } 2418*918dfc20SMatthew G. Knepley 2419*918dfc20SMatthew G. Knepley static PetscErrorCode RHSFunctionX(TS ts, PetscReal t, Vec V, Vec Xres, void *ctx) 2420*918dfc20SMatthew G. Knepley { 2421*918dfc20SMatthew G. Knepley AppCtx *user = (AppCtx *)ctx; 2422*918dfc20SMatthew G. Knepley DM sw; 2423*918dfc20SMatthew G. Knepley const PetscScalar *v; 2424*918dfc20SMatthew G. Knepley PetscScalar *xres; 2425*918dfc20SMatthew G. Knepley PetscInt Np, p, d, dim; 2426*918dfc20SMatthew G. Knepley 2427*918dfc20SMatthew G. Knepley PetscFunctionBeginUser; 2428*918dfc20SMatthew G. Knepley PetscCall(PetscLogEventBegin(user->RhsXEvent, ts, 0, 0, 0)); 2429*918dfc20SMatthew G. Knepley PetscCall(TSGetDM(ts, &sw)); 2430*918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim)); 2431*918dfc20SMatthew G. Knepley PetscCall(VecGetLocalSize(Xres, &Np)); 2432*918dfc20SMatthew G. Knepley PetscCall(VecGetArrayRead(V, &v)); 2433*918dfc20SMatthew G. Knepley PetscCall(VecGetArray(Xres, &xres)); 2434*918dfc20SMatthew G. Knepley Np /= dim; 2435*918dfc20SMatthew G. Knepley for (p = 0; p < Np; ++p) { 2436*918dfc20SMatthew G. Knepley for (d = 0; d < dim; ++d) xres[p * dim + d] = v[p * dim + d]; 2437*918dfc20SMatthew G. Knepley } 2438*918dfc20SMatthew G. Knepley PetscCall(VecRestoreArrayRead(V, &v)); 2439*918dfc20SMatthew G. Knepley PetscCall(VecRestoreArray(Xres, &xres)); 2440*918dfc20SMatthew G. Knepley PetscCall(PetscLogEventEnd(user->RhsXEvent, ts, 0, 0, 0)); 2441*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 2442*918dfc20SMatthew G. Knepley } 2443*918dfc20SMatthew G. Knepley 2444*918dfc20SMatthew G. Knepley static PetscErrorCode RHSFunctionV(TS ts, PetscReal t, Vec X, Vec Vres, void *ctx) 2445*918dfc20SMatthew G. Knepley { 2446*918dfc20SMatthew G. Knepley DM sw; 2447*918dfc20SMatthew G. Knepley AppCtx *user = (AppCtx *)ctx; 2448*918dfc20SMatthew G. Knepley SNES snes = ((AppCtx *)ctx)->snes; 2449*918dfc20SMatthew G. Knepley const PetscScalar *x; 2450*918dfc20SMatthew G. Knepley PetscScalar *vres; 2451*918dfc20SMatthew G. Knepley PetscReal *E, m_p, q_p; 2452*918dfc20SMatthew G. Knepley PetscInt Np, p, dim, d; 2453*918dfc20SMatthew G. Knepley Parameter *param; 2454*918dfc20SMatthew G. Knepley 2455*918dfc20SMatthew G. Knepley PetscFunctionBeginUser; 2456*918dfc20SMatthew G. Knepley PetscCall(PetscLogEventBegin(user->RhsVEvent, ts, 0, 0, 0)); 2457*918dfc20SMatthew G. Knepley PetscCall(TSGetDM(ts, &sw)); 2458*918dfc20SMatthew G. Knepley PetscCall(ComputeFieldAtParticles(snes, sw)); 2459*918dfc20SMatthew G. Knepley 2460*918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim)); 2461*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "E_field", NULL, NULL, (void **)&E)); 2462*918dfc20SMatthew G. Knepley PetscCall(PetscBagGetData(user->bag, (void **)¶m)); 2463*918dfc20SMatthew G. Knepley m_p = user->masses[0] * param->m0; 2464*918dfc20SMatthew G. Knepley q_p = user->charges[0] * param->q0; 2465*918dfc20SMatthew G. Knepley PetscCall(VecGetLocalSize(Vres, &Np)); 2466*918dfc20SMatthew G. Knepley PetscCall(VecGetArrayRead(X, &x)); 2467*918dfc20SMatthew G. Knepley PetscCall(VecGetArray(Vres, &vres)); 2468*918dfc20SMatthew G. Knepley Np /= dim; 2469*918dfc20SMatthew G. Knepley for (p = 0; p < Np; ++p) { 2470*918dfc20SMatthew G. Knepley for (d = 0; d < dim; ++d) vres[p * dim + d] = q_p * E[p * dim + d] / m_p; 2471*918dfc20SMatthew G. Knepley } 2472*918dfc20SMatthew G. Knepley PetscCall(VecRestoreArrayRead(X, &x)); 2473*918dfc20SMatthew G. Knepley /* 2474*918dfc20SMatthew G. Knepley Synchronized, ordered output for parallel/sequential test cases. 2475*918dfc20SMatthew G. Knepley In the 1D (on the 2D mesh) case, every y component should be zero. 2476*918dfc20SMatthew G. Knepley */ 2477*918dfc20SMatthew G. Knepley if (user->checkVRes) { 2478*918dfc20SMatthew G. Knepley PetscBool pr = user->checkVRes > 1 ? PETSC_TRUE : PETSC_FALSE; 2479*918dfc20SMatthew G. Knepley PetscInt step; 2480*918dfc20SMatthew G. Knepley 2481*918dfc20SMatthew G. Knepley PetscCall(TSGetStepNumber(ts, &step)); 2482*918dfc20SMatthew G. Knepley if (pr) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "step: %" PetscInt_FMT "\n", step)); 2483*918dfc20SMatthew G. Knepley for (PetscInt p = 0; p < Np; ++p) { 2484*918dfc20SMatthew 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]))); 2485*918dfc20SMatthew 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])); 2486*918dfc20SMatthew G. Knepley } 2487*918dfc20SMatthew G. Knepley if (pr) PetscCall(PetscSynchronizedFlush(PETSC_COMM_WORLD, PETSC_STDOUT)); 2488*918dfc20SMatthew G. Knepley } 2489*918dfc20SMatthew G. Knepley PetscCall(VecRestoreArray(Vres, &vres)); 2490*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "E_field", NULL, NULL, (void **)&E)); 2491*918dfc20SMatthew G. Knepley PetscCall(PetscLogEventEnd(user->RhsVEvent, ts, 0, 0, 0)); 2492*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 2493*918dfc20SMatthew G. Knepley } 2494*918dfc20SMatthew G. Knepley 2495*918dfc20SMatthew G. Knepley static PetscErrorCode CreateSolution(TS ts) 2496*918dfc20SMatthew G. Knepley { 2497*918dfc20SMatthew G. Knepley DM sw; 2498*918dfc20SMatthew G. Knepley Vec u; 2499*918dfc20SMatthew G. Knepley PetscInt dim, Np; 2500*918dfc20SMatthew G. Knepley 2501*918dfc20SMatthew G. Knepley PetscFunctionBegin; 2502*918dfc20SMatthew G. Knepley PetscCall(TSGetDM(ts, &sw)); 2503*918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim)); 2504*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(sw, &Np)); 2505*918dfc20SMatthew G. Knepley PetscCall(VecCreate(PETSC_COMM_WORLD, &u)); 2506*918dfc20SMatthew G. Knepley PetscCall(VecSetBlockSize(u, dim)); 2507*918dfc20SMatthew G. Knepley PetscCall(VecSetSizes(u, 2 * Np * dim, PETSC_DECIDE)); 2508*918dfc20SMatthew G. Knepley PetscCall(VecSetUp(u)); 2509*918dfc20SMatthew G. Knepley PetscCall(TSSetSolution(ts, u)); 2510*918dfc20SMatthew G. Knepley PetscCall(VecDestroy(&u)); 2511*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 2512*918dfc20SMatthew G. Knepley } 2513*918dfc20SMatthew G. Knepley 2514*918dfc20SMatthew G. Knepley static PetscErrorCode SetProblem(TS ts) 2515*918dfc20SMatthew G. Knepley { 2516*918dfc20SMatthew G. Knepley AppCtx *user; 2517*918dfc20SMatthew G. Knepley DM sw; 2518*918dfc20SMatthew G. Knepley 2519*918dfc20SMatthew G. Knepley PetscFunctionBegin; 2520*918dfc20SMatthew G. Knepley PetscCall(TSGetDM(ts, &sw)); 2521*918dfc20SMatthew G. Knepley PetscCall(DMGetApplicationContext(sw, (void **)&user)); 2522*918dfc20SMatthew G. Knepley // Define unified system for (X, V) 2523*918dfc20SMatthew G. Knepley { 2524*918dfc20SMatthew G. Knepley Mat J; 2525*918dfc20SMatthew G. Knepley PetscInt dim, Np; 2526*918dfc20SMatthew G. Knepley 2527*918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim)); 2528*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(sw, &Np)); 2529*918dfc20SMatthew G. Knepley PetscCall(MatCreate(PETSC_COMM_WORLD, &J)); 2530*918dfc20SMatthew G. Knepley PetscCall(MatSetSizes(J, 2 * Np * dim, 2 * Np * dim, PETSC_DECIDE, PETSC_DECIDE)); 2531*918dfc20SMatthew G. Knepley PetscCall(MatSetBlockSize(J, 2 * dim)); 2532*918dfc20SMatthew G. Knepley PetscCall(MatSetFromOptions(J)); 2533*918dfc20SMatthew G. Knepley PetscCall(MatSetUp(J)); 2534*918dfc20SMatthew G. Knepley PetscCall(TSSetRHSFunction(ts, NULL, RHSFunction, user)); 2535*918dfc20SMatthew G. Knepley PetscCall(TSSetRHSJacobian(ts, J, J, RHSJacobian, user)); 2536*918dfc20SMatthew G. Knepley PetscCall(MatDestroy(&J)); 2537*918dfc20SMatthew G. Knepley } 2538*918dfc20SMatthew G. Knepley /* Define split system for X and V */ 2539*918dfc20SMatthew G. Knepley { 2540*918dfc20SMatthew G. Knepley Vec u; 2541*918dfc20SMatthew G. Knepley IS isx, isv, istmp; 2542*918dfc20SMatthew G. Knepley const PetscInt *idx; 2543*918dfc20SMatthew G. Knepley PetscInt dim, Np, rstart; 2544*918dfc20SMatthew G. Knepley 2545*918dfc20SMatthew G. Knepley PetscCall(TSGetSolution(ts, &u)); 2546*918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim)); 2547*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(sw, &Np)); 2548*918dfc20SMatthew G. Knepley PetscCall(VecGetOwnershipRange(u, &rstart, NULL)); 2549*918dfc20SMatthew G. Knepley PetscCall(ISCreateStride(PETSC_COMM_WORLD, Np, (rstart / dim) + 0, 2, &istmp)); 2550*918dfc20SMatthew G. Knepley PetscCall(ISGetIndices(istmp, &idx)); 2551*918dfc20SMatthew G. Knepley PetscCall(ISCreateBlock(PETSC_COMM_WORLD, dim, Np, idx, PETSC_COPY_VALUES, &isx)); 2552*918dfc20SMatthew G. Knepley PetscCall(ISRestoreIndices(istmp, &idx)); 2553*918dfc20SMatthew G. Knepley PetscCall(ISDestroy(&istmp)); 2554*918dfc20SMatthew G. Knepley PetscCall(ISCreateStride(PETSC_COMM_WORLD, Np, (rstart / dim) + 1, 2, &istmp)); 2555*918dfc20SMatthew G. Knepley PetscCall(ISGetIndices(istmp, &idx)); 2556*918dfc20SMatthew G. Knepley PetscCall(ISCreateBlock(PETSC_COMM_WORLD, dim, Np, idx, PETSC_COPY_VALUES, &isv)); 2557*918dfc20SMatthew G. Knepley PetscCall(ISRestoreIndices(istmp, &idx)); 2558*918dfc20SMatthew G. Knepley PetscCall(ISDestroy(&istmp)); 2559*918dfc20SMatthew G. Knepley PetscCall(TSRHSSplitSetIS(ts, "position", isx)); 2560*918dfc20SMatthew G. Knepley PetscCall(TSRHSSplitSetIS(ts, "momentum", isv)); 2561*918dfc20SMatthew G. Knepley PetscCall(ISDestroy(&isx)); 2562*918dfc20SMatthew G. Knepley PetscCall(ISDestroy(&isv)); 2563*918dfc20SMatthew G. Knepley PetscCall(TSRHSSplitSetRHSFunction(ts, "position", NULL, RHSFunctionX, user)); 2564*918dfc20SMatthew G. Knepley PetscCall(TSRHSSplitSetRHSFunction(ts, "momentum", NULL, RHSFunctionV, user)); 2565*918dfc20SMatthew G. Knepley } 2566*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 2567*918dfc20SMatthew G. Knepley } 2568*918dfc20SMatthew G. Knepley 2569*918dfc20SMatthew G. Knepley static PetscErrorCode DMSwarmTSRedistribute(TS ts) 2570*918dfc20SMatthew G. Knepley { 2571*918dfc20SMatthew G. Knepley DM sw; 2572*918dfc20SMatthew G. Knepley Vec u; 2573*918dfc20SMatthew G. Knepley PetscReal t, maxt, dt; 2574*918dfc20SMatthew G. Knepley PetscInt n, maxn; 2575*918dfc20SMatthew G. Knepley 2576*918dfc20SMatthew G. Knepley PetscFunctionBegin; 2577*918dfc20SMatthew G. Knepley PetscCall(TSGetDM(ts, &sw)); 2578*918dfc20SMatthew G. Knepley PetscCall(TSGetTime(ts, &t)); 2579*918dfc20SMatthew G. Knepley PetscCall(TSGetMaxTime(ts, &maxt)); 2580*918dfc20SMatthew G. Knepley PetscCall(TSGetTimeStep(ts, &dt)); 2581*918dfc20SMatthew G. Knepley PetscCall(TSGetStepNumber(ts, &n)); 2582*918dfc20SMatthew G. Knepley PetscCall(TSGetMaxSteps(ts, &maxn)); 2583*918dfc20SMatthew G. Knepley 2584*918dfc20SMatthew G. Knepley PetscCall(TSReset(ts)); 2585*918dfc20SMatthew G. Knepley PetscCall(TSSetDM(ts, sw)); 2586*918dfc20SMatthew G. Knepley PetscCall(TSSetFromOptions(ts)); 2587*918dfc20SMatthew G. Knepley PetscCall(TSSetTime(ts, t)); 2588*918dfc20SMatthew G. Knepley PetscCall(TSSetMaxTime(ts, maxt)); 2589*918dfc20SMatthew G. Knepley PetscCall(TSSetTimeStep(ts, dt)); 2590*918dfc20SMatthew G. Knepley PetscCall(TSSetStepNumber(ts, n)); 2591*918dfc20SMatthew G. Knepley PetscCall(TSSetMaxSteps(ts, maxn)); 2592*918dfc20SMatthew G. Knepley 2593*918dfc20SMatthew G. Knepley PetscCall(CreateSolution(ts)); 2594*918dfc20SMatthew G. Knepley PetscCall(SetProblem(ts)); 2595*918dfc20SMatthew G. Knepley PetscCall(TSGetSolution(ts, &u)); 2596*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 2597*918dfc20SMatthew G. Knepley } 2598*918dfc20SMatthew G. Knepley 2599*918dfc20SMatthew G. Knepley PetscErrorCode line(PetscInt dim, PetscReal time, const PetscReal dummy[], PetscInt p, PetscScalar x[], void *ctx) 2600*918dfc20SMatthew G. Knepley { 2601*918dfc20SMatthew G. Knepley DM sw, cdm; 2602*918dfc20SMatthew G. Knepley PetscInt Np; 2603*918dfc20SMatthew G. Knepley PetscReal low[2], high[2]; 2604*918dfc20SMatthew G. Knepley AppCtx *user = (AppCtx *)ctx; 2605*918dfc20SMatthew G. Knepley 2606*918dfc20SMatthew G. Knepley sw = user->swarm; 2607*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetCellDM(sw, &cdm)); 2608*918dfc20SMatthew G. Knepley // Get the bounding box so we can equally space the particles 2609*918dfc20SMatthew G. Knepley PetscCall(DMGetLocalBoundingBox(cdm, low, high)); 2610*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(sw, &Np)); 2611*918dfc20SMatthew G. Knepley // shift it by h/2 so nothing is initialized directly on a boundary 2612*918dfc20SMatthew G. Knepley x[0] = ((high[0] - low[0]) / Np) * (p + 0.5); 2613*918dfc20SMatthew G. Knepley x[1] = 0.; 2614*918dfc20SMatthew G. Knepley return PETSC_SUCCESS; 2615*918dfc20SMatthew G. Knepley } 2616*918dfc20SMatthew G. Knepley 2617*918dfc20SMatthew G. Knepley /* 2618*918dfc20SMatthew G. Knepley InitializeSolveAndSwarm - Set the solution values to the swarm coordinates and velocities, and also possibly set the initial values. 2619*918dfc20SMatthew G. Knepley 2620*918dfc20SMatthew G. Knepley Input Parameters: 2621*918dfc20SMatthew G. Knepley + ts - The TS 2622*918dfc20SMatthew G. Knepley - useInitial - Flag to also set the initial conditions to the current coordinates and velocities and setup the problem 2623*918dfc20SMatthew G. Knepley 2624*918dfc20SMatthew G. Knepley Output Parameters: 2625*918dfc20SMatthew G. Knepley . u - The initialized solution vector 2626*918dfc20SMatthew G. Knepley 2627*918dfc20SMatthew G. Knepley Level: advanced 2628*918dfc20SMatthew G. Knepley 2629*918dfc20SMatthew G. Knepley .seealso: InitializeSolve() 2630*918dfc20SMatthew G. Knepley */ 2631*918dfc20SMatthew G. Knepley static PetscErrorCode InitializeSolveAndSwarm(TS ts, PetscBool useInitial) 2632*918dfc20SMatthew G. Knepley { 2633*918dfc20SMatthew G. Knepley DM sw; 2634*918dfc20SMatthew G. Knepley Vec u, gc, gv; 2635*918dfc20SMatthew G. Knepley IS isx, isv; 2636*918dfc20SMatthew G. Knepley PetscInt dim; 2637*918dfc20SMatthew G. Knepley AppCtx *user; 2638*918dfc20SMatthew G. Knepley 2639*918dfc20SMatthew G. Knepley PetscFunctionBeginUser; 2640*918dfc20SMatthew G. Knepley PetscCall(TSGetDM(ts, &sw)); 2641*918dfc20SMatthew G. Knepley PetscCall(DMGetApplicationContext(sw, &user)); 2642*918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim)); 2643*918dfc20SMatthew G. Knepley if (useInitial) { 2644*918dfc20SMatthew G. Knepley PetscReal v0[2] = {1., 0.}; 2645*918dfc20SMatthew G. Knepley if (user->perturbed_weights) { 2646*918dfc20SMatthew G. Knepley PetscCall(InitializeParticles_PerturbedWeights(sw, user)); 2647*918dfc20SMatthew G. Knepley } else { 2648*918dfc20SMatthew G. Knepley PetscCall(DMSwarmComputeLocalSizeFromOptions(sw)); 2649*918dfc20SMatthew G. Knepley PetscCall(DMSwarmInitializeCoordinates(sw)); 2650*918dfc20SMatthew G. Knepley PetscCall(DMSwarmInitializeVelocitiesFromOptions(sw, v0)); 2651*918dfc20SMatthew G. Knepley } 2652*918dfc20SMatthew G. Knepley PetscCall(DMSwarmMigrate(sw, PETSC_TRUE)); 2653*918dfc20SMatthew G. Knepley PetscCall(DMSwarmTSRedistribute(ts)); 2654*918dfc20SMatthew G. Knepley } 2655*918dfc20SMatthew G. Knepley PetscCall(DMSetUp(sw)); 2656*918dfc20SMatthew G. Knepley PetscCall(TSGetSolution(ts, &u)); 2657*918dfc20SMatthew G. Knepley PetscCall(TSRHSSplitGetIS(ts, "position", &isx)); 2658*918dfc20SMatthew G. Knepley PetscCall(TSRHSSplitGetIS(ts, "momentum", &isv)); 2659*918dfc20SMatthew G. Knepley PetscCall(DMSwarmCreateGlobalVectorFromField(sw, DMSwarmPICField_coor, &gc)); 2660*918dfc20SMatthew G. Knepley PetscCall(DMSwarmCreateGlobalVectorFromField(sw, "velocity", &gv)); 2661*918dfc20SMatthew G. Knepley PetscCall(VecISCopy(u, isx, SCATTER_FORWARD, gc)); 2662*918dfc20SMatthew G. Knepley PetscCall(VecISCopy(u, isv, SCATTER_FORWARD, gv)); 2663*918dfc20SMatthew G. Knepley PetscCall(DMSwarmDestroyGlobalVectorFromField(sw, DMSwarmPICField_coor, &gc)); 2664*918dfc20SMatthew G. Knepley PetscCall(DMSwarmDestroyGlobalVectorFromField(sw, "velocity", &gv)); 2665*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 2666*918dfc20SMatthew G. Knepley } 2667*918dfc20SMatthew G. Knepley 2668*918dfc20SMatthew G. Knepley static PetscErrorCode InitializeSolve(TS ts, Vec u) 2669*918dfc20SMatthew G. Knepley { 2670*918dfc20SMatthew G. Knepley PetscFunctionBegin; 2671*918dfc20SMatthew G. Knepley PetscCall(TSSetSolution(ts, u)); 2672*918dfc20SMatthew G. Knepley PetscCall(InitializeSolveAndSwarm(ts, PETSC_TRUE)); 2673*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 2674*918dfc20SMatthew G. Knepley } 2675*918dfc20SMatthew G. Knepley 2676*918dfc20SMatthew G. Knepley static PetscErrorCode MigrateParticles(TS ts) 2677*918dfc20SMatthew G. Knepley { 2678*918dfc20SMatthew G. Knepley DM sw, cdm; 2679*918dfc20SMatthew G. Knepley const PetscReal *L; 2680*918dfc20SMatthew G. Knepley AppCtx *ctx; 2681*918dfc20SMatthew G. Knepley 2682*918dfc20SMatthew G. Knepley PetscFunctionBeginUser; 2683*918dfc20SMatthew G. Knepley PetscCall(TSGetDM(ts, &sw)); 2684*918dfc20SMatthew G. Knepley PetscCall(DMGetApplicationContext(sw, &ctx)); 2685*918dfc20SMatthew G. Knepley PetscCall(DMViewFromOptions(sw, NULL, "-migrate_view_pre")); 2686*918dfc20SMatthew G. Knepley { 2687*918dfc20SMatthew G. Knepley Vec u, gc, gv, position, momentum; 2688*918dfc20SMatthew G. Knepley IS isx, isv; 2689*918dfc20SMatthew G. Knepley PetscReal *pos, *mom; 2690*918dfc20SMatthew G. Knepley 2691*918dfc20SMatthew G. Knepley PetscCall(TSGetSolution(ts, &u)); 2692*918dfc20SMatthew G. Knepley PetscCall(TSRHSSplitGetIS(ts, "position", &isx)); 2693*918dfc20SMatthew G. Knepley PetscCall(TSRHSSplitGetIS(ts, "momentum", &isv)); 2694*918dfc20SMatthew G. Knepley PetscCall(VecGetSubVector(u, isx, &position)); 2695*918dfc20SMatthew G. Knepley PetscCall(VecGetSubVector(u, isv, &momentum)); 2696*918dfc20SMatthew G. Knepley PetscCall(VecGetArray(position, &pos)); 2697*918dfc20SMatthew G. Knepley PetscCall(VecGetArray(momentum, &mom)); 2698*918dfc20SMatthew G. Knepley PetscCall(DMSwarmCreateGlobalVectorFromField(sw, DMSwarmPICField_coor, &gc)); 2699*918dfc20SMatthew G. Knepley PetscCall(DMSwarmCreateGlobalVectorFromField(sw, "velocity", &gv)); 2700*918dfc20SMatthew G. Knepley PetscCall(VecISCopy(u, isx, SCATTER_REVERSE, gc)); 2701*918dfc20SMatthew G. Knepley PetscCall(VecISCopy(u, isv, SCATTER_REVERSE, gv)); 2702*918dfc20SMatthew G. Knepley 2703*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetCellDM(sw, &cdm)); 2704*918dfc20SMatthew G. Knepley PetscCall(DMGetPeriodicity(cdm, NULL, NULL, &L)); 2705*918dfc20SMatthew G. Knepley PetscCheck(L, PetscObjectComm((PetscObject)cdm), PETSC_ERR_ARG_WRONG, "Mesh must be periodic"); 2706*918dfc20SMatthew G. Knepley if ((L[0] || L[1]) >= 0.) { 2707*918dfc20SMatthew G. Knepley PetscReal *x, *v, upper[3], lower[3]; 2708*918dfc20SMatthew G. Knepley PetscInt Np, dim; 2709*918dfc20SMatthew G. Knepley 2710*918dfc20SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(sw, &Np)); 2711*918dfc20SMatthew G. Knepley PetscCall(DMGetDimension(cdm, &dim)); 2712*918dfc20SMatthew G. Knepley PetscCall(DMGetBoundingBox(cdm, lower, upper)); 2713*918dfc20SMatthew G. Knepley PetscCall(VecGetArray(gc, &x)); 2714*918dfc20SMatthew G. Knepley PetscCall(VecGetArray(gv, &v)); 2715*918dfc20SMatthew G. Knepley for (PetscInt p = 0; p < Np; ++p) { 2716*918dfc20SMatthew G. Knepley for (PetscInt d = 0; d < dim; ++d) { 2717*918dfc20SMatthew G. Knepley if (pos[p * dim + d] < lower[d]) { 2718*918dfc20SMatthew G. Knepley x[p * dim + d] = pos[p * dim + d] + (upper[d] - lower[d]); 2719*918dfc20SMatthew G. Knepley } else if (pos[p * dim + d] > upper[d]) { 2720*918dfc20SMatthew G. Knepley x[p * dim + d] = pos[p * dim + d] - (upper[d] - lower[d]); 2721*918dfc20SMatthew G. Knepley } else { 2722*918dfc20SMatthew G. Knepley x[p * dim + d] = pos[p * dim + d]; 2723*918dfc20SMatthew G. Knepley } 2724*918dfc20SMatthew 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]); 2725*918dfc20SMatthew G. Knepley v[p * dim + d] = mom[p * dim + d]; 2726*918dfc20SMatthew G. Knepley } 2727*918dfc20SMatthew G. Knepley } 2728*918dfc20SMatthew G. Knepley PetscCall(VecRestoreArray(gc, &x)); 2729*918dfc20SMatthew G. Knepley PetscCall(VecRestoreArray(gv, &v)); 2730*918dfc20SMatthew G. Knepley } 2731*918dfc20SMatthew G. Knepley PetscCall(VecRestoreArray(position, &pos)); 2732*918dfc20SMatthew G. Knepley PetscCall(VecRestoreArray(momentum, &mom)); 2733*918dfc20SMatthew G. Knepley PetscCall(VecRestoreSubVector(u, isx, &position)); 2734*918dfc20SMatthew G. Knepley PetscCall(VecRestoreSubVector(u, isv, &momentum)); 2735*918dfc20SMatthew G. Knepley PetscCall(DMSwarmDestroyGlobalVectorFromField(sw, "velocity", &gv)); 2736*918dfc20SMatthew G. Knepley PetscCall(DMSwarmDestroyGlobalVectorFromField(sw, DMSwarmPICField_coor, &gc)); 2737*918dfc20SMatthew G. Knepley } 2738*918dfc20SMatthew G. Knepley PetscCall(DMSwarmMigrate(sw, PETSC_TRUE)); 2739*918dfc20SMatthew G. Knepley PetscInt step; 2740*918dfc20SMatthew G. Knepley 2741*918dfc20SMatthew G. Knepley PetscCall(TSGetStepNumber(ts, &step)); 2742*918dfc20SMatthew G. Knepley if (!(step % ctx->remapFreq)) { 2743*918dfc20SMatthew G. Knepley // Monitor electric field before we destroy it 2744*918dfc20SMatthew G. Knepley PetscReal ptime; 2745*918dfc20SMatthew G. Knepley PetscInt step; 2746*918dfc20SMatthew G. Knepley 2747*918dfc20SMatthew G. Knepley PetscCall(TSGetStepNumber(ts, &step)); 2748*918dfc20SMatthew G. Knepley PetscCall(TSGetTime(ts, &ptime)); 2749*918dfc20SMatthew G. Knepley if (ctx->efield_monitor) PetscCall(MonitorEField(ts, step, ptime, NULL, ctx)); 2750*918dfc20SMatthew G. Knepley if (ctx->poisson_monitor) PetscCall(MonitorPoisson(ts, step, ptime, NULL, ctx)); 2751*918dfc20SMatthew G. Knepley PetscCall(DMSwarmRemap(sw)); 2752*918dfc20SMatthew G. Knepley ctx->validE = PETSC_FALSE; 2753*918dfc20SMatthew G. Knepley } 2754*918dfc20SMatthew G. Knepley // This MUST come last, since it recreates the subswarms and they must DMClone() the new swarm 2755*918dfc20SMatthew G. Knepley PetscCall(DMSwarmTSRedistribute(ts)); 2756*918dfc20SMatthew G. Knepley PetscCall(InitializeSolveAndSwarm(ts, PETSC_FALSE)); 2757*918dfc20SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 2758*918dfc20SMatthew G. Knepley } 2759*918dfc20SMatthew G. Knepley 2760*918dfc20SMatthew G. Knepley int main(int argc, char **argv) 2761*918dfc20SMatthew G. Knepley { 2762*918dfc20SMatthew G. Knepley DM dm, sw; 2763*918dfc20SMatthew G. Knepley TS ts; 2764*918dfc20SMatthew G. Knepley Vec u; 2765*918dfc20SMatthew G. Knepley PetscReal dt; 2766*918dfc20SMatthew G. Knepley PetscInt maxn; 2767*918dfc20SMatthew G. Knepley AppCtx user; 2768*918dfc20SMatthew G. Knepley 2769*918dfc20SMatthew G. Knepley PetscCall(PetscInitialize(&argc, &argv, NULL, help)); 2770*918dfc20SMatthew G. Knepley PetscCall(ProcessOptions(PETSC_COMM_WORLD, &user)); 2771*918dfc20SMatthew G. Knepley PetscCall(PetscBagCreate(PETSC_COMM_SELF, sizeof(Parameter), &user.bag)); 2772*918dfc20SMatthew G. Knepley PetscCall(CreateMesh(PETSC_COMM_WORLD, &user, &dm)); 2773*918dfc20SMatthew G. Knepley PetscCall(CreatePoisson(dm, &user)); 2774*918dfc20SMatthew G. Knepley PetscCall(CreateMomentFields(dm, &user)); 2775*918dfc20SMatthew G. Knepley PetscCall(CreateSwarm(dm, &user, &sw)); 2776*918dfc20SMatthew G. Knepley PetscCall(SetupParameters(PETSC_COMM_WORLD, &user)); 2777*918dfc20SMatthew G. Knepley PetscCall(InitializeConstants(sw, &user)); 2778*918dfc20SMatthew G. Knepley PetscCall(DMSetApplicationContext(sw, &user)); 2779*918dfc20SMatthew G. Knepley 2780*918dfc20SMatthew G. Knepley PetscCall(TSCreate(PETSC_COMM_WORLD, &ts)); 2781*918dfc20SMatthew G. Knepley PetscCall(TSSetProblemType(ts, TS_NONLINEAR)); 2782*918dfc20SMatthew G. Knepley PetscCall(TSSetDM(ts, sw)); 2783*918dfc20SMatthew G. Knepley PetscCall(TSSetMaxTime(ts, 0.1)); 2784*918dfc20SMatthew G. Knepley PetscCall(TSSetTimeStep(ts, 0.00001)); 2785*918dfc20SMatthew G. Knepley PetscCall(TSSetMaxSteps(ts, 100)); 2786*918dfc20SMatthew G. Knepley PetscCall(TSSetExactFinalTime(ts, TS_EXACTFINALTIME_MATCHSTEP)); 2787*918dfc20SMatthew G. Knepley 2788*918dfc20SMatthew G. Knepley if (user.efield_monitor) PetscCall(TSMonitorSet(ts, MonitorEField, &user, NULL)); 2789*918dfc20SMatthew G. Knepley if (user.moment_monitor) PetscCall(TSMonitorSet(ts, MonitorMoments, &user, NULL)); 2790*918dfc20SMatthew G. Knepley if (user.moment_field_monitor) PetscCall(TSMonitorSet(ts, MonitorMomentFields, &user, NULL)); 2791*918dfc20SMatthew G. Knepley if (user.initial_monitor) PetscCall(TSMonitorSet(ts, MonitorInitialConditions, &user, NULL)); 2792*918dfc20SMatthew G. Knepley if (user.positions_monitor) PetscCall(TSMonitorSet(ts, MonitorPositions_2D, &user, NULL)); 2793*918dfc20SMatthew G. Knepley if (user.poisson_monitor) PetscCall(TSMonitorSet(ts, MonitorPoisson, &user, NULL)); 2794*918dfc20SMatthew G. Knepley if (user.velocity_monitor >= 0) PetscCall(TSMonitorSet(ts, MonitorVelocity, &user, NULL)); 2795*918dfc20SMatthew G. Knepley 2796*918dfc20SMatthew G. Knepley PetscCall(TSSetFromOptions(ts)); 2797*918dfc20SMatthew G. Knepley PetscCall(TSGetTimeStep(ts, &dt)); 2798*918dfc20SMatthew G. Knepley PetscCall(TSGetMaxSteps(ts, &maxn)); 2799*918dfc20SMatthew G. Knepley user.steps = maxn; 2800*918dfc20SMatthew G. Knepley user.stepSize = dt; 2801*918dfc20SMatthew G. Knepley PetscCall(SetupContext(dm, sw, &user)); 2802*918dfc20SMatthew G. Knepley PetscCall(TSSetComputeInitialCondition(ts, InitializeSolve)); 2803*918dfc20SMatthew G. Knepley PetscCall(TSSetPostStep(ts, MigrateParticles)); 2804*918dfc20SMatthew G. Knepley PetscCall(CreateSolution(ts)); 2805*918dfc20SMatthew G. Knepley PetscCall(TSGetSolution(ts, &u)); 2806*918dfc20SMatthew G. Knepley PetscCall(TSComputeInitialCondition(ts, u)); 2807*918dfc20SMatthew G. Knepley PetscCall(CheckNonNegativeWeights(sw, &user)); 2808*918dfc20SMatthew G. Knepley PetscCall(TSSolve(ts, NULL)); 2809*918dfc20SMatthew G. Knepley 2810*918dfc20SMatthew G. Knepley if (user.checkLandau) { 2811*918dfc20SMatthew G. Knepley // We should get a lookup table based on charge density and \hat k 2812*918dfc20SMatthew G. Knepley const PetscReal gammaEx = -0.15336; 2813*918dfc20SMatthew G. Knepley const PetscReal omegaEx = 1.4156; 2814*918dfc20SMatthew G. Knepley const PetscReal tol = 1e-2; 2815*918dfc20SMatthew G. Knepley 2816*918dfc20SMatthew G. Knepley PetscCheck(PetscAbsReal((user.gamma - gammaEx) / gammaEx) < tol, PETSC_COMM_WORLD, PETSC_ERR_LIB, "Invalid Landau gamma %g != %g", user.gamma, gammaEx); 2817*918dfc20SMatthew G. Knepley PetscCheck(PetscAbsReal((user.omega - omegaEx) / omegaEx) < tol, PETSC_COMM_WORLD, PETSC_ERR_LIB, "Invalid Landau omega %g != %g", user.omega, omegaEx); 2818*918dfc20SMatthew G. Knepley } 2819*918dfc20SMatthew G. Knepley 2820*918dfc20SMatthew G. Knepley PetscCall(SNESDestroy(&user.snes)); 2821*918dfc20SMatthew G. Knepley PetscCall(DMDestroy(&user.dmN)); 2822*918dfc20SMatthew G. Knepley PetscCall(ISDestroy(&user.isN)); 2823*918dfc20SMatthew G. Knepley PetscCall(MatDestroy(&user.MN)); 2824*918dfc20SMatthew G. Knepley PetscCall(DMDestroy(&user.dmP)); 2825*918dfc20SMatthew G. Knepley PetscCall(ISDestroy(&user.isP)); 2826*918dfc20SMatthew G. Knepley PetscCall(MatDestroy(&user.MP)); 2827*918dfc20SMatthew G. Knepley PetscCall(DMDestroy(&user.dmE)); 2828*918dfc20SMatthew G. Knepley PetscCall(ISDestroy(&user.isE)); 2829*918dfc20SMatthew G. Knepley PetscCall(MatDestroy(&user.ME)); 2830*918dfc20SMatthew G. Knepley PetscCall(DMDestroy(&user.dmMom)); 2831*918dfc20SMatthew G. Knepley PetscCall(DMDestroy(&user.dmPot)); 2832*918dfc20SMatthew G. Knepley PetscCall(ISDestroy(&user.isPot)); 2833*918dfc20SMatthew G. Knepley PetscCall(MatDestroy(&user.M)); 2834*918dfc20SMatthew G. Knepley PetscCall(PetscFEGeomDestroy(&user.fegeom)); 2835*918dfc20SMatthew G. Knepley PetscCall(TSDestroy(&ts)); 2836*918dfc20SMatthew G. Knepley PetscCall(DMDestroy(&sw)); 2837*918dfc20SMatthew G. Knepley PetscCall(DMDestroy(&dm)); 2838*918dfc20SMatthew G. Knepley PetscCall(DestroyContext(&user)); 2839*918dfc20SMatthew G. Knepley PetscCall(PetscFinalize()); 2840*918dfc20SMatthew G. Knepley return 0; 2841*918dfc20SMatthew G. Knepley } 2842*918dfc20SMatthew G. Knepley 2843*918dfc20SMatthew G. Knepley /*TEST 2844*918dfc20SMatthew G. Knepley 2845*918dfc20SMatthew G. Knepley build: 2846*918dfc20SMatthew G. Knepley requires: !complex double 2847*918dfc20SMatthew G. Knepley 2848*918dfc20SMatthew G. Knepley # This tests that we can compute the correct decay rate and frequency 2849*918dfc20SMatthew G. Knepley # For gold runs, use -dm_plex_box_faces 160 -vdm_plex_box_faces 450 -remap_dm_plex_box_faces 80,150 2850*918dfc20SMatthew G. Knepley test: 2851*918dfc20SMatthew G. Knepley suffix: 0 2852*918dfc20SMatthew G. Knepley args: -cosine_coefficients 0.01 -charges -1. -perturbed_weights -total_weight 1. \ 2853*918dfc20SMatthew G. Knepley -dm_plex_dim 1 -dm_plex_box_faces 80 -dm_plex_box_lower 0. -dm_plex_box_upper 12.5664 \ 2854*918dfc20SMatthew G. Knepley -dm_plex_box_bd periodic -dm_plex_hash_location \ 2855*918dfc20SMatthew G. Knepley -vdm_plex_dim 1 -vdm_plex_box_faces 220 -vdm_plex_box_lower -6 -vdm_plex_box_upper 6 \ 2856*918dfc20SMatthew G. Knepley -vpetscspace_degree 2 -vdm_plex_hash_location \ 2857*918dfc20SMatthew G. Knepley -remap_freq 100 -dm_swarm_remap_type pfak -remap_dm_plex_dim 2 -remap_dm_plex_simplex 0 \ 2858*918dfc20SMatthew G. Knepley -remap_dm_plex_box_faces 40,110 -remap_dm_plex_box_bd periodic,none \ 2859*918dfc20SMatthew G. Knepley -remap_dm_plex_box_lower 0.,-6. -remap_dm_plex_box_upper 12.5664,6. \ 2860*918dfc20SMatthew G. Knepley -remap_petscspace_degree 1 -remap_dm_plex_hash_location \ 2861*918dfc20SMatthew G. Knepley -ftop_ksp_type lsqr -ftop_pc_type none -ftop_ksp_rtol 1.e-14 -ptof_pc_type lu \ 2862*918dfc20SMatthew G. Knepley -em_type primal -petscspace_degree 1 -em_snes_atol 1.e-12 -em_snes_error_if_not_converged \ 2863*918dfc20SMatthew G. Knepley -em_ksp_error_if_not_converged -em_pc_type svd -em_proj_pc_type lu \ 2864*918dfc20SMatthew G. Knepley -ts_type basicsymplectic -ts_basicsymplectic_type 1 -ts_dt 0.03 -ts_max_steps 500 \ 2865*918dfc20SMatthew G. Knepley -ts_max_time 100 \ 2866*918dfc20SMatthew G. Knepley -emax_tao_type brgn -emax_tao_max_it 100 -emax_tao_brgn_regularization_type l2pure \ 2867*918dfc20SMatthew G. Knepley -emax_tao_brgn_regularizer_weight 1e-5 -tao_brgn_subsolver_tao_bnk_ksp_rtol 1e-12 \ 2868*918dfc20SMatthew G. Knepley -output_step 1 -efield_monitor quiet 2869*918dfc20SMatthew G. Knepley 2870*918dfc20SMatthew G. Knepley TEST*/ 2871