Compare commits

..

2 Commits

Author SHA1 Message Date
b62745adec nits 2025-03-24 16:59:39 -04:00
b7f44d9ac0 simplify Model::run 2025-03-24 16:46:42 -04:00
3 changed files with 23 additions and 105 deletions

View File

@@ -11,7 +11,7 @@ impl Buf {
}
// Truncate x and y and return a corresponding index into the data slice.
fn index(&self, x: f32, y: f32) -> usize {
const fn index(&self, x: f32, y: f32) -> usize {
// x/y can come in negative, hence we shift them by width/height.
let i = (x + self.width as f32) as usize & (self.width - 1);
let j = (y + self.height as f32) as usize & (self.height - 1);

View File

@@ -1,5 +1,6 @@
use crate::{grid::Grid, palette::Palette};
use image::RgbImage;
use itertools::multizip;
/// Stores data that is located in grids that is used for image generation
@@ -48,16 +49,6 @@ impl ThinGridData {
.select_nth_unstable_by(index, |a, b| a.partial_cmp(b).unwrap());
sorted[index]
}
pub fn size_of(&self) -> usize {
let mut output: usize = 0;
output += std::mem::size_of_val(&self.width);
output += std::mem::size_of_val(&self.height);
for i in self.data.iter() {
output += std::mem::size_of_val(&i);
}
output
}
}
/// Class for storing data that will be used to create images
@@ -65,29 +56,17 @@ impl ThinGridData {
pub struct ImgData {
pub grids: Vec<ThinGridData>,
pub palette: Palette,
pub iteration: i32,
}
impl ImgData {
pub fn new(in_grids: Vec<ThinGridData>, in_palette: Palette, in_iteration: i32) -> Self {
pub fn new(in_grids: Vec<ThinGridData>, in_palette: Palette) -> Self {
ImgData {
grids: in_grids,
palette: in_palette,
iteration: in_iteration,
}
}
pub fn size_of(&self) -> usize {
let mut output: usize = 0;
output += std::mem::size_of_val(&self.iteration);
output += std::mem::size_of_val(&self.palette);
for grid in self.grids.iter() {
output += grid.size_of();
}
output
}
pub fn save_to_image(&self) {
pub fn to_image(&self) -> RgbImage {
let (width, height) = (self.grids[0].width, self.grids[0].height);
let mut img = image::RgbImage::new(width as u32, height as u32);
@@ -116,8 +95,6 @@ impl ImgData {
img.put_pixel(x as u32, y as u32, image::Rgb([r as u8, g as u8, b as u8]));
}
}
img.save(format!("./tmp/out_{}.png", self.iteration).as_str())
.unwrap();
img
}
}

View File

@@ -23,13 +23,13 @@ pub struct Model {
diffusivity: usize,
// Current model iteration.
iteration: i32,
iteration: usize,
// Color palette
palette: Palette,
// List of ImgData to be processed post-simulation into images
img_data_vec: Vec<ImgData>,
img_data_vec: Vec<(usize, ImgData)>,
}
impl Model {
@@ -96,8 +96,6 @@ impl Model {
// Simulates `steps` # of steps
#[inline]
pub fn run(&mut self, steps: usize) {
let debug: bool = false;
let pb = ProgressBar::new(steps as u64);
pb.set_style(
ProgressStyle::default_bar()
@@ -111,21 +109,15 @@ impl Model {
let mut time_per_step_list: Vec<f64> = Vec::new();
let agents_num: usize = self.grids.iter().map(|grid| grid.agents.len()).sum();
for i in 0..steps {
if debug {
println!("Starting tick for all agents...")
};
(0..steps).for_each(|_| {
// Combine grids
let grids = &mut self.grids;
combine(grids, &self.attraction_table);
combine(&mut self.grids, &self.attraction_table);
let agents_tick_time = Instant::now();
// Tick agents
let diffusivity = self.diffusivity;
self.grids.par_iter_mut().for_each(|grid| {
grid.tick();
grid.diffuse(diffusivity); // Diffuse + Decay
grid.diffuse(self.diffusivity); // Diffuse + Decay
});
self.save_image_data();
@@ -135,37 +127,27 @@ impl Model {
time_per_agent_list.push(ms_per_agent);
time_per_step_list.push(agents_tick_elapsed);
if debug {
println!(
"Finished tick for all agents. took {}ms\nTime per agent: {}ms\n",
agents_tick_elapsed, ms_per_agent
)
};
self.iteration += 1;
pb.set_position(i as u64);
}
pb.inc(1);
});
pb.finish();
let avg_per_step: f64 =
time_per_step_list.iter().sum::<f64>() / time_per_step_list.len() as f64;
let avg_per_agent: f64 =
time_per_agent_list.iter().sum::<f64>() / time_per_agent_list.len() as f64;
println!(
"Average time per step: {}ms\nAverage time per agent: {}ms",
avg_per_step, avg_per_agent
);
}
fn size_of_imgdata_vec(&self) -> usize {
self.img_data_vec[0].size_of() * self.img_data_vec.len()
}
fn save_image_data(&mut self) {
let grids = ThinGridData::new_from_grid_vec(self.grids.clone());
let img_data = ImgData::new(grids, self.palette, self.iteration);
self.img_data_vec.push(img_data);
let size: usize = self.size_of_imgdata_vec();
let img_data = ImgData::new(grids, self.palette);
self.img_data_vec.push((self.iteration + 1, img_data));
let size: usize = std::mem::size_of_val(&self.img_data_vec);
let mb = size / 1024 / 1024;
// println!("{} B | {} KB | {} MB", size, size/1024, size/1024/1024);
@@ -185,7 +167,7 @@ impl Model {
self.img_data_vec.clear();
}
pub fn render_all_imgdata(&self) {
pub fn render_all_imgdata(&mut self) {
if !Path::new("./tmp").exists() {
std::fs::create_dir("./tmp").expect("could create directory");
}
@@ -195,56 +177,15 @@ impl Model {
"{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] ({pos}/{len}, {percent}%, {per_sec})",
));
/*
for img in &self.img_data_vec {
Self::save_to_image(img.to_owned());
pb.inc(1);
}
pb.finish();
*/
self.img_data_vec
.drain(..)
.collect::<Vec<_>>()
.par_iter()
.progress_with(pb)
.for_each(|img| {
// Self::save_to_image(img.to_owned());
img.save_to_image();
.for_each(|(i, img)| {
img.to_image()
.save(format!("./tmp/out_{}.png", i).as_str())
.unwrap();
});
}
/*
pub fn save_to_image(imgdata: ImgData) {
let (width, height) = (imgdata.grids[0].width, imgdata.grids[0].height);
let mut img = image::RgbImage::new(width as u32, height as u32);
let max_values: Vec<_> = imgdata
.grids
.iter()
.map(|grid| grid.quantile(0.999) * 1.5)
.collect();
for y in 0..height {
for x in 0..width {
let i = y * width + x;
let (mut r, mut g, mut b) = (0.0_f32, 0.0_f32, 0.0_f32);
for (grid, max_value, color) in
multizip((&imgdata.grids, &max_values, &imgdata.palette.colors))
{
let mut t = (grid.data()[i] / max_value).clamp(0.0, 1.0);
t = t.powf(1.0 / 2.2); // gamma correction
r += color.0[0] as f32 * t;
g += color.0[1] as f32 * t;
b += color.0[2] as f32 * t;
}
r = r.clamp(0.0, 255.0);
g = g.clamp(0.0, 255.0);
b = b.clamp(0.0, 255.0);
img.put_pixel(x as u32, y as u32, image::Rgb([r as u8, g as u8, b as u8]));
}
}
img.save(format!("./tmp/out_{}.png", imgdata.iteration).as_str())
.unwrap();
}
*/
}