Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
54512e7
+run_test
JamesMcClung Oct 15, 2025
99e2083
inc_curr*; *: rename to .cxx
JamesMcClung Jun 2, 2025
d645411
inc_push; *: rename to .cxx
JamesMcClung Jun 11, 2025
ef2ee80
test_reflective_bcs*: rm accidental BgkMfields
JamesMcClung Oct 15, 2025
21b6759
checks_impl: print names of diffed quantities
JamesMcClung Oct 10, 2025
f393957
setup_particles: add missing includes
JamesMcClung May 8, 2025
1d764ef
setup_particles: get_n_in_cell takes density
JamesMcClung May 16, 2025
b94a473
setup_particles: mv get_n_in_cell
JamesMcClung May 16, 2025
d99f271
grid: +prts_per_unit_density
JamesMcClung May 16, 2025
9de0273
setup_particles: use prts_per_unit_density
JamesMcClung May 16, 2025
3bd6c9a
setup_particles: getWeight takes density
JamesMcClung Oct 10, 2025
cd734c7
setup_particles: rename wni->weight
JamesMcClung Oct 10, 2025
bee8976
-test_bnd_prt_inflow
JamesMcClung May 8, 2025
9ccb87a
+injector_boundary_inflow
JamesMcClung May 9, 2025
e96c78b
injector_boundary_inflow: +ParticleGeneratorMaxwellian
JamesMcClung May 9, 2025
ddd85f5
injector_boundary_inflow: +ctor for generator
JamesMcClung May 16, 2025
8dd16e3
injector_boundary_inflow: make Real types public
JamesMcClung May 16, 2025
cb1d99a
+test_injector_boundary_inflow: failing gen test
JamesMcClung May 16, 2025
77d0c44
injector_boundary_inflow: store gen info
JamesMcClung May 16, 2025
f795a45
injector_boundary_inflow; test: pass w too
JamesMcClung May 16, 2025
bcf4b1c
injector_boundary_inflow: sample u
JamesMcClung May 16, 2025
d726c48
injector_boundary_inflow; test: pass pos info to get
JamesMcClung May 16, 2025
c1d841b
injector_boundary_inflow: template by generator
JamesMcClung May 16, 2025
da059f3
test_injector_boundary_inflow: use better kind_idx
JamesMcClung May 16, 2025
1f2094b
test_injector_boundary_inflow: +Integration test
JamesMcClung May 16, 2025
93657ae
test_injector_boundary_inflow: pass inject_particles
JamesMcClung May 16, 2025
8238587
injector_boundary_inflow: template by PushParticles
JamesMcClung May 16, 2025
bdd7e54
injector_boundary_inflow: pass grid, do injection
JamesMcClung May 16, 2025
a12eb00
injector_boundary_inflow: update currents
JamesMcClung May 16, 2025
c49d15f
test_injector_boundary_inflow: don't put prts at edge
JamesMcClung May 20, 2025
4b68523
injector_boundary_inflow: don't zero out fields
JamesMcClung May 20, 2025
cf3758a
test_injector_boundary_inflow: use nicell=2
JamesMcClung May 20, 2025
d408453
test_injector_boundary_inflow: use nmax=2
JamesMcClung May 20, 2025
e3b0d31
injector_boundary_inflow: rename to initial_idx
JamesMcClung May 20, 2025
cbf8fe4
injector_boundary_inflow: -w
JamesMcClung May 29, 2025
763c625
injector_boundary_inflow: rm unused vars
JamesMcClung Jun 2, 2025
9865b68
injector_boundary_inflow: rename prts_in_cell
JamesMcClung Jun 2, 2025
056feee
injector_boundary_inflow: use get_n_in_cell
JamesMcClung Jun 2, 2025
04258c3
injector_boundary_inflow: rm EM stuff
JamesMcClung Jun 2, 2025
fbe3ee9
injector_boundary_inflow: use cell_idx as initial
JamesMcClung Jun 2, 2025
b9f69d1
injector_boundary_inflow: rm ip
JamesMcClung Jun 2, 2025
388df3b
injector_boundary_inflow: rm accessor
JamesMcClung Jun 2, 2025
c9cfff7
injector_boundary_inflow: mv/rename min_pos
JamesMcClung Jun 2, 2025
ff6f276
injector_boundary_inflow: cleanup assertions
JamesMcClung Jun 2, 2025
bf64156
test_injector_boundary_inflow: use periodic BCs
JamesMcClung Oct 15, 2025
762456c
injector_boundary_inflow: deposit current in boundary
JamesMcClung Oct 15, 2025
46963bc
test_injector_boundary_inflow: only inject 1 particle
JamesMcClung Oct 15, 2025
db4e971
test_injector_boundary_inflow: use open BCs
JamesMcClung Oct 10, 2025
27f5bab
psc_bnd_fields_impl: assert 0 -> todo
JamesMcClung Oct 10, 2025
c8e809e
test_injector_boundary_inflow: assert n_patches=1
JamesMcClung Oct 15, 2025
581fa64
test_injector_boundary_inflow: rename test
JamesMcClung Oct 15, 2025
42e2b3e
test_injector_boundary_inflow: templatize generator by count
JamesMcClung Oct 15, 2025
458046b
test_injector_boundary_inflow: +multi-particle test
JamesMcClung Oct 15, 2025
f2b71c4
injector_boundary_inflow: add comment
JamesMcClung Oct 15, 2025
fa3de48
run_test: mv and document
JamesMcClung Oct 15, 2025
67b50ee
boundary_injector; *: rename file
JamesMcClung Oct 16, 2025
3567c0c
boundary_injector; *: rename class
JamesMcClung Oct 16, 2025
6dd7710
test_boundary_injector; *: rename file
JamesMcClung Oct 16, 2025
cfd512c
test_boundary_injector: rename tests
JamesMcClung Oct 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions scripts/run_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/bash

# Usage: scripts/run_test.sh name_of_test
# Example: scripts/run_test.sh test_injector_boundary_inflow
# Assumes you are in the root psc directory and have a build directory.

set -e
cd build
make $1
mkdir -p runs
cp ../bits/adios2cfg.xml runs/
cd runs
../src/libpsc/tests/$1 "${@:2}"
164 changes: 164 additions & 0 deletions src/include/boundary_injector.hxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
#pragma once

#include <math.h>

#include "grid.hxx"
#include "rng.hxx"
#include "particle.h"
#include <psc.hxx>
#include "pushp.hxx"
#include "dim.hxx"
#include "setup_particles.hxx"
#include "../libpsc/psc_push_particles/inc_push.cxx"

class ParticleGeneratorMaxwellian
{
public:
using Real = psc::particle::Inject::Real;
using Real3 = psc::particle::Inject::Real3;

// FIXME would be nice to just pass 1 thing for kind-related info
ParticleGeneratorMaxwellian(int kind_idx, Grid_t::Kind kind, Real3 mean_u,
Real3 temperature)
: kind_idx{kind_idx}
{
for (int d = 0; d < 3; d++) {
Real stdev_u = sqrt(temperature[d] / kind.m);
vdfs[d] = VelocityDistributionFunction{mean_u[d], stdev_u};
}
}

psc::particle::Inject get(Real3 min_pos, Real3 pos_range)
{
Real3 x;
for (int d = 0; d < 3; d++) {
x[d] = min_pos[d] + uniform_dist.get() * pos_range[d];
}

Real3 u{vdfs[0].get(), vdfs[1].get(), vdfs[2].get()};
Real w = 1.0;
psc::particle::Tag tag = 0;

return {x, u, w, kind_idx, tag};
}

private:
using VelocityDistributionFunction = rng::Normal<Real>;
Vec3<VelocityDistributionFunction> vdfs;
int kind_idx;
rng::Uniform<Real> uniform_dist{0.0, 1.0};
};

template <typename PARTICLE_GENERATOR, typename PUSH_PARTICLES>
class BoundaryInjector
{
static const int INJECT_DIM_IDX_ = 1;

public:
using ParticleGenerator = PARTICLE_GENERATOR;
using PushParticles = PUSH_PARTICLES;

using Mparticles = typename PushParticles::Mparticles;
using MfieldsState = typename PushParticles::MfieldsState;
using AdvanceParticle_t = typename PushParticles::AdvanceParticle_t;
using Current = typename PushParticles::Current;
using Dim = typename PushParticles::Dim;
using real_t = typename PushParticles::real_t;
using Real3 = typename PushParticles::Real3;
using checks_order = typename PushParticles::checks_order;

BoundaryInjector(ParticleGenerator particle_generator, Grid_t& grid)
: partice_generator{particle_generator},
advance{grid.dt},
prts_per_unit_density{grid.norm.prts_per_unit_density}
{}

/// Injects particles at the lower y-bound as if there were a population of
/// particles just beyond the edge. The imaginary particle population has unit
/// density, and individual particles from that population are sampled using
/// the given ParticleGenerator.
///
/// Some of these limitations may be removed in the future.
void operator()(Mparticles& mprts, MfieldsState& mflds)
{
static_assert(INJECT_DIM_IDX_ == 1,
"only injection at lower bound of y is supported");

const Grid_t& grid = mprts.grid();
auto injectors_by_patch = mprts.injector();

Real3 dxi = Real3{1., 1., 1.} / Real3(grid.domain.dx);
Current current(grid);

for (int patch_idx = 0; patch_idx < grid.n_patches(); patch_idx++) {
Int3 ilo = grid.patches[patch_idx].off;

if (ilo[INJECT_DIM_IDX_] != 0) {
continue;
}

Int3 ihi = ilo + grid.ldims;

auto&& injector = injectors_by_patch[patch_idx];
auto flds = mflds[patch_idx];
typename Current::fields_t J(flds);

for (Int3 cell_idx = ilo; cell_idx[0] < ihi[0]; cell_idx[0]++) {
for (cell_idx[2] = ilo[2]; cell_idx[2] < ihi[2]; cell_idx[2]++) {
cell_idx[INJECT_DIM_IDX_] = -1;

Real3 cell_corner =
grid.domain.corner + Double3(cell_idx) * grid.domain.dx;
int n_prts_to_try_inject =
get_n_in_cell(1.0, prts_per_unit_density, true);
real_t charge_injected = 0;

for (int prt_count = 0; prt_count < n_prts_to_try_inject;
prt_count++) {
psc::particle::Inject prt =
partice_generator.get(cell_corner, grid.domain.dx);

Real3 v = advance.calc_v(prt.u);
Real3 initial_x = prt.x;
advance.push_x(prt.x, v, 1.0);

if (prt.x[INJECT_DIM_IDX_] < grid.domain.corner[INJECT_DIM_IDX_]) {
// don't inject a particle that fails to enter the domain
continue;
}

injector(prt);

// Update currents
// Taken from push_particles_1vb.hxx PushParticlesVb::push_mprts()

Real3 initial_normalized_pos = initial_x * dxi;

Int3 final_idx;
Real3 final_normalized_pos;
find_idx_pos_1st_rel(prt.x, dxi, final_idx, final_normalized_pos,
real_t(0.));

// CURRENT DENSITY BETWEEN (n+.5)*dt and (n+1.5)*dt
real_t qni_wni = grid.kinds[prt.kind].q * prt.w;
current.calc_j(J, initial_normalized_pos, final_normalized_pos,
final_idx, cell_idx, qni_wni, v);

charge_injected += qni_wni;
}

// set current in boundary to account for injected charge
flds.storage()(cell_idx[0] + grid.ibn[0], -1 + grid.ibn[1],
cell_idx[2] + grid.ibn[2], JXI + 1) =
charge_injected * grid.domain.dx[1] / grid.dt /
prts_per_unit_density;
}
}
}
}

private:
ParticleGenerator partice_generator;
AdvanceParticle<real_t, dim_y> advance;
real_t prts_per_unit_density;
};
2 changes: 2 additions & 0 deletions src/include/grid.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ struct Grid_<T>::Normalization
double vt = sqrt(prm.tt / prm.mm);
double wp = sqrt(sqr(prm.qq) * prm.n0 / prm.eps0 / prm.mm);

prts_per_unit_density = prm.nicell;
cori = 1. / prm.nicell;
double alpha_ = wp / wl;
beta = vt / cc;
Expand All @@ -299,6 +300,7 @@ struct Grid_<T>::Normalization
real_t eta = {1.};
real_t beta = {1.};
real_t cori = {1.};
real_t prts_per_unit_density;

real_t e0;
real_t b0;
Expand Down
57 changes: 36 additions & 21 deletions src/include/setup_particles.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@
#include <algorithm>
#include <functional>
#include <type_traits>

#include <mrc_profile.h>

#include "centering.hxx"
#include "particle.h"
#include "rng.hxx"

struct psc_particle_npt
Expand All @@ -24,9 +28,6 @@ struct psc_particle_np
psc::particle::Tag tag;
};

// ======================================================================
// SetupParticles

namespace
{
const centering::Centerer defaultCenterer(centering::CC);
Expand Down Expand Up @@ -92,6 +93,28 @@ private:
std::function<void(int, Double3, int, Int3, psc_particle_np&)> func;
};

// ======================================================================
// get_n_in_cell
//
// helper function for partition / particle setup

template <typename real_t>
int get_n_in_cell(real_t density, real_t prts_per_unit_density,
bool fractional_n_particles_per_cell)
{
static rng::Uniform<float> dist{0, 1};
if (density == 0.0) {
return 0;
}
if (fractional_n_particles_per_cell) {
return density * prts_per_unit_density + dist.get();
}
return std::max(1, int(density * prts_per_unit_density + .5));
}

// ======================================================================
// SetupParticles

template <typename MP>
struct SetupParticles
{
Expand All @@ -111,19 +134,11 @@ struct SetupParticles

// ----------------------------------------------------------------------
// get_n_in_cell
//
// helper function for partition / particle setup

int get_n_in_cell(const psc_particle_np& np)
int get_n_in_cell(real_t density)
{
static rng::Uniform<float> dist{0, 1};
if (np.n == 0) {
return 0;
}
if (fractional_n_particles_per_cell) {
return np.n / norm_.cori + dist.get();
}
return std::max(1, int(np.n / norm_.cori + .5));
return ::get_n_in_cell(density, real_t(norm_.prts_per_unit_density),
fractional_n_particles_per_cell);
}

// ----------------------------------------------------------------------
Expand Down Expand Up @@ -161,7 +176,7 @@ struct SetupParticles

int n_in_cell;
if (pop != neutralizing_population) {
n_in_cell = get_n_in_cell(np);
n_in_cell = get_n_in_cell(np.n);
n_q_in_cell += kinds_[np.kind].q * n_in_cell;
} else {
// FIXME, should handle the case where not the last population
Expand All @@ -180,9 +195,9 @@ struct SetupParticles
// setupParticle

psc::particle::Inject setupParticle(const psc_particle_np& np, Double3 pos,
double wni)
double weight)
{
return psc::particle::Inject{pos, np.p(), wni, np.kind, np.tag};
return psc::particle::Inject{pos, np.p(), weight, np.kind, np.tag};
}

// ----------------------------------------------------------------------
Expand Down Expand Up @@ -244,12 +259,12 @@ struct SetupParticles
// ----------------------------------------------------------------------
// getWeight

real_t getWeight(const psc_particle_np& np, int n_in_cell)
real_t getWeight(real_t density, int n_in_cell)
{
if (fractional_n_particles_per_cell) {
return 1.;
} else {
return np.n / (n_in_cell * norm_.cori);
return density * norm_.prts_per_unit_density / n_in_cell;
}
}

Expand Down Expand Up @@ -281,8 +296,8 @@ struct SetupParticles
op_cellwise(grid, p, init_np,
[&](int n_in_cell, psc_particle_np& np, Double3& pos) {
for (int cnt = 0; cnt < n_in_cell; cnt++) {
real_t wni = getWeight(np, n_in_cell);
auto prt = setupParticle(np, pos, wni);
real_t weight = getWeight(np.n, n_in_cell);
auto prt = setupParticle(np, pos, weight);
injector(prt);
}
});
Expand Down
6 changes: 4 additions & 2 deletions src/libpsc/psc_bnd_fields/psc_bnd_fields_impl.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,8 @@ struct BndFields_ : BndFieldsBase
const int* ldims = mflds.grid().ldims;
Int3 ib = mflds.ib(), im = mflds.im();

assert(0);
// TODO
// assert(0);
#if 0

if (d == 1) {
Expand Down Expand Up @@ -554,7 +555,8 @@ struct BndFields_ : BndFieldsBase
const int* ldims = mflds.grid().ldims;
Int3 ib = mflds.ib(), im = mflds.im();

assert(0);
// TODO
// assert(0);
#if 0
if (d == 1) {
int my _mrc_unused = ldims[1];
Expand Down
2 changes: 2 additions & 0 deletions src/libpsc/psc_checks/checks_impl.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ public:
MPI_Allreduce(&local_err, &max_err, 1, MPI_DOUBLE, MPI_MAX, grid.comm());

if (should_print_diffs(max_err)) {
mpi_printf(grid.comm(), "continuity: drho -- -dt*div j\n");
psc::helper::print_diff(d_rho, -dt_divj, err_threshold);
}

Expand Down Expand Up @@ -160,6 +161,7 @@ public:
max_err = std::max(max_err, patch_err);

if (should_print_diffs(patch_err)) {
mpi_printf(grid.comm(), "gauss: rho -- div E\n");
psc::helper::print_diff(patch_rho, patch_dive, err_threshold);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ GT_INLINE void deposit(Curr& curr, const int _i[3], const real_t fnqs[3],
deposition(curr, i, qni_wni, dx, xa, dim_xyz{});
}

#include "inc_curr_1vb_split.c"
#include "inc_curr_1vb_var1.c"
#include "inc_curr_1vb_2d.c"
#include "inc_curr_zigzag.c"
#include "inc_curr_1vb_split.cxx"
#include "inc_curr_1vb_var1.cxx"
#include "inc_curr_1vb_2d.cxx"
#include "inc_curr_zigzag.cxx"

template <typename _Order, typename _Dim, typename _fields_t>
struct Current1vb;
4 changes: 2 additions & 2 deletions src/libpsc/psc_push_particles/push_config.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@

#include "inc_defs.h"
#include "interpolate.hxx"
#include "inc_curr.c"
#include "inc_push.c"
#include "inc_curr.cxx"
#include "inc_push.cxx"
#include "push_particles.hxx"
#include "push_particles_esirkepov.hxx"
#include "push_particles_1vb.hxx"
Expand Down
2 changes: 1 addition & 1 deletion src/libpsc/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ add_psc_test(test_reflective_bcs_integration)
add_psc_test(test_mfields)
add_psc_test(test_mfields_cuda)
add_psc_test(test_bnd)
add_psc_test(test_bnd_prt_inflow)
add_psc_test(test_boundary_injector)
add_psc_test(test_deposit)
add_psc_test(test_current_deposition)
add_psc_test(test_push_particles)
Expand Down
Loading