Skip to content

Commit

Permalink
Add documentation for remaining objects and fix warnings
Browse files Browse the repository at this point in the history
  • Loading branch information
ThomasdenH committed Jul 5, 2018
1 parent b791adf commit 6d485de
Show file tree
Hide file tree
Showing 10 changed files with 80 additions and 15 deletions.
2 changes: 2 additions & 0 deletions src/fields/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ mod scalarfield;
mod scaledvectorfield;
mod vectorfield;



pub use self::scalarfield::ScalarField;
pub use self::scaledvectorfield::ScaledVectorField;
pub use self::vectorfield::VectorField;
4 changes: 4 additions & 0 deletions src/fields/scalarfield.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use nalgebra::*;
use std::ops::{Add, AddAssign, Index, IndexMut, Mul, MulAssign, Sub, SubAssign};

/// On a grid of a certain size, a scalar is located on every coordinate.
#[derive(PartialEq, Clone, Debug)]
pub struct ScalarField {
size: Vector3<usize>,
Expand All @@ -21,14 +22,17 @@ impl ScalarField {
self.scalars = self.scalars.map(|a| 1.0 / a);
}

/// Get the three-dimensional size of this field.
pub fn size(&self) -> Vector3<usize> {
self.size
}

/// Get the number of scalars in this field.
pub fn len(&self) -> usize {
self.scalars.len()
}

/// Get the scalars in this field.
pub fn scalars(&self) -> &DVector<f32> {
&self.scalars
}
Expand Down
10 changes: 4 additions & 6 deletions src/fields/scaledvectorfield.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,15 @@ pub struct ScaledVectorField<'a> {
}

impl<'a> ScaledVectorField<'a> {
/// Get the size of this field.
pub fn size(&self) -> Vector3<usize> {
self.field.size()
}

/// Get the number of vectors in this field.
pub fn len(&self) -> usize {
self.field.len()
}

pub fn field(&self) -> &VectorField {
self.field
}
}

impl<'a> Mul<f32> for &'a VectorField {
Expand Down Expand Up @@ -51,7 +49,7 @@ impl<'a, 'b> AddAssign<&'b ScaledVectorField<'a>> for VectorField {
debug_assert!(self.size() == other.size());
for (self_element, other_element) in self.vectors_mut()
.iter_mut()
.zip(other.field().vectors().iter())
.zip(other.field.vectors().iter())
{
*self_element += other.scalar * other_element
}
Expand All @@ -63,7 +61,7 @@ impl<'a, 'b> SubAssign<&'b ScaledVectorField<'a>> for VectorField {
debug_assert!(self.size() == other.size());
for (self_element, other_element) in self.vectors_mut()
.iter_mut()
.zip(other.field().vectors().iter())
.zip(other.field.vectors().iter())
{
*self_element -= other.scalar * other_element
}
Expand Down
11 changes: 11 additions & 0 deletions src/fields/vectorfield.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ use std::ops::{Add, AddAssign, Div, Index, IndexMut, Mul, Neg, Sub, SubAssign};

use fields::ScalarField;

/// Represents a vector field. It has a certain size, with a vector on every coordinate on the grid.
#[derive(PartialEq, Clone, Debug)]
pub struct VectorField {
size: Vector3<usize>,
vectors: DVector<Vector3<f32>>,
}

impl VectorField {
/// Create a new `VectorField` filled with (0, 0, 0) with a certain `size`.
pub fn new(size: Vector3<usize>) -> VectorField {
VectorField {
size,
Expand Down Expand Up @@ -42,6 +44,7 @@ impl VectorField {
}
}

/// Same as `curl_positive`, but uses no allocations and recycles a `VectorField` instead.
pub fn curl_positive_to(&self, mut to: VectorField) -> VectorField {
debug_assert!(self.size() == to.size());
for x in 0..self.size.x as isize {
Expand All @@ -61,6 +64,8 @@ impl VectorField {
to
}

/// Calculates the negative curl of a vector field. The new positions will be the centers of the
/// Yee grid planes formed between four grid edges.
pub fn curl_negative(&self) -> VectorField {
VectorField {
size: self.size,
Expand All @@ -84,6 +89,7 @@ impl VectorField {
}
}

/// Same as `curl_negative`, but uses no allocations and recycles a `VectorField` instead.
pub fn curl_negative_to(&self, mut to: VectorField) -> VectorField {
debug_assert!(self.size() == to.size());
for x in 0..self.size.x as isize {
Expand All @@ -103,14 +109,17 @@ impl VectorField {
to
}

/// Returns the size in three dimensions of this field.
pub fn size(&self) -> Vector3<usize> {
self.size
}

/// Returns the number of vectors in this field.
pub fn len(&self) -> usize {
self.vectors.len()
}

/// Clone the components of this vector field to the vector field `other`.
pub fn clone_to(&self, mut other: VectorField) -> VectorField {
debug_assert!(self.size() == other.size());
for i in 0..self.vectors.len() {
Expand All @@ -119,10 +128,12 @@ impl VectorField {
other
}

/// Returns the vectors in this field in an immutable way.
pub fn vectors(&self) -> &DVector<Vector3<f32>> {
&self.vectors
}

/// Returns the vectors inside this field in a mutable way.
pub fn vectors_mut(&mut self) -> &mut DVector<Vector3<f32>> {
&mut self.vectors
}
Expand Down
30 changes: 24 additions & 6 deletions src/greenfunctions/cosinebasis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,19 @@ use std::f32::consts::PI;
use std::io::Stdout;
use std::sync::{Arc, Mutex};

/// Determines a direction in space.
#[derive(Eq, PartialEq, Copy, Clone, Hash, Debug)]
pub enum Direction {
X,
Y,
Z,
NegX,
NegY,
NegZ,
#[allow(missing_docs)] X,
#[allow(missing_docs)] Y,
#[allow(missing_docs)] Z,
#[allow(missing_docs)] NegX,
#[allow(missing_docs)] NegY,
#[allow(missing_docs)] NegZ,
}

impl Direction {
/// Converts a `Direction` to a normalized normal vector in that direction.
fn vector(self) -> Vector3<f32> {
match self {
Direction::X => Vector3::new(1.0, 0.0, 0.0),
Expand All @@ -30,6 +32,8 @@ impl Direction {
}
}

/// A `CosineBasis` can compute the casimir force for a bounding plane surface by expanding the
/// source as a cosine basis and measuring the response.
pub struct CosineBasis<'a> {
p0: Point3<usize>,
p1: Point3<usize>,
Expand Down Expand Up @@ -61,6 +65,8 @@ impl<'a> CosineBasis<'a> {
}
}

/// If this method is called with a progress bar, that progress bar will be updated as the force
/// is computed. If it is called with `None`, no progress bar will be used.
pub fn with_progress_bar(
mut self,
progress_bar: Option<Arc<Mutex<ProgressBar<Stdout>>>>,
Expand All @@ -69,6 +75,7 @@ impl<'a> CosineBasis<'a> {
self
}

/// Compute the force due to this basis.
pub fn force(&self) -> Vector3<f32> {
let (amax, bmax) = match self.normal {
Direction::X | Direction::NegX => (self.p1.y - self.p0.y, self.p1.z - self.p0.z),
Expand Down Expand Up @@ -109,6 +116,8 @@ impl<'a> CosineBasis<'a> {
total_force
}

/// Generate a cosine basis source. `na` and `nb` determine the number of the expansion, and
/// the `polarization` determines the component to set the source to.
fn get_source(&self, na: usize, nb: usize, polarization: Direction) -> VectorField {
let mut source_field = VectorField::new(self.permitivity.size());
match self.normal {
Expand Down Expand Up @@ -152,10 +161,14 @@ impl<'a> CosineBasis<'a> {
source_field
}

/// Computes the force for a particular basis by multiplying the stress tensor with the Green
/// tensor.
pub fn force_for_basis(&self, na: usize, nb: usize) -> Vector3<f32> {
self.stress_tensor(na, nb) * self.normal.vector()
}

/// Computes the stress tensor. When multiplied with a surface normal vector, this gives the
/// force between both sides of that surface.
pub fn stress_tensor(&self, na: usize, nb: usize) -> Matrix3<f32> {
let electric_tensor = self.green_tensor(na, nb, OperatorType::Electric);
let magnetic_tensor = self.green_tensor(na, nb, OperatorType::Magnetic);
Expand All @@ -165,6 +178,8 @@ impl<'a> CosineBasis<'a> {
* (electric_tensor - Matrix3::from_diagonal_element(0.5) * electric_tensor.trace()))
}

/// Computes the Green tensor, which has as columns the Green functions for different
/// polarizations.
pub fn green_tensor(&self, na: usize, nb: usize, operator_type: OperatorType) -> Matrix3<f32> {
Matrix3::from_columns(&[
self.green_function(&self.get_source(na, nb, Direction::X), operator_type),
Expand All @@ -173,6 +188,9 @@ impl<'a> CosineBasis<'a> {
])
}

/// Performs operator inversion using the conjugate gradient method to obtain the Green
/// functions due to the incoming `source`. The `operator_type` determines the type of operator
/// to use and thereby the type of Green function to compute.
pub fn green_function(
&self,
source: &VectorField,
Expand Down
4 changes: 4 additions & 0 deletions src/greenfunctions/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
/// This modele contains the functions required for the calculation of the force due to a cosine
/// source.
pub mod cosinebasis;
/// This module contains the electric and magnetic field operators that can be multiplied with a
/// vector field.
mod operator;
9 changes: 9 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
#![warn(missing_docs)]

//! `casimir-fdfd` is an implementation of a stress-tensor based FDFD method for computing Casimir
//! forces. Based on [Virtual photons in imaginary time: Computing exact Casimir forces via standard numerical-electromagnetism techniques](https://arxiv.org/abs/0705.3661).

#[macro_use]
extern crate failure;
extern crate nalgebra;
Expand All @@ -12,9 +17,13 @@ extern crate serde;
#[macro_use]
extern crate assert_approx_eq;

/// Contains the simulation configuration options.
pub mod config;
/// Contains the fields used in the simulation.
pub mod fields;
/// Contains the functions to compute Green functions and stress tensors.
pub mod greenfunctions;
/// Geometry and materials that describe the simulated environment.
pub mod world;

use clap::{App, Arg};
Expand Down
2 changes: 1 addition & 1 deletion src/world/material.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ mod tests {

#[test]
fn custom_serde() {
let material: DrudeMaterial = from_str(r#"{
let _: DrudeMaterial = from_str(r#"{
"omega_p": 7.79,
"omega_tau": 48.8,
"step": 0.1,
Expand Down
21 changes: 19 additions & 2 deletions src/world/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,23 @@ impl<'a> Iterator for ForceIterator<'a> {
/// These errors can be thrown when validating a world.
#[derive(Debug, Fail)]
pub enum WorldError {
/// An error indicating that one of the shapes is too close too the edge, causing the bounding
/// box to cross the boundary.
#[fail(display = "shape {} too close to edge", index)]
ShapeTooCloseToEdge { index: usize },
ShapeTooCloseToEdge {
/// The index of the violating object.
index: usize
},

/// An error indicating that the bounding boxes of two objects in this world intersect and
/// and therefore this world is invalid.
#[fail(display = "bounding boxes of shapes {} and {} intersect", index_1, index_2)]
ShapesIntersect { index_1: usize, index_2: usize },
ShapesIntersect {
/// The index of the first object intersecting with the second.
index_1: usize,
/// The index of the second object intersecting with the first.
index_2: usize
},
}

impl World {
Expand Down Expand Up @@ -141,6 +153,9 @@ impl World {
Ok(())
}

/// Performs a recursive integration between two frequencies. If the difference between the
/// midpoint force and the linear interpolation is too large, both sides of the domain will use
/// this function recursively to integrate the force.
pub fn integrate_force_between_frequencies(
&self,
i: usize,
Expand Down Expand Up @@ -181,6 +196,8 @@ impl World {
}
}

/// Compute the force on object `i` for a certain `frequency`. This method will also subtract
/// the error forces due to quantization by subtracting the force due to single objects.
fn force_on_for_freq(&self, i: usize, frequency: f32) -> Vector3<f32> {
// Progress bar
let bbox = &self.objects[i].bbox();
Expand Down
2 changes: 2 additions & 0 deletions src/world/shape.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,14 @@ impl fmt::Display for Shape {
impl Shape {
/// Create a new box, with the lowest coordinates in `p0`, and the highest coordinates in `p1`.
/// `material` is the material to use for this object.
#[cfg(test)]
pub fn new_box(p0: Point3<usize>, p1: Point3<usize>, material: DrudeMaterial) -> Shape {
Shape::Box { p0, p1, material }
}

/// Create a new sphere, centered at `point` and with a `radius`. `material` is the material to
/// use for this object.
#[cfg(test)]
pub fn new_sphere(point: Point3<usize>, radius: f32, material: DrudeMaterial) -> Shape {
Shape::Sphere {
point,
Expand Down

0 comments on commit 6d485de

Please sign in to comment.