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