Skip to content

Commit

Permalink
Prep new release
Browse files Browse the repository at this point in the history
- Add documentation for looping feature

- Generalize impl of Config::read_loop

- Fix bug with empty ident under looping

- Update changelog, licence and readme
  • Loading branch information
tgblackburn committed Jan 23, 2023
1 parent fba172f commit aa118c0
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 21 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ptarmigan"
version = "1.1.0"
version = "1.2.0"
authors = ["tgblackburn"]
edition = "2018"
publish = false
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright 2020 Tom Blackburn
Copyright 2020 The Ptarmigan contributors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,13 @@ will run the code, parallelized over `np` MPI tasks (if MPI support has been ena
The code bins the final-state particles to generate the distribution functions requested in the input file, which are written in plain-text or FITS format.

If `hdf5-output` is enabled, complete data about all particles can be written as a single HDF5 file.


## Contribute

Pull requests, bug fixes and new features, are welcome!

Contributors:

* Tom Blackburn
* Kyle Fleck
8 changes: 8 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## v1.2.0

2023-01-23

Added:

* Looping over a range of a0s (PR #45).

## v1.1.0

2023-01-13
Expand Down
1 change: 1 addition & 0 deletions docs/input.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Tracking:

* `a0`: the laser strength parameter, normalized amplitude, etc.
Defined by the peak electric field, so a0 is sqrt(2) larger for LP than for CP at fixed intensity.
Alternatively, specifying `a0:start`, `a0:step` and `a0:stop` will run a single simulation for all a0 values in the given range.
* `wavelength`: of the carrier wave, in metres, or
* `omega`: the equivalent photon energy, in joules. The conversion constants `eV` etc are provided for convenience.
* `waist` (optional): if specified, the laser pulse will be focused to a spot size of `waist`, which defines the radius at which the intensity falls to 1/e^2 of its maximum value. Otherwise the laser is modelled as a plane wave.
Expand Down
52 changes: 36 additions & 16 deletions src/input/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// use std::fmt;
// use std::error::Error;
use std::path::Path;
use std::ops::Add;
use yaml_rust::{YamlLoader, yaml::Yaml};
use meval::Context;

Expand Down Expand Up @@ -128,7 +129,7 @@ impl<'a> Config<'a> {
self
}

/// Locates a key-value pair in the configuration file and attempts the
/// Locates a key-value pair in the configuration file and attempts
/// to parse the value as the specified type.
/// The path to the key-value pair is specified by a string of colon-separated
/// sections, e.g. `'section:subsection:subsubsection:key'`.
Expand Down Expand Up @@ -184,25 +185,44 @@ impl<'a> Config<'a> {
.ok()
}

/// Uses 'Config::read' to determine if a0 is to be looped over. If a "start" key is given,
/// assumes that a0 will be looped over.
#[allow(unused)]
pub fn read_loop<S: AsRef<str> + std::fmt::Display>(&self, path: S) -> Result<Vec<f64>, InputError> {
if self.read::<f64, &str>(format!("{}{}", path, ":start").as_str()).is_err() {
let value: f64 = self.read(path)?;
let v: Vec<f64> = vec![value; 1];
/// Locates a key-value pair in the configuration file and attempts
/// to parse it as a looped variable, returning a Vec of the values.
/// The loop is defined by a `start`, `stop` and `step`:
///
/// ```
/// let text: &str = "---
/// x:
/// start: 1.0
/// stop: 1.5
/// step: 0.1
/// ";
///
/// let values: Vec<f64> = Config::from_string(&text).unwrap()
/// .read_loop("x").unwrap();
///
/// assert_eq!(values, vec![1.0, 1.1, 1.2, 1.3, 1.4, 1.5]);
/// ```
pub fn read_loop<T, S>(&self, path: S) -> Result<Vec<T>, InputError>
where
T: FromYaml + PartialOrd + Add<Output=T> + Copy,
S: AsRef<str> {
let key = path.as_ref();

if self.read::<T, _>(format!("{}{}", key, ":start").as_str()).is_err() {
let value = self.read(path)?;
let v = vec![value];
Ok(v)
}
else { // 'start' value found
let start: f64 = self.read(format!("{}{}", path, ":start").as_str())?;
let stop: f64 = self.read(format!("{}{}", path, ":stop").as_str())?;
let step: f64 = self.read(format!("{}{}", path, ":step").as_str())?;
let start = self.read(format!("{}{}", key, ":start").as_str())?;
let stop = self.read(format!("{}{}", key, ":stop").as_str())?;
let step = self.read(format!("{}{}", key, ":step").as_str())?;

let mut v: Vec<f64> = Vec::new();
let mut x: f64 = start;
let mut v: Vec<T> = Vec::new();
let mut x = start;
while x <= stop {
v.push(x);
x += step;
x = x + step;
}
Ok(v)
}
Expand Down Expand Up @@ -290,7 +310,7 @@ mod tests {
";
let mut config = Config::from_string(&text).unwrap();
//config.with_context("constants");
let a0_values1 = config.read_loop("laser:a0").unwrap();
let a0_values1: Vec<f64> = config.read_loop("laser:a0").unwrap();
assert_eq!(a0_values1, vec![10.0; 1]);

// Test extraction of looped values
Expand All @@ -303,7 +323,7 @@ mod tests {
";
config = Config::from_string(&text).unwrap();
//config.with_context("constants");
let a0_values = config.read_loop("laser:a0").unwrap();
let a0_values: Vec<f64> = config.read_loop("laser:a0").unwrap();
assert_eq!(a0_values, vec![1.0, 3.0, 5.0, 7.0, 9.0]);
}

Expand Down
7 changes: 5 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,7 @@ fn main() -> Result<(), Box<dyn Error>> {
})?;

// Simulation building and running starts here
for a0_v in a0_values.iter() {
for (run, a0_v) in a0_values.iter().enumerate() {
let a0: f64 = *a0_v;
// Rare event sampling for pair creation
let pair_rate_increase = input.read::<f64,_>("control:increase_pair_rate_by")
Expand Down Expand Up @@ -625,6 +625,9 @@ fn main() -> Result<(), Box<dyn Error>> {

if id == 0 {
println!("Running {} task{} with {} primary particles per task...", ntasks, if ntasks > 1 {"s"} else {""}, num);
if a0_values.len() > 1 {
println!("\t* sim {} of {} at a0 = {}", run + 1, a0_values.len(), a0);
}
#[cfg(feature = "with-mpi")] {
println!("\t* with MPI support enabled");
}
Expand Down Expand Up @@ -760,7 +763,7 @@ fn main() -> Result<(), Box<dyn Error>> {

// Updating 'ident' in case of a0 looping
let current_ident: String = if a0_values.len() > 1 {
format!("{}_a0_{:.3}", ident, a0)
format!("{}{}a0_{:.3}", ident, if ident.is_empty() {""} else {"_"}, a0)
}
else {
ident.to_owned()
Expand Down

0 comments on commit aa118c0

Please sign in to comment.