Skip to content

Commit

Permalink
Merge pull request #328 from ammarhakim/maxwellian-moments
Browse files Browse the repository at this point in the history
Refactor of Vlasov correction and projection to new LTE Vlasov objects
  • Loading branch information
ammarhakim authored Mar 27, 2024
2 parents 6b5a5b6 + ed31b53 commit 2ab8b56
Show file tree
Hide file tree
Showing 140 changed files with 5,758 additions and 2,886 deletions.
42 changes: 36 additions & 6 deletions apps/gkyl_vlasov.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,32 @@ struct gkyl_vm_low_inp {
struct gkyl_comm *comm;
};

// Parameters for projection
struct gkyl_vlasov_projection {
enum gkyl_projection_id proj_id; // type of projection (see gkyl_eqn_type.h)

union {
struct {
// pointer and context to initialization function
void *ctx_func;
void (*func)(double t, const double *xn, double *fout, void *ctx);
};
struct {
// pointers and contexts to initialization functions for LTE distribution projection
// (Maxwellian for non-relativistic, Maxwell-Juttner for relativistic)
void *ctx_density;
void (*density)(double t, const double *xn, double *fout, void *ctx);
void *ctx_V_drift;
void (*V_drift)(double t, const double *xn, double *fout, void *ctx);
void *ctx_temp;
void (*temp)(double t, const double *xn, double *fout, void *ctx);

// boolean if we are correcting all the moments or only density
bool correct_all_moms;
};
};
};

// Parameters for species collisions
struct gkyl_vlasov_collisions {
enum gkyl_collision_id collision_id; // type of collisions (see gkyl_eqn_type.h)
Expand All @@ -33,6 +59,12 @@ struct gkyl_vlasov_collisions {
double nuFrac; // Parameter for rescaling collision frequency from SI values
double hbar; // Planck's constant/2 pi

// boolean if we are correcting all the moments or only density:
// only used by BGK collisions
bool correct_all_moms;
double iter_eps; // error tolerance for moment fixes (density is always exact)
int max_iter; // maximum number of iteration

int num_cross_collisions; // number of species to cross-collide with
char collide_with[GKYL_MAX_SPECIES][128]; // names of species to cross collide with

Expand All @@ -46,9 +78,8 @@ struct gkyl_vlasov_source {
double source_length; // required for boundary flux source
char source_species[128];

void *ctx; // context for source function
// function for computing source profile
void (*profile)(double t, const double *xn, double *aout, void *ctx);
// sources using projection routine
struct gkyl_vlasov_projection projection;
};

// Parameters for fluid species source
Expand Down Expand Up @@ -88,9 +119,8 @@ struct gkyl_vlasov_species {
double lower[3], upper[3]; // lower, upper bounds of velocity-space
int cells[3]; // velocity-space cells

void *ctx; // context for initial condition init function
// pointer to initialization function
void (*init)(double t, const double *xn, double *fout, void *ctx);
// initial conditions using projection routine
struct gkyl_vlasov_projection projection;

int num_diag_moments; // number of diagnostic moments
char diag_moments[16][16]; // list of diagnostic moments
Expand Down
136 changes: 102 additions & 34 deletions apps/gkyl_vlasov_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
#include <gkyl_array_rio.h>
#include <gkyl_bc_basic.h>
#include <gkyl_bgk_collisions.h>
#include <gkyl_correct_mj.h>
#include <gkyl_dg_advection.h>
#include <gkyl_dg_bin_ops.h>
#include <gkyl_dg_calc_em_vars.h>
Expand All @@ -41,7 +40,6 @@
#include <gkyl_eval_on_nodes.h>
#include <gkyl_ghost_surf_calc.h>
#include <gkyl_hyper_dg.h>
#include <gkyl_mj_moments.h>
#include <gkyl_mom_bcorr_lbo_vlasov.h>
#include <gkyl_mom_calc.h>
#include <gkyl_mom_calc_bcorr.h>
Expand All @@ -52,15 +50,16 @@
#include <gkyl_prim_lbo_cross_calc.h>
#include <gkyl_prim_lbo_type.h>
#include <gkyl_prim_lbo_vlasov.h>
#include <gkyl_proj_maxwellian_on_basis.h>
#include <gkyl_proj_mj_on_basis.h>
#include <gkyl_proj_on_basis.h>
#include <gkyl_range.h>
#include <gkyl_rect_decomp.h>
#include <gkyl_rect_grid.h>
#include <gkyl_spitzer_coll_freq.h>
#include <gkyl_util.h>
#include <gkyl_vlasov.h>
#include <gkyl_vlasov_lte_correct.h>
#include <gkyl_vlasov_lte_moments.h>
#include <gkyl_vlasov_lte_proj_on_basis.h>
#include <gkyl_wave_geom.h>
#include <gkyl_wv_eqn.h>

Expand All @@ -76,7 +75,8 @@ static const char *const valid_moment_names[] = {
"M3i",
"M3ijk",
"FiveMoments",
"SRFiveMoments", // relativistic moments n, vb, P
"LTEMoments", // this is an internal flag for computing moments (n, V_drift, T/m)
// of the LTE (local thermodynamic equilibrium) distribution
"Integrated", // this is an internal flag, not for passing to moment type
};

Expand All @@ -93,19 +93,22 @@ is_moment_name_valid(const char *nm)

// data for moments
struct vm_species_moment {
struct gkyl_dg_updater_moment *mcalc; // moment update

struct gkyl_array *marr; // array to moment data
struct gkyl_array *marr_host; // host copy (same as marr if not on GPUs)
// Options for moment calculation:
// 1. Compute the moment directly with dg_updater_moment
// 2. Compute the moments of the equivalent LTE (local thermodynamic equilibrium)
// distribution (n, V_drift, T/m) with specialized updater
union {
struct {
struct gkyl_vlasov_lte_moments *vlasov_lte_moms; // updater for computing LTE moments
};
struct {
struct gkyl_dg_updater_moment *mcalc; // moment update
};
};

struct gkyl_mj_moments *mj_moms;
const char *nm; // Moment name
struct gkyl_array *n;
struct gkyl_array *vbi;
struct gkyl_array *T;
int vdim;
int num_basis;
bool is_sr_five_moments;
bool is_vlasov_lte_moms;
};

// forward declare species struct
Expand Down Expand Up @@ -156,26 +159,19 @@ struct vm_bgk_collisions {
struct gkyl_array *nu_init; // Array for initial collisionality when using Spitzer updater
struct gkyl_spitzer_coll_freq* spitzer_calc; // Updater for Spitzer collisionality if computing Spitzer value

struct gkyl_array *fmax;
struct gkyl_array *nu_fmax;
struct gkyl_array *f_lte;
struct gkyl_array *nu_f_lte;

enum gkyl_model_id model_id;
struct vm_species_moment moms; // moments needed in BGK (n, V_drift, T/m) for LTE distribution

// organization of the different models for BGK collisions
union {
// special relativistic Vlasov-Maxwell model
struct {
struct gkyl_proj_mj_on_basis *proj_mj; // Maxwell-Juttner projection object
struct gkyl_correct_mj *corr_mj; // Maxwell-Juttner correction object
struct gkyl_mj_moments *mj_moms;// Maxwell-Juttner moments object
struct gkyl_array *n_stationary, *vb, *T_stationary;
};
// non-relativistic vlasov model
struct {
struct vm_species_moment moms; // moments needed in BGK (single array includes Zeroth, First, and Second moment)
struct gkyl_proj_maxwellian_on_basis *proj_max; // Maxwellian projection object
};
};
// LTE distribution function projection object
// also corrects the density of projected distribution function
struct gkyl_vlasov_lte_proj_on_basis *proj_lte;

// Correction updater for insuring LTE distribution has desired LTE (n, V_drift, T/m) moments
bool correct_all_moms; // boolean if we are correcting all the moments
struct gkyl_vlasov_lte_correct *corr_lte;

struct gkyl_bgk_collisions *up_bgk; // BGK updater (also computes stable timestep)
};
Expand All @@ -185,6 +181,41 @@ struct vm_boundary_fluxes {
gkyl_ghost_surf_calc *flux_slvr; // boundary flux solver
};

struct vm_proj {
enum gkyl_projection_id proj_id; // type of projection
enum gkyl_model_id model_id;
// organization of the different projection objects and the required data and solvers
union {
// function projection
struct {
struct gkyl_proj_on_basis *proj_func; // projection operator for specified function
struct gkyl_array *proj_host; // array for projection on host-side if running on GPUs
};
// LTE (Local thermodynamic equilibrium) distribution function project with moment correction
// (Maxwellian for non-relativistic, Maxwell-Juttner for relativistic)
struct {
struct gkyl_array *dens; // host-side density
struct gkyl_array *V_drift; // host-side V_drift
struct gkyl_array *T_over_m; // host-side T/m (temperature/mass)

struct gkyl_array *vlasov_lte_moms_host; // host-side LTE moms (n, V_drift, T/m)
struct gkyl_array *vlasov_lte_moms; // LTE moms (n, V_drift, T/m) for passing to updaters

struct gkyl_proj_on_basis *proj_dens; // projection operator for density
struct gkyl_proj_on_basis *proj_V_drift; // projection operator for V_drift
struct gkyl_proj_on_basis *proj_temp; // projection operator for temperature

// LTE distribution function projection object
// also corrects the density of projected distribution function
struct gkyl_vlasov_lte_proj_on_basis *proj_lte;

// Correction updater for insuring LTE distribution has desired LTE (n, V_drift, T/m) moments
bool correct_all_moms; // boolean if we are correcting all the moments
struct gkyl_vlasov_lte_correct *corr_lte;
};
};
};

struct vm_source {
struct vm_species_moment moms; // source moments

Expand All @@ -193,7 +224,7 @@ struct vm_source {

struct gkyl_array *source; // applied source
struct gkyl_array *source_host; // host copy for use in IO and projecting
gkyl_proj_on_basis *source_proj; // projector for source
struct vm_proj proj_source; // projector for source

struct vm_species *source_species; // species to use for the source
int source_species_idx; // index of source species
Expand Down Expand Up @@ -285,6 +316,8 @@ struct vm_species {
gkyl_proj_on_basis *accel_proj; // projector for acceleration
struct vm_eval_accel_ctx accel_ctx; // context for applied acceleration

struct vm_proj proj_init; // projector for initial conditions

enum gkyl_source_id source_id; // type of source
struct vm_source src; // applied source

Expand Down Expand Up @@ -705,6 +738,39 @@ void vm_species_bflux_rhs(gkyl_vlasov_app *app, const struct vm_species *species
*/
void vm_species_bflux_release(const struct gkyl_vlasov_app *app, const struct vm_boundary_fluxes *bflux);

/** vm_species_projection API */

/**
* Initialize species projection object.
*
* @param app vlasov app object
* @param s Species object
* @param inp Input struct for projection (contains functions pointers for type of projection)
* @param proj Species projection object
*/
void vm_species_projection_init(struct gkyl_vlasov_app *app, struct vm_species *s,
struct gkyl_vlasov_projection inp, struct vm_proj *proj);

/**
* Compute species projection
*
* @param app vlasov app object
* @param species Species object
* @param proj Species projection object
* @param f Output distribution function from projection
* @param tm Time for use in projection
*/
void vm_species_projection_calc(gkyl_vlasov_app *app, const struct vm_species *species,
struct vm_proj *proj, struct gkyl_array *f, double tm);

/**
* Release species projection object.
*
* @param app vlasov app object
* @param proj Species projection object to release
*/
void vm_species_projection_release(const struct gkyl_vlasov_app *app, const struct vm_proj *proj);

/** vm_species_source API */

/**
Expand All @@ -721,9 +787,11 @@ void vm_species_source_init(struct gkyl_vlasov_app *app, struct vm_species *s, s
*
* @param app Vlasov app object
* @param species Species object
* @param src Pointer to source
* @param tm Time for use in source
*/
void vm_species_source_calc(gkyl_vlasov_app *app, struct vm_species *species, double tm);
void vm_species_source_calc(gkyl_vlasov_app *app, struct vm_species *species,
struct vm_source *src, double tm);

/**
* Compute RHS contribution from source
Expand Down
4 changes: 2 additions & 2 deletions apps/vlasov.c
Original file line number Diff line number Diff line change
Expand Up @@ -355,12 +355,12 @@ gkyl_vlasov_app_calc_integrated_mom(gkyl_vlasov_app* app, double tm)

if (s->model_id == GKYL_MODEL_SR) {
// Compute the necessary factors to correctly integrate relativistic quantities such as:
// 1/Gamma = sqrt(1 - V_drift^2/c^2) where V_drift is computed from weak division: M0 * V_drift = M1i
// GammaV_inv = sqrt(1 - V_drift^2/c^2) where V_drift is computed from weak division: M0 * V_drift = M1i
vm_species_moment_calc(&s->m0, s->local, app->local, s->f);
vm_species_moment_calc(&s->m1i, s->local, app->local, s->f);
gkyl_calc_prim_vars_u_from_rhou(s->V_drift_mem, app->confBasis, &app->local,
s->m0.marr, s->m1i.marr, s->V_drift);
gkyl_calc_sr_vars_Gamma_inv(&app->confBasis, &app->basis, &app->local, s->V_drift, s->GammaV_inv);
gkyl_calc_sr_vars_GammaV_inv(&app->confBasis, &app->basis, &app->local, s->V_drift, s->GammaV_inv);
}
vm_species_moment_calc(&s->integ_moms, s->local, app->local, s->f);
// reduce to compute sum over whole domain, append to diagnostics
Expand Down
4 changes: 2 additions & 2 deletions apps/vlasov_lw.c
Original file line number Diff line number Diff line change
Expand Up @@ -331,8 +331,8 @@ vm_app_new(lua_State *L)
vm.vdim = species[s]->vdim;

app_lw->species_func_ctx[s] = species[s]->init_ref;
vm.species[s].init = eval_ic;
vm.species[s].ctx = &app_lw->species_func_ctx[s];
vm.species[s].projection.func = eval_ic;
vm.species[s].projection.ctx_func = &app_lw->species_func_ctx[s];
}

// set field input
Expand Down
24 changes: 8 additions & 16 deletions apps/vm_species.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,9 @@ vm_species_init(struct gkyl_vm *vm, struct gkyl_vlasov_app *app, struct vm_speci
8, eval_accel, &s->accel_ctx);
}

// initialize projection routine for initial conditions
vm_species_projection_init(app, s, s->info.projection, &s->proj_init);

// set species source id
s->source_id = s->info.source.source_id;

Expand Down Expand Up @@ -285,26 +288,13 @@ vm_species_init(struct gkyl_vm *vm, struct gkyl_vlasov_app *app, struct vm_speci
void
vm_species_apply_ic(gkyl_vlasov_app *app, struct vm_species *species, double t0)
{
int poly_order = app->poly_order;
gkyl_proj_on_basis *proj;
proj = gkyl_proj_on_basis_new(&species->grid, &app->basis,
poly_order+1, 1, species->info.init, species->info.ctx);

// run updater; need to project onto extended range for ease of handling
// subsequent operations over extended range such as primitive variable computations
// This is needed to fill the corner cells as the corner cells may not be filled by
// boundary conditions and we cannot divide by 0 anywhere or the weak divisions will fail
gkyl_proj_on_basis_advance(proj, t0, &species->local_ext, species->f_host);
gkyl_proj_on_basis_release(proj);

if (app->use_gpu) // note: f_host is same as f when not on GPUs
gkyl_array_copy(species->f, species->f_host);
vm_species_projection_calc(app, species, &species->proj_init, species->f, t0);

// Pre-compute applied acceleration in case it's time-independent
vm_species_calc_accel(app, species, t0);

// we are pre-computing source for now as it is time-independent
vm_species_source_calc(app, species, t0);
vm_species_source_calc(app, species, &species->src, t0);

// copy contents of initial conditions into buffer if specific BCs require them
// *only works in x dimension for now*
Expand Down Expand Up @@ -485,6 +475,8 @@ vm_species_release(const gkyl_vlasov_app* app, const struct vm_species *s)
gkyl_array_release(s->bc_buffer_lo_fixed);
gkyl_array_release(s->bc_buffer_up_fixed);

vm_species_projection_release(app, &s->proj_init);

gkyl_comm_release(s->comm);

if (app->use_gpu)
Expand Down Expand Up @@ -540,7 +532,7 @@ vm_species_release(const gkyl_vlasov_app* app, const struct vm_species *s)
if (s->collision_id == GKYL_LBO_COLLISIONS) {
vm_species_lbo_release(app, &s->lbo);
}
else if (s->collision_id == GKYL_LBO_COLLISIONS) {
else if (s->collision_id == GKYL_BGK_COLLISIONS) {
vm_species_bgk_release(app, &s->bgk);
}

Expand Down
Loading

0 comments on commit 2ab8b56

Please sign in to comment.