Skip to content

Commit

Permalink
Merge pull request #296 from ammarhakim/vm-bgk
Browse files Browse the repository at this point in the history
Adding the BGK collision operator to the Vlasov app
  • Loading branch information
ammarhakim authored Mar 11, 2024
2 parents 6f149b6 + 8d66e0e commit 6ba08d6
Show file tree
Hide file tree
Showing 12 changed files with 1,339 additions and 17 deletions.
78 changes: 77 additions & 1 deletion apps/gkyl_vlasov_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <gkyl_array_reduce.h>
#include <gkyl_array_rio.h>
#include <gkyl_bc_basic.h>
#include <gkyl_bgk_collisions.h>
#include <gkyl_dg_advection.h>
#include <gkyl_dg_bin_ops.h>
#include <gkyl_dg_calc_em_vars.h>
Expand Down Expand Up @@ -49,6 +50,7 @@
#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_on_basis.h>
#include <gkyl_range.h>
#include <gkyl_rect_decomp.h>
Expand Down Expand Up @@ -131,6 +133,25 @@ struct vm_lbo_collisions {
gkyl_dg_updater_collisions *coll_slvr; // collision solver
};

struct vm_bgk_collisions {
struct gkyl_array *nu_sum; // BGK collision frequency
struct gkyl_array *nu_sum_host; // BGK collision frequency host-side for I/O
struct gkyl_array *self_nu; // BGK self-collision frequency

bool normNu; // Boolean to determine if using Spitzer value
struct gkyl_array *norm_nu; // Array for normalization factor computed from Spitzer updater n/sqrt(2 vt^2)^3
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 vm_species_moment moms; // moments needed in BGK (single array includes Zeroth, First, and Second moment)

struct gkyl_array *fmax;
struct gkyl_array *nu_fmax;

struct gkyl_proj_maxwellian_on_basis *proj_max; // Maxwellian projection object
struct gkyl_bgk_collisions *up_bgk; // BGK updater (also computes stable timestep)
};

struct vm_boundary_fluxes {
struct vm_species_moment integ_moms[2*GKYL_MAX_CDIM]; // integrated moments
gkyl_ghost_surf_calc *flux_slvr; // boundary flux solver
Expand Down Expand Up @@ -240,7 +261,15 @@ struct vm_species {
struct vm_source src; // applied source

enum gkyl_collision_id collision_id; // type of collisions
struct vm_lbo_collisions lbo; // collisions object
// collisions
union {
struct {
struct vm_lbo_collisions lbo; // LBO collisions object
};
struct {
struct vm_bgk_collisions bgk; // BGK collisions object
};
};

double *omegaCfl_ptr;
};
Expand Down Expand Up @@ -569,6 +598,53 @@ void vm_species_lbo_rhs(gkyl_vlasov_app *app,
*/
void vm_species_lbo_release(const struct gkyl_vlasov_app *app, const struct vm_lbo_collisions *lbo);

/** vm_species_bgk API */

/**
* Initialize species BGK collisions object.
*
* @param app Vlasov app object
* @param s Species object
* @param bgk Species BGK object
*/
void vm_species_bgk_init(struct gkyl_vlasov_app *app, struct vm_species *s,
struct vm_bgk_collisions *bgk);

/**
* Compute necessary moments for BGK collisions
*
* @param app Vlasov app object
* @param species Pointer to species
* @param bgk Pointer to BGK
* @param fin Input distribution function
*/
void vm_species_bgk_moms(gkyl_vlasov_app *app,
const struct vm_species *species,
struct vm_bgk_collisions *bgk,
const struct gkyl_array *fin);

/**
* Compute RHS from BGK collisions
*
* @param app Vlasov app object
* @param species Pointer to species
* @param bgk Pointer to BGK
* @param fin Input distribution function
* @param rhs On output, the RHS from bgk
*/
void vm_species_bgk_rhs(gkyl_vlasov_app *app,
const struct vm_species *species,
struct vm_bgk_collisions *bgk,
const struct gkyl_array *fin, struct gkyl_array *rhs);

/**
* Release species BGK object.
*
* @param app Vlasov app object
* @param bgk Species BGK object to release
*/
void vm_species_bgk_release(const struct gkyl_vlasov_app *app, const struct vm_bgk_collisions *bgk);

/** vm_species_boundary_fluxes API */

/**
Expand Down
4 changes: 4 additions & 0 deletions apps/vlasov.c
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,10 @@ forward_euler(gkyl_vlasov_app* app, double tcurr, double dt,
if (app->species[i].collision_id == GKYL_LBO_COLLISIONS) {
vm_species_lbo_moms(app, &app->species[i], &app->species[i].lbo, fin[i]);
}
else if (app->species[i].collision_id == GKYL_BGK_COLLISIONS) {
vm_species_bgk_moms(app, &app->species[i],
&app->species[i].bgk, fin[i]);
}
}

// compute necessary moments for cross-species collisions
Expand Down
17 changes: 15 additions & 2 deletions apps/vm_species.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,14 @@ vm_species_init(struct gkyl_vm *vm, struct gkyl_vlasov_app *app, struct vm_speci

// determine collision type to use in vlasov update
s->collision_id = s->info.collisions.collision_id;
s->lbo = (struct vm_lbo_collisions) { };
s->bgk = (struct vm_bgk_collisions) { };
if (s->collision_id == GKYL_LBO_COLLISIONS) {
vm_species_lbo_init(app, s, &s->lbo);
}
else if (s->collision_id == GKYL_BGK_COLLISIONS) {
vm_species_bgk_init(app, s, &s->bgk);
}

// determine which directions are not periodic
int num_periodic_dir = app->num_periodic_dir, is_np[3] = {1, 1, 1};
Expand Down Expand Up @@ -341,8 +346,12 @@ vm_species_rhs(gkyl_vlasov_app *app, struct vm_species *species,
gkyl_dg_updater_vlasov_advance(species->slvr, &species->local,
fin, species->cflrate, rhs);

if (species->collision_id == GKYL_LBO_COLLISIONS)
if (species->collision_id == GKYL_LBO_COLLISIONS) {
vm_species_lbo_rhs(app, species, &species->lbo, fin, rhs);
}
else if (species->collision_id == GKYL_BGK_COLLISIONS) {
vm_species_bgk_rhs(app, species, &species->bgk, fin, rhs);
}

app->stat.nspecies_omega_cfl +=1;
struct timespec tm = gkyl_wall_clock();
Expand Down Expand Up @@ -528,8 +537,12 @@ vm_species_release(const gkyl_vlasov_app* app, const struct vm_species *s)
vm_species_source_release(app, &s->src);
}

if (s->collision_id == GKYL_LBO_COLLISIONS)
if (s->collision_id == GKYL_LBO_COLLISIONS) {
vm_species_lbo_release(app, &s->lbo);
}
else if (s->collision_id == GKYL_LBO_COLLISIONS) {
vm_species_bgk_release(app, &s->bgk);
}

// Copy BCs are allocated by default. Need to free.
for (int d=0; d<app->cdim; ++d) {
Expand Down
113 changes: 113 additions & 0 deletions apps/vm_species_bgk.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
#include <assert.h>
#include <gkyl_vlasov_priv.h>

void
vm_species_bgk_init(struct gkyl_vlasov_app *app, struct vm_species *s, struct vm_bgk_collisions *bgk)
{
int cdim = app->cdim, vdim = app->vdim;
// allocate nu and initialize it
bgk->nu_sum = mkarr(app->use_gpu, app->confBasis.num_basis, app->local_ext.volume);
bgk->self_nu = mkarr(app->use_gpu, app->confBasis.num_basis, app->local_ext.volume);
struct gkyl_array *self_nu = mkarr(false, app->confBasis.num_basis, app->local_ext.volume);

gkyl_proj_on_basis *proj = gkyl_proj_on_basis_new(&app->grid, &app->confBasis,
app->poly_order+1, 1, s->info.collisions.self_nu, s->info.collisions.ctx);
gkyl_proj_on_basis_advance(proj, 0.0, &app->local, self_nu);
gkyl_proj_on_basis_release(proj);
gkyl_array_copy(bgk->self_nu, self_nu);
gkyl_array_copy(bgk->nu_sum, self_nu);
gkyl_array_release(self_nu);

bgk->spitzer_calc = 0;
bgk->normNu = false;
if (s->info.collisions.normNu) {
bgk->normNu = true;
double nuFrac = s->info.collisions.nuFrac ? s->info.collisions.nuFrac : 1.0;
double eps0 = 1.0;
double hbar = 1.0;
bgk->spitzer_calc = gkyl_spitzer_coll_freq_new(&app->confBasis, app->poly_order+1,
nuFrac, eps0, hbar, app->use_gpu);
// Create arrays for scaling collisionality by normalization factor
// norm_nu is computed from Spitzer calc and is the normalization factor for the local
// density and thermal velocity, norm_nu_sr = n/(vth_s^2 + vth_r^2)^(3/2)
// nu_init is the inital collisionality profile, which must be stored so that at every time
// time step the collisionality profile is properly scaled and the effects are not cumulative
bgk->norm_nu = mkarr(app->use_gpu, app->confBasis.num_basis, app->local_ext.volume);
bgk->nu_init = mkarr(app->use_gpu, app->confBasis.num_basis, app->local_ext.volume);
gkyl_array_copy(bgk->nu_init, bgk->self_nu);
}

// Host-side copy for I/O
bgk->nu_sum_host = bgk->nu_sum;
if (app->use_gpu)
bgk->nu_sum_host = mkarr(false, app->confBasis.num_basis, app->local_ext.volume);

// allocate moments needed for BGK collisions update
vm_species_moment_init(app, s, &bgk->moms, "FiveMoments");

bgk->proj_max = gkyl_proj_maxwellian_on_basis_new(&s->grid, &app->confBasis, &app->basis,
app->poly_order+1, app->use_gpu);
bgk->fmax = mkarr(app->use_gpu, app->basis.num_basis, s->local_ext.volume);
bgk->nu_fmax = mkarr(app->use_gpu, app->basis.num_basis, s->local_ext.volume);
// BGK updater (also computes stable timestep)
bgk->up_bgk = gkyl_bgk_collisions_new(&app->confBasis, &app->basis, app->use_gpu);
}

// computes moments
void
vm_species_bgk_moms(gkyl_vlasov_app *app, const struct vm_species *species,
struct vm_bgk_collisions *bgk, const struct gkyl_array *fin)
{
struct timespec wst = gkyl_wall_clock();

// compute needed moments
vm_species_moment_calc(&bgk->moms, species->local, app->local, fin);

app->stat.species_coll_mom_tm += gkyl_time_diff_now_sec(wst);
}

// updates the collision terms in the rhs
void
vm_species_bgk_rhs(gkyl_vlasov_app *app, const struct vm_species *species,
struct vm_bgk_collisions *bgk, const struct gkyl_array *fin, struct gkyl_array *rhs)
{
struct timespec wst = gkyl_wall_clock();
gkyl_array_clear(bgk->nu_fmax, 0.0);

// Obtain self-collisions nu*fmax
gkyl_proj_maxwellian_on_basis_lab_mom(bgk->proj_max, &species->local, &app->local,
bgk->moms.marr, bgk->fmax);
gkyl_dg_mul_conf_phase_op_range(&app->confBasis, &app->basis, bgk->fmax,
bgk->self_nu, bgk->fmax, &app->local, &species->local);
gkyl_array_accumulate(bgk->nu_fmax, 1.0, bgk->fmax);

gkyl_bgk_collisions_advance(bgk->up_bgk, &app->local, &species->local,
bgk->nu_sum, bgk->nu_fmax, fin, rhs, species->cflrate);

app->stat.species_coll_tm += gkyl_time_diff_now_sec(wst);
}

void
vm_species_bgk_release(const struct gkyl_vlasov_app *app, const struct vm_bgk_collisions *bgk)
{
gkyl_array_release(bgk->self_nu);
gkyl_array_release(bgk->nu_sum);

gkyl_array_release(bgk->fmax);
gkyl_array_release(bgk->nu_fmax);

if (app->use_gpu) {
gkyl_array_release(bgk->nu_sum_host);
}

vm_species_moment_release(app, &bgk->moms);

if (bgk->normNu) {
gkyl_array_release(bgk->norm_nu);
gkyl_array_release(bgk->nu_init);
gkyl_spitzer_coll_freq_release(bgk->spitzer_calc);
}

gkyl_proj_maxwellian_on_basis_release(bgk->proj_max);
gkyl_bgk_collisions_release(bgk->up_bgk);
}
Loading

0 comments on commit 6ba08d6

Please sign in to comment.