2020-04-11 13:19:34 +00:00
|
|
|
#![feature(str_strip)]
|
2020-04-02 19:36:56 +00:00
|
|
|
use sbp::utils::json_to_grids;
|
2020-03-31 22:08:55 +00:00
|
|
|
use sbp::*;
|
2020-04-02 19:36:56 +00:00
|
|
|
use structopt::StructOpt;
|
2020-03-31 22:08:55 +00:00
|
|
|
|
2020-04-13 11:31:01 +00:00
|
|
|
mod file;
|
|
|
|
use file::*;
|
|
|
|
|
2020-04-12 22:00:27 +00:00
|
|
|
struct System {
|
2020-03-31 22:08:55 +00:00
|
|
|
fnow: Vec<euler::Field>,
|
|
|
|
fnext: Vec<euler::Field>,
|
2020-04-12 19:32:20 +00:00
|
|
|
wb: Vec<euler::WorkBuffers>,
|
2020-03-31 22:08:55 +00:00
|
|
|
k: [Vec<euler::Field>; 4],
|
2020-04-03 22:29:02 +00:00
|
|
|
grids: Vec<grid::Grid>,
|
2020-04-12 22:00:27 +00:00
|
|
|
metrics: Vec<Metrics>,
|
2020-04-02 19:36:56 +00:00
|
|
|
bt: Vec<euler::BoundaryCharacteristics>,
|
2020-04-10 10:30:18 +00:00
|
|
|
eb: Vec<euler::BoundaryStorage>,
|
2020-04-06 20:11:35 +00:00
|
|
|
time: Float,
|
2020-04-13 18:56:29 +00:00
|
|
|
interpolation_operators: Vec<euler::InterpolationOperators>,
|
2020-03-31 22:08:55 +00:00
|
|
|
}
|
|
|
|
|
2020-04-12 22:00:27 +00:00
|
|
|
enum Metrics {
|
2020-04-12 22:56:53 +00:00
|
|
|
Upwind4(grid::Metrics<operators::Upwind4, operators::Upwind4>),
|
|
|
|
Upwind9(grid::Metrics<operators::Upwind9, operators::Upwind9>),
|
|
|
|
Upwind4h2(grid::Metrics<operators::Upwind4h2, operators::Upwind4h2>),
|
|
|
|
Trad4(grid::Metrics<operators::SBP4, operators::SBP4>),
|
|
|
|
Trad8(grid::Metrics<operators::SBP8, operators::SBP8>),
|
2020-04-13 11:26:51 +00:00
|
|
|
|
|
|
|
Upwind4Upwind4h2(grid::Metrics<operators::Upwind4, operators::Upwind4h2>),
|
|
|
|
Upwind4h2Upwind4(grid::Metrics<operators::Upwind4h2, operators::Upwind4>),
|
2020-04-12 22:00:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl System {
|
|
|
|
fn new(
|
|
|
|
grids: Vec<grid::Grid>,
|
|
|
|
bt: Vec<euler::BoundaryCharacteristics>,
|
2020-04-13 18:56:29 +00:00
|
|
|
interpolation_operators: Vec<euler::InterpolationOperators>,
|
2020-04-13 11:26:51 +00:00
|
|
|
operatorx: &str,
|
|
|
|
operatory: &str,
|
2020-04-12 22:00:27 +00:00
|
|
|
) -> Self {
|
2020-03-31 22:08:55 +00:00
|
|
|
let fnow = grids
|
|
|
|
.iter()
|
|
|
|
.map(|g| euler::Field::new(g.ny(), g.nx()))
|
|
|
|
.collect::<Vec<_>>();
|
|
|
|
let fnext = fnow.clone();
|
|
|
|
let wb = grids
|
|
|
|
.iter()
|
2020-04-12 19:32:20 +00:00
|
|
|
.map(|g| euler::WorkBuffers::new(g.ny(), g.nx()))
|
2020-03-31 22:08:55 +00:00
|
|
|
.collect();
|
|
|
|
let k = [fnow.clone(), fnow.clone(), fnow.clone(), fnow.clone()];
|
2020-04-12 22:00:27 +00:00
|
|
|
let metrics = grids
|
|
|
|
.iter()
|
2020-04-13 11:26:51 +00:00
|
|
|
.map(|g| match (operatorx, operatory) {
|
|
|
|
("upwind4", "upwind4") => Metrics::Upwind4(
|
2020-04-12 22:56:53 +00:00
|
|
|
g.metrics::<operators::Upwind4, operators::Upwind4>()
|
|
|
|
.unwrap(),
|
|
|
|
),
|
2020-04-13 11:26:51 +00:00
|
|
|
("upwind9", "upwind9") => Metrics::Upwind9(
|
2020-04-12 22:56:53 +00:00
|
|
|
g.metrics::<operators::Upwind9, operators::Upwind9>()
|
|
|
|
.unwrap(),
|
|
|
|
),
|
2020-04-13 11:26:51 +00:00
|
|
|
("upwind4h2", "upwind4h2") => Metrics::Upwind4h2(
|
2020-04-12 22:56:53 +00:00
|
|
|
g.metrics::<operators::Upwind4h2, operators::Upwind4h2>()
|
|
|
|
.unwrap(),
|
|
|
|
),
|
2020-04-13 11:26:51 +00:00
|
|
|
("trad4", "trad4") => {
|
|
|
|
Metrics::Trad4(g.metrics::<operators::SBP4, operators::SBP4>().unwrap())
|
|
|
|
}
|
|
|
|
("trad8", "trad8") => {
|
|
|
|
Metrics::Trad8(g.metrics::<operators::SBP8, operators::SBP8>().unwrap())
|
|
|
|
}
|
|
|
|
("upwind4", "upwind4h2") => Metrics::Upwind4Upwind4h2(
|
|
|
|
g.metrics::<operators::Upwind4, operators::Upwind4h2>()
|
|
|
|
.unwrap(),
|
|
|
|
),
|
|
|
|
("upwind4h2", "upwind4") => Metrics::Upwind4h2Upwind4(
|
|
|
|
g.metrics::<operators::Upwind4h2, operators::Upwind4>()
|
|
|
|
.unwrap(),
|
|
|
|
),
|
|
|
|
(opx, opy) => panic!("operator combination {}x{} not known", opx, opy),
|
2020-04-12 22:00:27 +00:00
|
|
|
})
|
|
|
|
.collect::<Vec<_>>();
|
|
|
|
|
2020-04-06 20:11:35 +00:00
|
|
|
let eb = bt
|
|
|
|
.iter()
|
|
|
|
.zip(&grids)
|
2020-04-10 10:30:18 +00:00
|
|
|
.map(|(bt, grid)| euler::BoundaryStorage::new(bt, grid))
|
2020-04-06 20:11:35 +00:00
|
|
|
.collect();
|
2020-03-31 22:08:55 +00:00
|
|
|
|
|
|
|
Self {
|
|
|
|
fnow,
|
|
|
|
fnext,
|
|
|
|
k,
|
|
|
|
wb,
|
|
|
|
grids,
|
2020-04-03 22:29:02 +00:00
|
|
|
metrics,
|
2020-04-02 19:36:56 +00:00
|
|
|
bt,
|
2020-04-06 20:11:35 +00:00
|
|
|
eb,
|
|
|
|
time: 0.0,
|
2020-04-13 18:56:29 +00:00
|
|
|
interpolation_operators,
|
2020-03-31 22:08:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn vortex(&mut self, t: Float, vortex_params: euler::VortexParameters) {
|
|
|
|
for (f, g) in self.fnow.iter_mut().zip(&self.grids) {
|
|
|
|
f.vortex(g.x(), g.y(), t, vortex_params);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-12 10:35:16 +00:00
|
|
|
fn advance(&mut self, dt: Float, pool: &rayon::ThreadPool) {
|
2020-04-12 22:00:27 +00:00
|
|
|
let metrics = &self.metrics;
|
2020-04-13 16:39:21 +00:00
|
|
|
let grids = &self.grids;
|
|
|
|
let bt = &self.bt;
|
|
|
|
let wb = &mut self.wb;
|
|
|
|
let mut eb = &mut self.eb;
|
2020-04-13 18:56:29 +00:00
|
|
|
let intops = &self.interpolation_operators;
|
2020-04-13 16:39:21 +00:00
|
|
|
|
2020-04-12 10:35:16 +00:00
|
|
|
let rhs = move |fut: &mut [euler::Field],
|
|
|
|
prev: &[euler::Field],
|
|
|
|
time: Float,
|
2020-04-13 16:39:21 +00:00
|
|
|
_c: (),
|
|
|
|
_mt: &mut ()| {
|
2020-04-13 18:56:29 +00:00
|
|
|
let bc = euler::extract_boundaries(prev, &bt, &mut eb, &grids, time, Some(intops));
|
2020-04-12 10:35:16 +00:00
|
|
|
pool.scope(|s| {
|
|
|
|
for ((((fut, prev), bc), wb), metrics) in fut
|
|
|
|
.iter_mut()
|
|
|
|
.zip(prev.iter())
|
|
|
|
.zip(bc)
|
|
|
|
.zip(wb.iter_mut())
|
|
|
|
.zip(metrics.iter())
|
2020-04-02 21:36:20 +00:00
|
|
|
{
|
2020-04-12 22:00:27 +00:00
|
|
|
s.spawn(move |_| match metrics {
|
|
|
|
Metrics::Upwind4(metrics) => {
|
|
|
|
euler::RHS_upwind(fut, prev, metrics, &bc, &mut wb.0)
|
|
|
|
}
|
|
|
|
Metrics::Upwind9(metrics) => {
|
|
|
|
euler::RHS_upwind(fut, prev, metrics, &bc, &mut wb.0)
|
|
|
|
}
|
|
|
|
Metrics::Upwind4h2(metrics) => {
|
|
|
|
euler::RHS_upwind(fut, prev, metrics, &bc, &mut wb.0)
|
|
|
|
}
|
|
|
|
Metrics::Trad4(metrics) => {
|
|
|
|
euler::RHS_trad(fut, prev, metrics, &bc, &mut wb.0)
|
|
|
|
}
|
|
|
|
Metrics::Trad8(metrics) => {
|
|
|
|
euler::RHS_trad(fut, prev, metrics, &bc, &mut wb.0)
|
|
|
|
}
|
2020-04-13 11:26:51 +00:00
|
|
|
Metrics::Upwind4Upwind4h2(metrics) => {
|
|
|
|
euler::RHS_trad(fut, prev, metrics, &bc, &mut wb.0)
|
|
|
|
}
|
|
|
|
Metrics::Upwind4h2Upwind4(metrics) => {
|
|
|
|
euler::RHS_trad(fut, prev, metrics, &bc, &mut wb.0)
|
|
|
|
}
|
2020-04-12 22:00:27 +00:00
|
|
|
});
|
2020-04-02 21:36:20 +00:00
|
|
|
}
|
|
|
|
});
|
2020-04-12 10:35:16 +00:00
|
|
|
};
|
2020-04-12 22:00:27 +00:00
|
|
|
|
2020-04-12 10:35:16 +00:00
|
|
|
let mut k = self
|
|
|
|
.k
|
|
|
|
.iter_mut()
|
|
|
|
.map(|k| k.as_mut_slice())
|
|
|
|
.collect::<Vec<_>>();
|
|
|
|
sbp::integrate::integrate_multigrid::<sbp::integrate::Rk4, _, _, _, _>(
|
|
|
|
rhs,
|
|
|
|
&self.fnow,
|
|
|
|
&mut self.fnext,
|
|
|
|
&mut self.time,
|
|
|
|
dt,
|
|
|
|
&mut k,
|
2020-04-13 16:39:21 +00:00
|
|
|
(),
|
|
|
|
&mut (),
|
2020-04-12 10:35:16 +00:00
|
|
|
pool,
|
|
|
|
);
|
|
|
|
|
|
|
|
std::mem::swap(&mut self.fnow, &mut self.fnext);
|
2020-04-02 21:36:20 +00:00
|
|
|
}
|
2020-03-31 22:08:55 +00:00
|
|
|
}
|
2020-04-06 20:32:36 +00:00
|
|
|
|
2020-04-02 19:36:56 +00:00
|
|
|
#[derive(Debug, StructOpt)]
|
|
|
|
struct Options {
|
|
|
|
json: std::path::PathBuf,
|
2020-04-03 20:30:30 +00:00
|
|
|
/// Disable the progressbar
|
|
|
|
#[structopt(long)]
|
2020-04-02 20:32:07 +00:00
|
|
|
no_progressbar: bool,
|
2020-04-03 20:30:30 +00:00
|
|
|
/// Number of simultaneous threads
|
|
|
|
#[structopt(short, long)]
|
|
|
|
jobs: Option<Option<usize>>,
|
2020-04-04 20:14:15 +00:00
|
|
|
/// Name of output file
|
2020-04-10 09:53:37 +00:00
|
|
|
#[structopt(default_value = "output.hdf", long, short)]
|
2020-04-04 20:14:15 +00:00
|
|
|
output: std::path::PathBuf,
|
2020-04-07 21:25:19 +00:00
|
|
|
/// Number of outputs to save
|
|
|
|
#[structopt(long, short)]
|
|
|
|
number_of_outputs: Option<u64>,
|
2020-04-08 18:04:12 +00:00
|
|
|
/// Print the time to complete, taken in the compute loop
|
|
|
|
#[structopt(long)]
|
|
|
|
timings: bool,
|
2020-04-08 18:19:50 +00:00
|
|
|
/// Print error at the end of the run
|
|
|
|
#[structopt(long)]
|
|
|
|
error: bool,
|
2020-03-31 22:08:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn main() {
|
2020-04-08 18:19:50 +00:00
|
|
|
type SBP = operators::Upwind4;
|
2020-04-02 19:36:56 +00:00
|
|
|
let opt = Options::from_args();
|
|
|
|
let filecontents = std::fs::read_to_string(&opt.json).unwrap();
|
2020-03-31 22:08:55 +00:00
|
|
|
|
2020-04-02 19:36:56 +00:00
|
|
|
let json = json::parse(&filecontents).unwrap();
|
|
|
|
let jgrids = json_to_grids(json["grids"].clone()).unwrap();
|
2020-04-06 20:11:35 +00:00
|
|
|
let vortexparams = utils::json_to_vortex(json["vortex"].clone());
|
2020-03-31 22:08:55 +00:00
|
|
|
|
2020-04-02 19:36:56 +00:00
|
|
|
let mut bt = Vec::with_capacity(jgrids.len());
|
2020-04-11 13:19:34 +00:00
|
|
|
let determine_bc = |dir: Option<&String>| match dir {
|
2020-04-06 20:11:35 +00:00
|
|
|
Some(dir) => {
|
|
|
|
if dir == "vortex" {
|
|
|
|
euler::BoundaryCharacteristic::Vortex(vortexparams)
|
2020-04-11 13:19:34 +00:00
|
|
|
} else if let Some(grid) = dir.strip_prefix("interpolate:") {
|
|
|
|
euler::BoundaryCharacteristic::Interpolate(
|
|
|
|
jgrids
|
|
|
|
.iter()
|
|
|
|
.position(|other| other.name.as_ref().map_or(false, |name| name == grid))
|
|
|
|
.unwrap(),
|
|
|
|
)
|
2020-04-06 20:11:35 +00:00
|
|
|
} else {
|
|
|
|
euler::BoundaryCharacteristic::Grid(
|
|
|
|
jgrids
|
|
|
|
.iter()
|
|
|
|
.position(|other| other.name.as_ref().map_or(false, |name| name == dir))
|
|
|
|
.unwrap(),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
2020-04-02 19:36:56 +00:00
|
|
|
None => euler::BoundaryCharacteristic::This,
|
|
|
|
};
|
|
|
|
for grid in &jgrids {
|
|
|
|
bt.push(euler::BoundaryCharacteristics {
|
|
|
|
north: determine_bc(grid.dirn.as_ref()),
|
|
|
|
south: determine_bc(grid.dirs.as_ref()),
|
|
|
|
east: determine_bc(grid.dire.as_ref()),
|
|
|
|
west: determine_bc(grid.dirw.as_ref()),
|
|
|
|
});
|
|
|
|
}
|
2020-04-13 18:56:29 +00:00
|
|
|
let interpolation_operators = jgrids
|
|
|
|
.iter()
|
|
|
|
.map(|_g| euler::InterpolationOperators {
|
|
|
|
north: Some(Box::new(operators::Interpolation4)),
|
|
|
|
south: Some(Box::new(operators::Interpolation4)),
|
|
|
|
east: Some(Box::new(operators::Interpolation4)),
|
|
|
|
west: Some(Box::new(operators::Interpolation4)),
|
|
|
|
})
|
|
|
|
.collect::<Vec<_>>();
|
2020-04-03 22:29:02 +00:00
|
|
|
let grids = jgrids.into_iter().map(|egrid| egrid.grid).collect();
|
|
|
|
|
2020-04-04 20:33:33 +00:00
|
|
|
let integration_time: Float = json["integration_time"].as_number().unwrap().into();
|
2020-03-31 22:08:55 +00:00
|
|
|
|
2020-04-13 11:26:51 +00:00
|
|
|
let (operatorx, operatory) = {
|
|
|
|
if json["operator"].is_object() {
|
|
|
|
(
|
|
|
|
json["operator"]["x"].as_str().unwrap(),
|
|
|
|
json["operator"]["y"].as_str().unwrap(),
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
let op = json["operator"].as_str().unwrap_or("upwind4");
|
|
|
|
(op, op)
|
|
|
|
}
|
|
|
|
};
|
2020-04-12 22:00:27 +00:00
|
|
|
|
2020-04-13 18:56:29 +00:00
|
|
|
let mut sys = System::new(grids, bt, interpolation_operators, operatorx, operatory);
|
2020-04-02 20:49:27 +00:00
|
|
|
sys.vortex(0.0, vortexparams);
|
2020-04-02 19:36:56 +00:00
|
|
|
|
|
|
|
let max_n = {
|
|
|
|
let max_nx = sys.grids.iter().map(|g| g.nx()).max().unwrap();
|
|
|
|
let max_ny = sys.grids.iter().map(|g| g.ny()).max().unwrap();
|
|
|
|
std::cmp::max(max_nx, max_ny)
|
|
|
|
};
|
|
|
|
let dt = 0.2 / (max_n as Float);
|
2020-04-02 20:32:07 +00:00
|
|
|
|
2020-04-04 20:14:15 +00:00
|
|
|
let ntime = (integration_time / dt).round() as u64;
|
2020-04-02 20:32:07 +00:00
|
|
|
|
2020-04-07 19:23:51 +00:00
|
|
|
let pool = {
|
2020-04-03 20:30:30 +00:00
|
|
|
let builder = rayon::ThreadPoolBuilder::new();
|
2020-04-07 19:23:51 +00:00
|
|
|
if let Some(j) = opt.jobs {
|
|
|
|
if let Some(j) = j {
|
|
|
|
builder.num_threads(j)
|
|
|
|
} else {
|
|
|
|
builder
|
|
|
|
}
|
2020-04-03 20:30:30 +00:00
|
|
|
} else {
|
2020-04-07 19:23:51 +00:00
|
|
|
builder.num_threads(1)
|
|
|
|
}
|
|
|
|
.build()
|
|
|
|
.unwrap()
|
2020-04-02 21:36:20 +00:00
|
|
|
};
|
|
|
|
|
2020-04-07 21:25:19 +00:00
|
|
|
let should_output = |itime| {
|
|
|
|
opt.number_of_outputs.map_or(false, |num_out| {
|
|
|
|
if num_out == 0 {
|
|
|
|
false
|
|
|
|
} else {
|
|
|
|
itime % (std::cmp::max(ntime / (num_out - 1), 1)) == 0
|
|
|
|
}
|
|
|
|
})
|
|
|
|
};
|
|
|
|
|
2020-04-07 18:35:00 +00:00
|
|
|
let output = File::create(&opt.output, sys.grids.as_slice()).unwrap();
|
2020-04-07 20:54:00 +00:00
|
|
|
let mut output = OutputThread::new(output);
|
2020-04-07 19:23:51 +00:00
|
|
|
|
2020-04-12 18:44:52 +00:00
|
|
|
let progressbar = progressbar(opt.no_progressbar, ntime);
|
2020-04-08 18:04:12 +00:00
|
|
|
|
|
|
|
let timer = if opt.timings {
|
|
|
|
Some(std::time::Instant::now())
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
|
2020-04-07 21:25:19 +00:00
|
|
|
for itime in 0..ntime {
|
|
|
|
if should_output(itime) {
|
|
|
|
output.add_timestep(itime, &sys.fnow);
|
|
|
|
}
|
2020-04-12 18:44:52 +00:00
|
|
|
progressbar.inc(1);
|
2020-04-07 19:23:51 +00:00
|
|
|
sys.advance(dt, &pool);
|
2020-04-01 20:37:01 +00:00
|
|
|
}
|
2020-04-12 18:44:52 +00:00
|
|
|
progressbar.finish_and_clear();
|
2020-04-01 20:37:01 +00:00
|
|
|
|
2020-04-08 18:04:12 +00:00
|
|
|
if let Some(timer) = timer {
|
|
|
|
let duration = timer.elapsed();
|
|
|
|
println!("Time elapsed: {} seconds", duration.as_secs_f64());
|
|
|
|
}
|
|
|
|
|
2020-04-07 20:54:00 +00:00
|
|
|
output.add_timestep(ntime, &sys.fnow);
|
2020-04-08 18:19:50 +00:00
|
|
|
if opt.error {
|
2020-04-11 13:19:34 +00:00
|
|
|
let time = ntime as Float * dt;
|
2020-04-08 18:19:50 +00:00
|
|
|
let mut e = 0.0;
|
|
|
|
for (fmod, grid) in sys.fnow.iter().zip(&sys.grids) {
|
|
|
|
let mut fvort = fmod.clone();
|
|
|
|
fvort.vortex(grid.x(), grid.y(), time, vortexparams);
|
|
|
|
e += fmod.h2_err::<SBP>(&fvort);
|
|
|
|
}
|
|
|
|
println!("Total error: {:e}", e);
|
|
|
|
}
|
2020-04-01 20:37:01 +00:00
|
|
|
}
|
|
|
|
|
2020-04-06 20:42:44 +00:00
|
|
|
fn progressbar(dummy: bool, ntime: u64) -> indicatif::ProgressBar {
|
|
|
|
if dummy {
|
|
|
|
indicatif::ProgressBar::hidden()
|
|
|
|
} else {
|
2020-04-12 18:44:52 +00:00
|
|
|
let progressbar = indicatif::ProgressBar::new(ntime);
|
|
|
|
progressbar.with_style(
|
2020-04-06 20:42:44 +00:00
|
|
|
indicatif::ProgressStyle::default_bar()
|
|
|
|
.template("{wide_bar:.cyan/blue} {pos}/{len} ({eta})"),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|