167 lines
4.3 KiB
Rust
167 lines
4.3 KiB
Rust
#![allow(dead_code)]
|
|
|
|
use crate::{fractal::fractal_dimension, parser::read_file};
|
|
use std::process;
|
|
use structopt::StructOpt;
|
|
|
|
use ansi_term::Color::Yellow;
|
|
|
|
pub mod constants;
|
|
pub mod fractal;
|
|
pub mod parser;
|
|
pub mod search;
|
|
|
|
/// Compute fractal dimension of crystallographic packings via the circle counting method
|
|
#[derive(StructOpt)]
|
|
#[structopt(name = "Circle Counter")]
|
|
struct Opt {
|
|
/// File containing data in the order generators, root, faces
|
|
#[structopt(name = "data file")]
|
|
data_file: String,
|
|
|
|
/// Activate debug mode
|
|
#[structopt(short, long)]
|
|
debug: bool,
|
|
|
|
/// Number of sample points in linear regression
|
|
#[structopt(short, long, default_value = "50")]
|
|
n: usize,
|
|
|
|
/// Maximum curvature of circles
|
|
#[structopt(short, long, default_value = "1000000")]
|
|
max: f64,
|
|
|
|
/// Whether or not to time excecution (automatically enabled by --debug)
|
|
#[structopt(short, long)]
|
|
time: bool,
|
|
|
|
/// Cap on the recursion depth (0 means no cap)
|
|
#[structopt(short, long, default_value = "0")]
|
|
depth: usize,
|
|
|
|
/// Whether the generators given are geometric or algebraic generators (defaults to algebraic)
|
|
#[structopt(short, long)]
|
|
geometric: bool,
|
|
}
|
|
|
|
fn main() {
|
|
let opt = Opt::from_args();
|
|
let debug = opt.debug;
|
|
let time = debug || opt.time;
|
|
let depth = opt.depth;
|
|
|
|
let beginning = std::time::Instant::now();
|
|
|
|
let (mut generators, root, faces, orthogonal_generators) = read_file(&opt.data_file)
|
|
.unwrap_or_else(|err| {
|
|
eprintln!("{}", err);
|
|
process::exit(-1);
|
|
});
|
|
|
|
let after_parsing = std::time::Instant::now();
|
|
if time {
|
|
let duration = after_parsing.duration_since(beginning);
|
|
println!(
|
|
"Took {}s to parse {}",
|
|
duration.as_secs_f64(),
|
|
opt.data_file
|
|
);
|
|
}
|
|
|
|
if debug {
|
|
println!(
|
|
"{} (parsed from command args):\t{}",
|
|
Yellow.paint("max"),
|
|
opt.max
|
|
);
|
|
println!(
|
|
"{} (parsed from command args):\t{}",
|
|
Yellow.paint("n"),
|
|
opt.n
|
|
);
|
|
}
|
|
|
|
if !opt.geometric {
|
|
let c = nalgebra::DMatrix::from_columns(&root);
|
|
let ct = c
|
|
.clone()
|
|
.pseudo_inverse(1e-5)
|
|
.expect(format!("Invalid root matrix {}", c).as_str());
|
|
println!("{}", ct);
|
|
|
|
generators = generators
|
|
.iter()
|
|
.map(|sigma| &c * sigma.transpose() * &ct)
|
|
.collect();
|
|
}
|
|
|
|
if debug {
|
|
println!(
|
|
"{} (parsed from file {})",
|
|
Yellow.paint("Generators"),
|
|
opt.data_file
|
|
);
|
|
for generator in &generators {
|
|
println!("{}", generator);
|
|
}
|
|
println!(
|
|
"{} (parsed from file {}):",
|
|
Yellow.paint("Root Tuple"),
|
|
opt.data_file
|
|
);
|
|
for circle in &root {
|
|
println!("{}", circle);
|
|
}
|
|
println!(
|
|
"{} (parsed from file {}):",
|
|
Yellow.paint("Faces"),
|
|
opt.data_file
|
|
);
|
|
println!("{:?}\n", faces);
|
|
println!(
|
|
"{} (parsed from file {}):",
|
|
Yellow.paint("Orthogonal Generators"),
|
|
opt.data_file
|
|
);
|
|
println!("{:?}\n", orthogonal_generators);
|
|
}
|
|
|
|
let delta = fractal_dimension(
|
|
generators,
|
|
root,
|
|
opt.max,
|
|
opt.n,
|
|
debug,
|
|
depth,
|
|
faces,
|
|
orthogonal_generators,
|
|
)
|
|
.unwrap();
|
|
let after_computing = std::time::Instant::now();
|
|
if time {
|
|
let duration1 = after_computing.duration_since(after_parsing);
|
|
let duration2 = after_computing.duration_since(beginning);
|
|
|
|
let time1 = duration1.as_secs_f64();
|
|
let time2 = duration2.as_secs_f64();
|
|
|
|
let seconds1 = time1 % 60.0;
|
|
let seconds2 = time2 % 60.0;
|
|
|
|
let minutes1 = (time1 as isize) / 60;
|
|
let minutes2 = (time2 as isize) / 60;
|
|
|
|
if minutes1 > 0 {
|
|
println!(
|
|
"\nTook {}m {}s to compute fractal dimension; {}m {}s total",
|
|
minutes1, seconds1, minutes2, seconds2
|
|
);
|
|
} else {
|
|
println!(
|
|
"\nTook {}s to compute fractal dimension; {}s total",
|
|
seconds1, seconds2,
|
|
);
|
|
}
|
|
}
|
|
println!("\n{}", delta);
|
|
}
|