Skip to main content

Point

Struct Point 

Source
pub struct Point { /* private fields */ }
Expand description

Definition of a point in 3d space.

A point consists of three coordinates and a global id. The global id makes it easier to identify points as they are distributed across MPI nodes.

Implementations§

Source§

impl Point

Source

pub fn new(coords: [f64; 3], global_id: usize) -> Self

Create a new point from coordinates and global id.

Source

pub fn coords(&self) -> [f64; 3]

Return the coordintes of a point.

Examples found in repository?
examples/mpi_complete_tree.rs (line 28)
10pub fn main() {
11    // Initialise MPI
12    let universe = mpi::initialize().unwrap();
13
14    // Get the world communicator
15    let comm = universe.world();
16
17    // Initialise a seeded Rng.
18    let mut rng = ChaCha8Rng::seed_from_u64(comm.rank() as u64);
19
20    // Create `npoints` per rank.
21    let npoints = 1000000;
22
23    // Generate random points on the positive octant of the unit sphere.
24
25    let mut points = generate_random_points(npoints, &mut rng, &comm);
26    // Make sure that the points live on the unit sphere.
27    for point in points.iter_mut() {
28        let len = point.coords()[0] * point.coords()[0]
29            + point.coords()[1] * point.coords()[1]
30            + point.coords()[2] * point.coords()[2];
31        let len = len.sqrt();
32        point.coords_mut()[0] /= len;
33        point.coords_mut()[1] /= len;
34        point.coords_mut()[2] /= len;
35    }
36
37    let start = Instant::now();
38    // The following code will create a complete octree with a maximum level of 16.
39    let octree = Octree::new(&points, 16, 50, &comm);
40    let duration = start.elapsed();
41
42    let global_number_of_points = octree.global_number_of_points();
43    let global_max_level = octree.global_max_level();
44
45    // We now check that each node of the tree has all its neighbors available.
46
47    if comm.rank() == 0 {
48        println!(
49            "Setup octree with {} points and maximum level {} in {} ms",
50            global_number_of_points,
51            global_max_level,
52            duration.as_millis()
53        );
54    }
55}
More examples
Hide additional examples
examples/mpi_complete_tree_debug.rs (line 31)
13pub fn main() {
14    // Initialise MPI
15    let universe = mpi::initialize().unwrap();
16
17    // Get the world communicator
18    let comm = universe.world();
19
20    // Initialise a seeded Rng.
21    let mut rng = ChaCha8Rng::seed_from_u64(comm.rank() as u64);
22
23    // Create `npoints` per rank.
24    let npoints = 10000;
25
26    // Generate random points.
27
28    let mut points = generate_random_points(npoints, &mut rng, &comm);
29    // Make sure that the points live on the unit sphere.
30    for point in points.iter_mut() {
31        let len = point.coords()[0] * point.coords()[0]
32            + point.coords()[1] * point.coords()[1]
33            + point.coords()[2] * point.coords()[2];
34        let len = len.sqrt();
35        point.coords_mut()[0] /= len;
36        point.coords_mut()[1] /= len;
37        point.coords_mut()[2] /= len;
38    }
39
40    let tree = Octree::new(&points, 15, 50, &comm);
41
42    // We now check that each node of the tree has all its neighbors available.
43
44    let leaf_tree = tree.leaf_keys();
45    let all_keys = tree.all_keys();
46
47    assert!(is_complete_linear_and_balanced(leaf_tree, &comm));
48    for &key in leaf_tree {
49        // We only check interior keys. Leaf keys may not have a neighbor
50        // on the same level.
51        let mut parent = key.parent();
52        while parent.level() > 0 {
53            // Check that the key itself is there.
54            assert!(all_keys.contains_key(&key));
55            // Check that all its neighbours are there.
56            for neighbor in parent.neighbours().iter().filter(|&key| key.is_valid()) {
57                assert!(all_keys.contains_key(neighbor));
58            }
59            parent = parent.parent();
60            // Check that the parent is there.
61            assert!(all_keys.contains_key(&parent));
62        }
63    }
64
65    // At the end check that the root of the tree is also contained.
66    assert!(all_keys.contains_key(&MortonKey::root()));
67
68    // Count the number of ghosts on each rank
69    // Count the number of global keys on each rank.
70
71    // Assert that all ghosts are from a different rank and count them.
72
73    let nghosts = all_keys
74        .iter()
75        .filter_map(|(_, &value)| {
76            if let KeyType::Ghost(rank) = value {
77                assert!(rank != comm.size() as usize);
78                Some(rank)
79            } else {
80                None
81            }
82        })
83        .count();
84
85    if comm.size() == 1 {
86        assert_eq!(nghosts, 0);
87    } else {
88        assert!(nghosts > 0);
89    }
90
91    let nglobal = all_keys
92        .iter()
93        .filter(|(_, &value)| matches!(value, KeyType::Global))
94        .count();
95
96    // Assert that all globals across all ranks have the same count.
97
98    let nglobals = gather_to_all(std::slice::from_ref(&nglobal), &comm);
99
100    assert_eq!(nglobals.iter().unique().count(), 1);
101
102    // Check that the points are associated with the correct leaf keys.
103    let mut npoints = 0;
104    let leaf_point_map = tree.leaf_keys_to_local_point_indices();
105
106    for (key, point_indices) in leaf_point_map {
107        for &index in point_indices {
108            assert!(key.is_ancestor(tree.point_keys()[index]));
109        }
110        npoints += point_indices.len();
111    }
112
113    // Make sure that the number of points and point keys lines up
114    // with the points stored for each leaf key.
115    assert_eq!(npoints, tree.points().len());
116    assert_eq!(npoints, tree.point_keys().len());
117
118    // Check the neighbour relationships.
119
120    let all_neighbours = tree.neighbour_map();
121    let all_keys = tree.all_keys();
122
123    for (key, key_type) in all_keys {
124        // Ghost keys should not be in the neighbour map.
125        match key_type {
126            KeyType::Ghost(_) => assert!(!all_neighbours.contains_key(key)),
127            _ => {
128                // If it is not a ghost the key should be in the neighbour map.
129                assert!(all_neighbours.contains_key(key));
130            }
131        }
132    }
133
134    if comm.rank() == 0 {
135        println!("No errors were found in setting up tree.");
136    }
137}
Source

pub fn coords_mut(&mut self) -> &mut [f64; 3]

Return a mutable pointer to the coordinates.

Examples found in repository?
examples/mpi_complete_tree.rs (line 32)
10pub fn main() {
11    // Initialise MPI
12    let universe = mpi::initialize().unwrap();
13
14    // Get the world communicator
15    let comm = universe.world();
16
17    // Initialise a seeded Rng.
18    let mut rng = ChaCha8Rng::seed_from_u64(comm.rank() as u64);
19
20    // Create `npoints` per rank.
21    let npoints = 1000000;
22
23    // Generate random points on the positive octant of the unit sphere.
24
25    let mut points = generate_random_points(npoints, &mut rng, &comm);
26    // Make sure that the points live on the unit sphere.
27    for point in points.iter_mut() {
28        let len = point.coords()[0] * point.coords()[0]
29            + point.coords()[1] * point.coords()[1]
30            + point.coords()[2] * point.coords()[2];
31        let len = len.sqrt();
32        point.coords_mut()[0] /= len;
33        point.coords_mut()[1] /= len;
34        point.coords_mut()[2] /= len;
35    }
36
37    let start = Instant::now();
38    // The following code will create a complete octree with a maximum level of 16.
39    let octree = Octree::new(&points, 16, 50, &comm);
40    let duration = start.elapsed();
41
42    let global_number_of_points = octree.global_number_of_points();
43    let global_max_level = octree.global_max_level();
44
45    // We now check that each node of the tree has all its neighbors available.
46
47    if comm.rank() == 0 {
48        println!(
49            "Setup octree with {} points and maximum level {} in {} ms",
50            global_number_of_points,
51            global_max_level,
52            duration.as_millis()
53        );
54    }
55}
More examples
Hide additional examples
examples/mpi_complete_tree_debug.rs (line 35)
13pub fn main() {
14    // Initialise MPI
15    let universe = mpi::initialize().unwrap();
16
17    // Get the world communicator
18    let comm = universe.world();
19
20    // Initialise a seeded Rng.
21    let mut rng = ChaCha8Rng::seed_from_u64(comm.rank() as u64);
22
23    // Create `npoints` per rank.
24    let npoints = 10000;
25
26    // Generate random points.
27
28    let mut points = generate_random_points(npoints, &mut rng, &comm);
29    // Make sure that the points live on the unit sphere.
30    for point in points.iter_mut() {
31        let len = point.coords()[0] * point.coords()[0]
32            + point.coords()[1] * point.coords()[1]
33            + point.coords()[2] * point.coords()[2];
34        let len = len.sqrt();
35        point.coords_mut()[0] /= len;
36        point.coords_mut()[1] /= len;
37        point.coords_mut()[2] /= len;
38    }
39
40    let tree = Octree::new(&points, 15, 50, &comm);
41
42    // We now check that each node of the tree has all its neighbors available.
43
44    let leaf_tree = tree.leaf_keys();
45    let all_keys = tree.all_keys();
46
47    assert!(is_complete_linear_and_balanced(leaf_tree, &comm));
48    for &key in leaf_tree {
49        // We only check interior keys. Leaf keys may not have a neighbor
50        // on the same level.
51        let mut parent = key.parent();
52        while parent.level() > 0 {
53            // Check that the key itself is there.
54            assert!(all_keys.contains_key(&key));
55            // Check that all its neighbours are there.
56            for neighbor in parent.neighbours().iter().filter(|&key| key.is_valid()) {
57                assert!(all_keys.contains_key(neighbor));
58            }
59            parent = parent.parent();
60            // Check that the parent is there.
61            assert!(all_keys.contains_key(&parent));
62        }
63    }
64
65    // At the end check that the root of the tree is also contained.
66    assert!(all_keys.contains_key(&MortonKey::root()));
67
68    // Count the number of ghosts on each rank
69    // Count the number of global keys on each rank.
70
71    // Assert that all ghosts are from a different rank and count them.
72
73    let nghosts = all_keys
74        .iter()
75        .filter_map(|(_, &value)| {
76            if let KeyType::Ghost(rank) = value {
77                assert!(rank != comm.size() as usize);
78                Some(rank)
79            } else {
80                None
81            }
82        })
83        .count();
84
85    if comm.size() == 1 {
86        assert_eq!(nghosts, 0);
87    } else {
88        assert!(nghosts > 0);
89    }
90
91    let nglobal = all_keys
92        .iter()
93        .filter(|(_, &value)| matches!(value, KeyType::Global))
94        .count();
95
96    // Assert that all globals across all ranks have the same count.
97
98    let nglobals = gather_to_all(std::slice::from_ref(&nglobal), &comm);
99
100    assert_eq!(nglobals.iter().unique().count(), 1);
101
102    // Check that the points are associated with the correct leaf keys.
103    let mut npoints = 0;
104    let leaf_point_map = tree.leaf_keys_to_local_point_indices();
105
106    for (key, point_indices) in leaf_point_map {
107        for &index in point_indices {
108            assert!(key.is_ancestor(tree.point_keys()[index]));
109        }
110        npoints += point_indices.len();
111    }
112
113    // Make sure that the number of points and point keys lines up
114    // with the points stored for each leaf key.
115    assert_eq!(npoints, tree.points().len());
116    assert_eq!(npoints, tree.point_keys().len());
117
118    // Check the neighbour relationships.
119
120    let all_neighbours = tree.neighbour_map();
121    let all_keys = tree.all_keys();
122
123    for (key, key_type) in all_keys {
124        // Ghost keys should not be in the neighbour map.
125        match key_type {
126            KeyType::Ghost(_) => assert!(!all_neighbours.contains_key(key)),
127            _ => {
128                // If it is not a ghost the key should be in the neighbour map.
129                assert!(all_neighbours.contains_key(key));
130            }
131        }
132    }
133
134    if comm.rank() == 0 {
135        println!("No errors were found in setting up tree.");
136    }
137}
Source

pub fn global_id(&self) -> usize

Return the global id of the point.

Trait Implementations§

Source§

impl Clone for Point

Source§

fn clone(&self) -> Point

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for Point

Source§

impl Equivalence for Point

Source§

type Out = DatatypeRef<'static>

The type of the equivalent MPI datatype (e.g. SystemDatatype or UserDatatype)
Source§

fn equivalent_datatype() -> Self::Out

The MPI datatype that is equivalent to this Rust type

Auto Trait Implementations§

§

impl Freeze for Point

§

impl RefUnwindSafe for Point

§

impl Send for Point

§

impl Sync for Point

§

impl Unpin for Point

§

impl UnsafeUnpin for Point

§

impl UnwindSafe for Point

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<Src, Scheme> ApproxFrom<Src, Scheme> for Src
where Scheme: ApproxScheme,

Source§

type Err = NoError

The error type produced by a failed conversion.
Source§

fn approx_from(src: Src) -> Result<Src, <Src as ApproxFrom<Src, Scheme>>::Err>

Convert the given value into an approximately equivalent representation.
Source§

impl<Dst, Src, Scheme> ApproxInto<Dst, Scheme> for Src
where Dst: ApproxFrom<Src, Scheme>, Scheme: ApproxScheme,

Source§

type Err = <Dst as ApproxFrom<Src, Scheme>>::Err

The error type produced by a failed conversion.
Source§

fn approx_into(self) -> Result<Dst, <Src as ApproxInto<Dst, Scheme>>::Err>

Convert the subject into an approximately equivalent representation.
Source§

impl<T> AsDatatype for T
where T: Equivalence,

Source§

type Out = <T as Equivalence>::Out

The type of the associated MPI datatype (e.g. SystemDatatype or UserDatatype)
Source§

fn as_datatype(&self) -> <T as AsDatatype>::Out

The associated MPI datatype
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> Buffer for T
where T: Equivalence,

Source§

impl<T> BufferMut for T
where T: Equivalence,

Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> Collection for T
where T: Equivalence,

Source§

fn count(&self) -> i32

How many things are in this collection.
Source§

impl<T, Dst> ConvAsUtil<Dst> for T

Source§

fn approx(self) -> Result<Dst, Self::Err>
where Self: Sized + ApproxInto<Dst>,

Approximate the subject with the default scheme.
Source§

fn approx_by<Scheme>(self) -> Result<Dst, Self::Err>
where Self: Sized + ApproxInto<Dst, Scheme>, Scheme: ApproxScheme,

Approximate the subject with a specific scheme.
Source§

impl<T> ConvUtil for T

Source§

fn approx_as<Dst>(self) -> Result<Dst, Self::Err>
where Self: Sized + ApproxInto<Dst>,

Approximate the subject to a given type with the default scheme.
Source§

fn approx_as_by<Dst, Scheme>(self) -> Result<Dst, Self::Err>
where Self: Sized + ApproxInto<Dst, Scheme>, Scheme: ApproxScheme,

Approximate the subject to a given type with a specific scheme.
Source§

fn into_as<Dst>(self) -> Dst
where Self: Sized + Into<Dst>,

Convert the subject to a given type.
Source§

fn try_as<Dst>(self) -> Result<Dst, Self::Err>
where Self: Sized + TryInto<Dst>,

Attempt to convert the subject to a given type.
Source§

fn value_as<Dst>(self) -> Result<Dst, Self::Err>
where Self: Sized + ValueInto<Dst>,

Attempt a value conversion of the subject to a given type.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointer for T
where T: Equivalence,

Source§

fn pointer(&self) -> *const c_void

A pointer to the starting address in memory
Source§

impl<T> PointerMut for T
where T: Equivalence,

Source§

fn pointer_mut(&mut self) -> *mut c_void

A mutable pointer to the starting address in memory
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<Src> TryFrom<Src> for Src

Source§

type Err = NoError

The error type produced by a failed conversion.
Source§

fn try_from(src: Src) -> Result<Src, <Src as TryFrom<Src>>::Err>

Convert the given value into the subject type.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<Src, Dst> TryInto<Dst> for Src
where Dst: TryFrom<Src>,

Source§

type Err = <Dst as TryFrom<Src>>::Err

The error type produced by a failed conversion.
Source§

fn try_into(self) -> Result<Dst, <Src as TryInto<Dst>>::Err>

Convert the subject into the destination type.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<Src> ValueFrom<Src> for Src

Source§

type Err = NoError

The error type produced by a failed conversion.
Source§

fn value_from(src: Src) -> Result<Src, <Src as ValueFrom<Src>>::Err>

Convert the given value into an exactly equivalent representation.
Source§

impl<Src, Dst> ValueInto<Dst> for Src
where Dst: ValueFrom<Src>,

Source§

type Err = <Dst as ValueFrom<Src>>::Err

The error type produced by a failed conversion.
Source§

fn value_into(self) -> Result<Dst, <Src as ValueInto<Dst>>::Err>

Convert the subject into an exactly equivalent representation.