///|
pub(all) struct SimulationScenario {
name : String
grid : Grid1D
particles : Int
steps : Int
dt : Double
boundary : Boundary1D
shape : ShapeKind
seed : Int
} derive(Debug, ToJson)
///|
pub fn standard_scenario(
name : String,
cells : Int,
particles : Int,
steps : Int,
) -> SimulationScenario {
{
name,
grid: Grid1D::new(cells.max(2), 1.0),
particles: particles.max(0),
steps: steps.max(0),
dt: 1.0e-4,
boundary: Periodic,
shape: CIC,
seed: deterministic_seed(name, cells + particles + steps),
}
}
///|
pub fn scenario_with_dt(
scenario : SimulationScenario,
dt : Double,
) -> SimulationScenario {
{ ..scenario, dt, }
}
///|
pub fn scenario_with_boundary(
scenario : SimulationScenario,
boundary : Boundary1D,
) -> SimulationScenario {
{ ..scenario, boundary, }
}
///|
pub fn scenario_with_shape(
scenario : SimulationScenario,
shape : ShapeKind,
) -> SimulationScenario {
{ ..scenario, shape, }
}
///|
pub fn scenario_initial_state(scenario : SimulationScenario) -> PicState {
let particles = sample_particles(
scenario.grid,
scenario.particles,
scenario.seed,
0.0,
1.0e4,
)
PicState::new(scenario.grid, particles)
}
///|
pub fn scenario_step(
state : PicState,
scenario : SimulationScenario,
) -> PicState {
let stepped = state.step(scenario.dt)
let particles = apply_particle_boundary_batch(
scenario.grid,
scenario.boundary,
stepped.particles,
).alive
let density = deposit_charge_with_shape(
scenario.grid,
particles,
scenario.shape,
)
{
grid: scenario.grid,
particles,
field: solve_periodic_field(scenario.grid, density),
time: stepped.time,
}
}
///|
pub fn scenario_run(scenario : SimulationScenario) -> PicState {
let mut state = scenario_initial_state(scenario)
for _ in 0.. Array[PicDiagnostics] {
let output : Array[PicDiagnostics] = []
let mut state = scenario_initial_state(scenario)
output.push(PicDiagnostics::from_state(state))
for _ in 0.. Int {
scenario.particles
}
///|
pub fn scenario_work_units(scenario : SimulationScenario) -> Int {
scenario.grid.cells * scenario.particles * scenario.steps
}
///|
pub fn scenario_description(scenario : SimulationScenario) -> String {
"\{scenario.name}: cells=\{scenario.grid.cells}, particles=\{scenario.particles}, steps=\{scenario.steps}, dt=\{scenario.dt}, shape=\{shape_name(scenario.shape)}"
}
///|
pub fn scenario_diagnostics_csv(scenario : SimulationScenario) -> String {
diagnostics_to_csv(scenario_trace(scenario))
}
///|
pub fn scenario_charge_error(scenario : SimulationScenario) -> Double {
let diagnostics = scenario_trace(scenario)
if diagnostics.length() == 0 {
0.0
} else {
(diagnostics[diagnostics.length() - 1].total_charge -
diagnostics[0].total_charge).abs()
}
}