///|
pub fn map_particles(
particles : ArrayView[Particle],
transform : (Particle) -> Particle,
) -> Array[Particle] {
particles.map(transform)
}
///|
pub fn map_field(field : Field1D, transform : (Double) -> Double) -> Field1D {
{
..field,
electric: field.electric.map(transform),
potential: field.potential.map(transform),
}
}
///|
pub fn scale_field(field : Field1D, factor : Double) -> Field1D {
map_field(field, fn(value) { value * factor })
}
///|
pub fn shift_field(grid : Grid1D, field : Field1D, shift : Double) -> Field1D {
{
..field,
electric: shift_profile(grid, field.electric, shift),
potential: shift_profile(grid, field.potential, shift),
}
}
///|
pub fn mix_fields(
first : Field1D,
second : Field1D,
fraction : Double,
) -> Field1D {
{
..first,
electric: field_add(
field_scale(first.electric, 1.0 - fraction),
field_scale(second.electric, fraction),
),
potential: field_add(
field_scale(first.potential, 1.0 - fraction),
field_scale(second.potential, fraction),
),
}
}
///|
pub fn normalize_field(field : Field1D) -> Field1D {
let scale = field_maximum(field.electric)
if scale == 0.0 {
field
} else {
scale_field(field, 1.0 / scale)
}
}
///|
pub fn project_field(field : Field1D) -> Field1D {
{
..field,
electric: project_zero_mean(field.electric),
potential: poisson_mean_free(field.potential),
}
}
///|
pub fn charge_neutralize(
_grid : Grid1D,
density : ArrayView[Double],
) -> Array[Double] {
density.map(fn(value) { value - mean(density) })
}
///|
pub fn particle_mean_shift(particles : ArrayView[Particle]) -> Array[Particle] {
let average = center_of_mass(Grid1D::new(1, 1.0), particles)
translate_particles(particles, -average)
}
///|
pub fn particle_velocity_center(
particles : ArrayView[Particle],
) -> Array[Particle] {
let average = velocity_mean(particles)
particles.map(fn(particle) {
Particle::new(
x=particle.x,
v=particle.v - average,
weight=particle.weight,
charge=particle.charge,
mass=particle.mass,
)
})
}
///|
pub fn particle_thermalize(
particles : ArrayView[Particle],
temperature : Double,
) -> Array[Particle] {
let scale = temperature.max(0.0).sqrt()
particles.map(fn(particle) {
Particle::new(
x=particle.x,
v=particle.v * scale,
weight=particle.weight,
charge=particle.charge,
mass=particle.mass,
)
})
}
///|
pub fn particle_merge(
first : ArrayView[Particle],
second : ArrayView[Particle],
) -> Array[Particle] {
let output = sample_clone(first)
for particle in second {
output.push(particle)
}
output
}