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
impl Point
Sourcepub fn new(coords: [f64; 3], global_id: usize) -> Self
pub fn new(coords: [f64; 3], global_id: usize) -> Self
Create a new point from coordinates and global id.
Sourcepub fn coords(&self) -> [f64; 3]
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
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}Sourcepub fn coords_mut(&mut self) -> &mut [f64; 3]
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
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}Trait Implementations§
impl Copy for Point
Source§impl Equivalence for Point
impl Equivalence for Point
Source§type Out = DatatypeRef<'static>
type Out = DatatypeRef<'static>
The type of the equivalent MPI datatype (e.g.
SystemDatatype or UserDatatype)Source§fn equivalent_datatype() -> Self::Out
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<Src, Scheme> ApproxFrom<Src, Scheme> for Srcwhere
Scheme: ApproxScheme,
impl<Src, Scheme> ApproxFrom<Src, Scheme> for Srcwhere
Scheme: ApproxScheme,
Source§fn approx_from(src: Src) -> Result<Src, <Src as ApproxFrom<Src, Scheme>>::Err>
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 Srcwhere
Dst: ApproxFrom<Src, Scheme>,
Scheme: ApproxScheme,
impl<Dst, Src, Scheme> ApproxInto<Dst, Scheme> for Srcwhere
Dst: ApproxFrom<Src, Scheme>,
Scheme: ApproxScheme,
Source§type Err = <Dst as ApproxFrom<Src, Scheme>>::Err
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>
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 Twhere
T: Equivalence,
impl<T> AsDatatype for Twhere
T: Equivalence,
Source§type Out = <T as Equivalence>::Out
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
fn as_datatype(&self) -> <T as AsDatatype>::Out
The associated MPI datatype
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
impl<T> Buffer for Twhere
T: Equivalence,
impl<T> BufferMut for Twhere
T: Equivalence,
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Collection for Twhere
T: Equivalence,
impl<T> Collection for Twhere
T: Equivalence,
Source§impl<T, Dst> ConvAsUtil<Dst> for T
impl<T, Dst> ConvAsUtil<Dst> for T
Source§impl<T> ConvUtil for T
impl<T> ConvUtil for T
Source§fn approx_as<Dst>(self) -> Result<Dst, Self::Err>where
Self: Sized + ApproxInto<Dst>,
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>
fn approx_as_by<Dst, Scheme>(self) -> Result<Dst, Self::Err>
Approximate the subject to a given type with a specific scheme.
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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 moreSource§impl<T> Pointer for Twhere
T: Equivalence,
impl<T> Pointer for Twhere
T: Equivalence,
Source§impl<T> PointerMut for Twhere
T: Equivalence,
impl<T> PointerMut for Twhere
T: Equivalence,
Source§fn pointer_mut(&mut self) -> *mut c_void
fn pointer_mut(&mut self) -> *mut c_void
A mutable pointer to the starting address in memory