pub struct MortonKey { /* private fields */ }
Expand description
A morton key
This is a distinct type to distinguish from u64 numbers.
Implementations§
Source§impl MortonKey
impl MortonKey
Sourcepub fn upper_bound() -> Self
pub fn upper_bound() -> Self
A key that is not valid or well formed but guaranteed to be larger than any valid key.
This is useful when a guaranteed upper bound is needed.
Sourcepub fn invalid_key() -> Self
pub fn invalid_key() -> Self
Create an invalid key.
Sourcepub fn is_valid(&self) -> bool
pub fn is_valid(&self) -> bool
Check if key is valid.
A key is not valid if its highest bit is 1.
Examples found in repository?
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
pub fn main() {
// Initialise MPI
let universe = mpi::initialize().unwrap();
// Get the world communicator
let comm = universe.world();
// Initialise a seeded Rng.
let mut rng = ChaCha8Rng::seed_from_u64(comm.rank() as u64);
// Create `npoints` per rank.
let npoints = 10000;
// Generate random points.
let mut points = generate_random_points(npoints, &mut rng, &comm);
// Make sure that the points live on the unit sphere.
for point in points.iter_mut() {
let len = point.coords()[0] * point.coords()[0]
+ point.coords()[1] * point.coords()[1]
+ point.coords()[2] * point.coords()[2];
let len = len.sqrt();
point.coords_mut()[0] /= len;
point.coords_mut()[1] /= len;
point.coords_mut()[2] /= len;
}
let tree = Octree::new(&points, 15, 50, &comm);
// We now check that each node of the tree has all its neighbors available.
let leaf_tree = tree.leaf_keys();
let all_keys = tree.all_keys();
assert!(is_complete_linear_and_balanced(leaf_tree, &comm));
for &key in leaf_tree {
// We only check interior keys. Leaf keys may not have a neighbor
// on the same level.
let mut parent = key.parent();
while parent.level() > 0 {
// Check that the key itself is there.
assert!(all_keys.contains_key(&key));
// Check that all its neighbours are there.
for neighbor in parent.neighbours().iter().filter(|&key| key.is_valid()) {
assert!(all_keys.contains_key(neighbor));
}
parent = parent.parent();
// Check that the parent is there.
assert!(all_keys.contains_key(&parent));
}
}
// At the end check that the root of the tree is also contained.
assert!(all_keys.contains_key(&MortonKey::root()));
// Count the number of ghosts on each rank
// Count the number of global keys on each rank.
// Assert that all ghosts are from a different rank and count them.
let nghosts = all_keys
.iter()
.filter_map(|(_, &value)| {
if let KeyType::Ghost(rank) = value {
assert!(rank != comm.size() as usize);
Some(rank)
} else {
None
}
})
.count();
if comm.size() == 1 {
assert_eq!(nghosts, 0);
} else {
assert!(nghosts > 0);
}
let nglobal = all_keys
.iter()
.filter(|(_, &value)| matches!(value, KeyType::Global))
.count();
// Assert that all globals across all ranks have the same count.
let nglobals = gather_to_all(std::slice::from_ref(&nglobal), &comm);
assert_eq!(nglobals.iter().unique().count(), 1);
// Check that the points are associated with the correct leaf keys.
let mut npoints = 0;
let leaf_point_map = tree.leaf_keys_to_local_point_indices();
for (key, point_indices) in leaf_point_map {
for &index in point_indices {
assert!(key.is_ancestor(tree.point_keys()[index]));
}
npoints += point_indices.len();
}
// Make sure that the number of points and point keys lines up
// with the points stored for each leaf key.
assert_eq!(npoints, tree.points().len());
assert_eq!(npoints, tree.point_keys().len());
// Check the neighbour relationships.
let all_neighbours = tree.neighbour_map();
let all_keys = tree.all_keys();
for (key, key_type) in all_keys {
// Ghost keys should not be in the neighbour map.
match key_type {
KeyType::Ghost(_) => assert!(!all_neighbours.contains_key(key)),
_ => {
// If it is not a ghost the key should be in the neighbour map.
assert!(all_neighbours.contains_key(key));
}
}
}
if comm.rank() == 0 {
println!("No errors were found in setting up tree.");
}
}
Sourcepub fn root() -> MortonKey
pub fn root() -> MortonKey
Create a root key.
A root key simply has the value 0
.
Examples found in repository?
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
pub fn main() {
// Initialise MPI
let universe = mpi::initialize().unwrap();
// Get the world communicator
let comm = universe.world();
// Initialise a seeded Rng.
let mut rng = ChaCha8Rng::seed_from_u64(comm.rank() as u64);
// Create `npoints` per rank.
let npoints = 10000;
// Generate random points.
let mut points = generate_random_points(npoints, &mut rng, &comm);
// Make sure that the points live on the unit sphere.
for point in points.iter_mut() {
let len = point.coords()[0] * point.coords()[0]
+ point.coords()[1] * point.coords()[1]
+ point.coords()[2] * point.coords()[2];
let len = len.sqrt();
point.coords_mut()[0] /= len;
point.coords_mut()[1] /= len;
point.coords_mut()[2] /= len;
}
let tree = Octree::new(&points, 15, 50, &comm);
// We now check that each node of the tree has all its neighbors available.
let leaf_tree = tree.leaf_keys();
let all_keys = tree.all_keys();
assert!(is_complete_linear_and_balanced(leaf_tree, &comm));
for &key in leaf_tree {
// We only check interior keys. Leaf keys may not have a neighbor
// on the same level.
let mut parent = key.parent();
while parent.level() > 0 {
// Check that the key itself is there.
assert!(all_keys.contains_key(&key));
// Check that all its neighbours are there.
for neighbor in parent.neighbours().iter().filter(|&key| key.is_valid()) {
assert!(all_keys.contains_key(neighbor));
}
parent = parent.parent();
// Check that the parent is there.
assert!(all_keys.contains_key(&parent));
}
}
// At the end check that the root of the tree is also contained.
assert!(all_keys.contains_key(&MortonKey::root()));
// Count the number of ghosts on each rank
// Count the number of global keys on each rank.
// Assert that all ghosts are from a different rank and count them.
let nghosts = all_keys
.iter()
.filter_map(|(_, &value)| {
if let KeyType::Ghost(rank) = value {
assert!(rank != comm.size() as usize);
Some(rank)
} else {
None
}
})
.count();
if comm.size() == 1 {
assert_eq!(nghosts, 0);
} else {
assert!(nghosts > 0);
}
let nglobal = all_keys
.iter()
.filter(|(_, &value)| matches!(value, KeyType::Global))
.count();
// Assert that all globals across all ranks have the same count.
let nglobals = gather_to_all(std::slice::from_ref(&nglobal), &comm);
assert_eq!(nglobals.iter().unique().count(), 1);
// Check that the points are associated with the correct leaf keys.
let mut npoints = 0;
let leaf_point_map = tree.leaf_keys_to_local_point_indices();
for (key, point_indices) in leaf_point_map {
for &index in point_indices {
assert!(key.is_ancestor(tree.point_keys()[index]));
}
npoints += point_indices.len();
}
// Make sure that the number of points and point keys lines up
// with the points stored for each leaf key.
assert_eq!(npoints, tree.points().len());
assert_eq!(npoints, tree.point_keys().len());
// Check the neighbour relationships.
let all_neighbours = tree.neighbour_map();
let all_keys = tree.all_keys();
for (key, key_type) in all_keys {
// Ghost keys should not be in the neighbour map.
match key_type {
KeyType::Ghost(_) => assert!(!all_neighbours.contains_key(key)),
_ => {
// If it is not a ghost the key should be in the neighbour map.
assert!(all_neighbours.contains_key(key));
}
}
}
if comm.rank() == 0 {
println!("No errors were found in setting up tree.");
}
}
Sourcepub fn deepest_first() -> Self
pub fn deepest_first() -> Self
Return the first deepest key.
This is the first key on the deepest level.
Sourcepub fn deepest_last() -> Self
pub fn deepest_last() -> Self
Return the last deepest key.
This is the last key on the deepest level.
Sourcepub fn physical_box(&self, bounding_box: &PhysicalBox) -> PhysicalBox
pub fn physical_box(&self, bounding_box: &PhysicalBox) -> PhysicalBox
Return the associated physical box.
Given the physical boundix bos of the octree this method returns the physical box associated with the key.
Sourcepub fn key_in_direction(&self, direction: [i64; 3]) -> MortonKey
pub fn key_in_direction(&self, direction: [i64; 3]) -> MortonKey
Return key in a given direction.
Returns an invalid key if there is no valid key in that direction.
Sourcepub fn is_well_formed(&self) -> bool
pub fn is_well_formed(&self) -> bool
A key is ill-formed if it has non-zero bits and positions that should be zero by the given level.
Sourcepub fn from_physical_point(
point: Point,
bounding_box: &PhysicalBox,
level: usize,
) -> Self
pub fn from_physical_point( point: Point, bounding_box: &PhysicalBox, level: usize, ) -> Self
Map a physical point within a bounding box to a Morton key on a given level.
It is assumed that points are strictly contained within the bounding box.
Sourcepub fn from_index_and_level(index: [usize; 3], level: usize) -> MortonKey
pub fn from_index_and_level(index: [usize; 3], level: usize) -> MortonKey
Create a new key by providing the [x, y, z] index and a level.
This is the preferred way to create a new Morton key.
Sourcepub fn level(&self) -> usize
pub fn level(&self) -> usize
Return the level of a key.
Examples found in repository?
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
pub fn main() {
// Initialise MPI
let universe = mpi::initialize().unwrap();
// Get the world communicator
let comm = universe.world();
// Initialise a seeded Rng.
let mut rng = ChaCha8Rng::seed_from_u64(comm.rank() as u64);
// Create `npoints` per rank.
let npoints = 10000;
// Generate random points.
let mut points = generate_random_points(npoints, &mut rng, &comm);
// Make sure that the points live on the unit sphere.
for point in points.iter_mut() {
let len = point.coords()[0] * point.coords()[0]
+ point.coords()[1] * point.coords()[1]
+ point.coords()[2] * point.coords()[2];
let len = len.sqrt();
point.coords_mut()[0] /= len;
point.coords_mut()[1] /= len;
point.coords_mut()[2] /= len;
}
let tree = Octree::new(&points, 15, 50, &comm);
// We now check that each node of the tree has all its neighbors available.
let leaf_tree = tree.leaf_keys();
let all_keys = tree.all_keys();
assert!(is_complete_linear_and_balanced(leaf_tree, &comm));
for &key in leaf_tree {
// We only check interior keys. Leaf keys may not have a neighbor
// on the same level.
let mut parent = key.parent();
while parent.level() > 0 {
// Check that the key itself is there.
assert!(all_keys.contains_key(&key));
// Check that all its neighbours are there.
for neighbor in parent.neighbours().iter().filter(|&key| key.is_valid()) {
assert!(all_keys.contains_key(neighbor));
}
parent = parent.parent();
// Check that the parent is there.
assert!(all_keys.contains_key(&parent));
}
}
// At the end check that the root of the tree is also contained.
assert!(all_keys.contains_key(&MortonKey::root()));
// Count the number of ghosts on each rank
// Count the number of global keys on each rank.
// Assert that all ghosts are from a different rank and count them.
let nghosts = all_keys
.iter()
.filter_map(|(_, &value)| {
if let KeyType::Ghost(rank) = value {
assert!(rank != comm.size() as usize);
Some(rank)
} else {
None
}
})
.count();
if comm.size() == 1 {
assert_eq!(nghosts, 0);
} else {
assert!(nghosts > 0);
}
let nglobal = all_keys
.iter()
.filter(|(_, &value)| matches!(value, KeyType::Global))
.count();
// Assert that all globals across all ranks have the same count.
let nglobals = gather_to_all(std::slice::from_ref(&nglobal), &comm);
assert_eq!(nglobals.iter().unique().count(), 1);
// Check that the points are associated with the correct leaf keys.
let mut npoints = 0;
let leaf_point_map = tree.leaf_keys_to_local_point_indices();
for (key, point_indices) in leaf_point_map {
for &index in point_indices {
assert!(key.is_ancestor(tree.point_keys()[index]));
}
npoints += point_indices.len();
}
// Make sure that the number of points and point keys lines up
// with the points stored for each leaf key.
assert_eq!(npoints, tree.points().len());
assert_eq!(npoints, tree.point_keys().len());
// Check the neighbour relationships.
let all_neighbours = tree.neighbour_map();
let all_keys = tree.all_keys();
for (key, key_type) in all_keys {
// Ghost keys should not be in the neighbour map.
match key_type {
KeyType::Ghost(_) => assert!(!all_neighbours.contains_key(key)),
_ => {
// If it is not a ghost the key should be in the neighbour map.
assert!(all_neighbours.contains_key(key));
}
}
}
if comm.rank() == 0 {
println!("No errors were found in setting up tree.");
}
}
Sourcepub fn decode(&self) -> (usize, [usize; 3])
pub fn decode(&self) -> (usize, [usize; 3])
Decode a key and return a tuple of the form (level, [x, y, z]), where the latter is the index vector.
Sourcepub fn parent(&self) -> Self
pub fn parent(&self) -> Self
Return the parent of a key.
Examples found in repository?
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
pub fn main() {
// Initialise MPI
let universe = mpi::initialize().unwrap();
// Get the world communicator
let comm = universe.world();
// Initialise a seeded Rng.
let mut rng = ChaCha8Rng::seed_from_u64(comm.rank() as u64);
// Create `npoints` per rank.
let npoints = 10000;
// Generate random points.
let mut points = generate_random_points(npoints, &mut rng, &comm);
// Make sure that the points live on the unit sphere.
for point in points.iter_mut() {
let len = point.coords()[0] * point.coords()[0]
+ point.coords()[1] * point.coords()[1]
+ point.coords()[2] * point.coords()[2];
let len = len.sqrt();
point.coords_mut()[0] /= len;
point.coords_mut()[1] /= len;
point.coords_mut()[2] /= len;
}
let tree = Octree::new(&points, 15, 50, &comm);
// We now check that each node of the tree has all its neighbors available.
let leaf_tree = tree.leaf_keys();
let all_keys = tree.all_keys();
assert!(is_complete_linear_and_balanced(leaf_tree, &comm));
for &key in leaf_tree {
// We only check interior keys. Leaf keys may not have a neighbor
// on the same level.
let mut parent = key.parent();
while parent.level() > 0 {
// Check that the key itself is there.
assert!(all_keys.contains_key(&key));
// Check that all its neighbours are there.
for neighbor in parent.neighbours().iter().filter(|&key| key.is_valid()) {
assert!(all_keys.contains_key(neighbor));
}
parent = parent.parent();
// Check that the parent is there.
assert!(all_keys.contains_key(&parent));
}
}
// At the end check that the root of the tree is also contained.
assert!(all_keys.contains_key(&MortonKey::root()));
// Count the number of ghosts on each rank
// Count the number of global keys on each rank.
// Assert that all ghosts are from a different rank and count them.
let nghosts = all_keys
.iter()
.filter_map(|(_, &value)| {
if let KeyType::Ghost(rank) = value {
assert!(rank != comm.size() as usize);
Some(rank)
} else {
None
}
})
.count();
if comm.size() == 1 {
assert_eq!(nghosts, 0);
} else {
assert!(nghosts > 0);
}
let nglobal = all_keys
.iter()
.filter(|(_, &value)| matches!(value, KeyType::Global))
.count();
// Assert that all globals across all ranks have the same count.
let nglobals = gather_to_all(std::slice::from_ref(&nglobal), &comm);
assert_eq!(nglobals.iter().unique().count(), 1);
// Check that the points are associated with the correct leaf keys.
let mut npoints = 0;
let leaf_point_map = tree.leaf_keys_to_local_point_indices();
for (key, point_indices) in leaf_point_map {
for &index in point_indices {
assert!(key.is_ancestor(tree.point_keys()[index]));
}
npoints += point_indices.len();
}
// Make sure that the number of points and point keys lines up
// with the points stored for each leaf key.
assert_eq!(npoints, tree.points().len());
assert_eq!(npoints, tree.point_keys().len());
// Check the neighbour relationships.
let all_neighbours = tree.neighbour_map();
let all_keys = tree.all_keys();
for (key, key_type) in all_keys {
// Ghost keys should not be in the neighbour map.
match key_type {
KeyType::Ghost(_) => assert!(!all_neighbours.contains_key(key)),
_ => {
// If it is not a ghost the key should be in the neighbour map.
assert!(all_neighbours.contains_key(key));
}
}
}
if comm.rank() == 0 {
println!("No errors were found in setting up tree.");
}
}
Sourcepub fn ancestor_at_level(&self, level: usize) -> Option<Self>
pub fn ancestor_at_level(&self, level: usize) -> Option<Self>
Return ancestor of key on specified level
Return None if level > self.level()
.
Return the key itself if level == self.level()
.
Sourcepub fn is_ancestor(&self, other: MortonKey) -> bool
pub fn is_ancestor(&self, other: MortonKey) -> bool
Check if key is ancestor of other
. If keys are identical also returns true.
Examples found in repository?
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
pub fn main() {
// Initialise MPI
let universe = mpi::initialize().unwrap();
// Get the world communicator
let comm = universe.world();
// Initialise a seeded Rng.
let mut rng = ChaCha8Rng::seed_from_u64(comm.rank() as u64);
// Create `npoints` per rank.
let npoints = 10000;
// Generate random points.
let mut points = generate_random_points(npoints, &mut rng, &comm);
// Make sure that the points live on the unit sphere.
for point in points.iter_mut() {
let len = point.coords()[0] * point.coords()[0]
+ point.coords()[1] * point.coords()[1]
+ point.coords()[2] * point.coords()[2];
let len = len.sqrt();
point.coords_mut()[0] /= len;
point.coords_mut()[1] /= len;
point.coords_mut()[2] /= len;
}
let tree = Octree::new(&points, 15, 50, &comm);
// We now check that each node of the tree has all its neighbors available.
let leaf_tree = tree.leaf_keys();
let all_keys = tree.all_keys();
assert!(is_complete_linear_and_balanced(leaf_tree, &comm));
for &key in leaf_tree {
// We only check interior keys. Leaf keys may not have a neighbor
// on the same level.
let mut parent = key.parent();
while parent.level() > 0 {
// Check that the key itself is there.
assert!(all_keys.contains_key(&key));
// Check that all its neighbours are there.
for neighbor in parent.neighbours().iter().filter(|&key| key.is_valid()) {
assert!(all_keys.contains_key(neighbor));
}
parent = parent.parent();
// Check that the parent is there.
assert!(all_keys.contains_key(&parent));
}
}
// At the end check that the root of the tree is also contained.
assert!(all_keys.contains_key(&MortonKey::root()));
// Count the number of ghosts on each rank
// Count the number of global keys on each rank.
// Assert that all ghosts are from a different rank and count them.
let nghosts = all_keys
.iter()
.filter_map(|(_, &value)| {
if let KeyType::Ghost(rank) = value {
assert!(rank != comm.size() as usize);
Some(rank)
} else {
None
}
})
.count();
if comm.size() == 1 {
assert_eq!(nghosts, 0);
} else {
assert!(nghosts > 0);
}
let nglobal = all_keys
.iter()
.filter(|(_, &value)| matches!(value, KeyType::Global))
.count();
// Assert that all globals across all ranks have the same count.
let nglobals = gather_to_all(std::slice::from_ref(&nglobal), &comm);
assert_eq!(nglobals.iter().unique().count(), 1);
// Check that the points are associated with the correct leaf keys.
let mut npoints = 0;
let leaf_point_map = tree.leaf_keys_to_local_point_indices();
for (key, point_indices) in leaf_point_map {
for &index in point_indices {
assert!(key.is_ancestor(tree.point_keys()[index]));
}
npoints += point_indices.len();
}
// Make sure that the number of points and point keys lines up
// with the points stored for each leaf key.
assert_eq!(npoints, tree.points().len());
assert_eq!(npoints, tree.point_keys().len());
// Check the neighbour relationships.
let all_neighbours = tree.neighbour_map();
let all_keys = tree.all_keys();
for (key, key_type) in all_keys {
// Ghost keys should not be in the neighbour map.
match key_type {
KeyType::Ghost(_) => assert!(!all_neighbours.contains_key(key)),
_ => {
// If it is not a ghost the key should be in the neighbour map.
assert!(all_neighbours.contains_key(key));
}
}
}
if comm.rank() == 0 {
println!("No errors were found in setting up tree.");
}
}
Sourcepub fn finest_common_ancestor(&self, other: MortonKey) -> MortonKey
pub fn finest_common_ancestor(&self, other: MortonKey) -> MortonKey
Return the finest common ancestor of two keys.
If the keys are identical return the key itself.
Sourcepub fn siblings(&self) -> [MortonKey; 8]
pub fn siblings(&self) -> [MortonKey; 8]
Return the 8 siblings of a key.
The key itself is part of the siblings.
Sourcepub fn neighbours(&self) -> [MortonKey; 26]
pub fn neighbours(&self) -> [MortonKey; 26]
Return the neighbours of a key.
The key itself is not part of the neighbours. If along a certain direction there is no neighbour then an invalid key is stored.
Examples found in repository?
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
pub fn main() {
// Initialise MPI
let universe = mpi::initialize().unwrap();
// Get the world communicator
let comm = universe.world();
// Initialise a seeded Rng.
let mut rng = ChaCha8Rng::seed_from_u64(comm.rank() as u64);
// Create `npoints` per rank.
let npoints = 10000;
// Generate random points.
let mut points = generate_random_points(npoints, &mut rng, &comm);
// Make sure that the points live on the unit sphere.
for point in points.iter_mut() {
let len = point.coords()[0] * point.coords()[0]
+ point.coords()[1] * point.coords()[1]
+ point.coords()[2] * point.coords()[2];
let len = len.sqrt();
point.coords_mut()[0] /= len;
point.coords_mut()[1] /= len;
point.coords_mut()[2] /= len;
}
let tree = Octree::new(&points, 15, 50, &comm);
// We now check that each node of the tree has all its neighbors available.
let leaf_tree = tree.leaf_keys();
let all_keys = tree.all_keys();
assert!(is_complete_linear_and_balanced(leaf_tree, &comm));
for &key in leaf_tree {
// We only check interior keys. Leaf keys may not have a neighbor
// on the same level.
let mut parent = key.parent();
while parent.level() > 0 {
// Check that the key itself is there.
assert!(all_keys.contains_key(&key));
// Check that all its neighbours are there.
for neighbor in parent.neighbours().iter().filter(|&key| key.is_valid()) {
assert!(all_keys.contains_key(neighbor));
}
parent = parent.parent();
// Check that the parent is there.
assert!(all_keys.contains_key(&parent));
}
}
// At the end check that the root of the tree is also contained.
assert!(all_keys.contains_key(&MortonKey::root()));
// Count the number of ghosts on each rank
// Count the number of global keys on each rank.
// Assert that all ghosts are from a different rank and count them.
let nghosts = all_keys
.iter()
.filter_map(|(_, &value)| {
if let KeyType::Ghost(rank) = value {
assert!(rank != comm.size() as usize);
Some(rank)
} else {
None
}
})
.count();
if comm.size() == 1 {
assert_eq!(nghosts, 0);
} else {
assert!(nghosts > 0);
}
let nglobal = all_keys
.iter()
.filter(|(_, &value)| matches!(value, KeyType::Global))
.count();
// Assert that all globals across all ranks have the same count.
let nglobals = gather_to_all(std::slice::from_ref(&nglobal), &comm);
assert_eq!(nglobals.iter().unique().count(), 1);
// Check that the points are associated with the correct leaf keys.
let mut npoints = 0;
let leaf_point_map = tree.leaf_keys_to_local_point_indices();
for (key, point_indices) in leaf_point_map {
for &index in point_indices {
assert!(key.is_ancestor(tree.point_keys()[index]));
}
npoints += point_indices.len();
}
// Make sure that the number of points and point keys lines up
// with the points stored for each leaf key.
assert_eq!(npoints, tree.points().len());
assert_eq!(npoints, tree.point_keys().len());
// Check the neighbour relationships.
let all_neighbours = tree.neighbour_map();
let all_keys = tree.all_keys();
for (key, key_type) in all_keys {
// Ghost keys should not be in the neighbour map.
match key_type {
KeyType::Ghost(_) => assert!(!all_neighbours.contains_key(key)),
_ => {
// If it is not a ghost the key should be in the neighbour map.
assert!(all_neighbours.contains_key(key));
}
}
}
if comm.rank() == 0 {
println!("No errors were found in setting up tree.");
}
}
Sourcepub fn child_index(&self) -> usize
pub fn child_index(&self) -> usize
Return the index of the key as a child of the parent, i.e. 0, 1, …, 7.
Sourcepub fn finest_outer_descendent(&self) -> MortonKey
pub fn finest_outer_descendent(&self) -> MortonKey
Return the finest descendent that is opposite to the joint corner with the siblings.
Sourcepub fn next_non_descendent_key(&self) -> Option<MortonKey>
pub fn next_non_descendent_key(&self) -> Option<MortonKey>
Return the next possible Morton key on the deepest level that is not a descendent of the current key.
If the key is already the last possible key then return None.
Sourcepub fn linearize(keys: &[MortonKey]) -> Vec<MortonKey>
pub fn linearize(keys: &[MortonKey]) -> Vec<MortonKey>
Linearize by sorting and removing overlaps.
Sourcepub fn fill_between_keys(&self, key2: MortonKey) -> Vec<MortonKey>
pub fn fill_between_keys(&self, key2: MortonKey) -> Vec<MortonKey>
Fill the region between two keys with a minimal number of keys.
Sourcepub fn complete_tree(keys: &[MortonKey]) -> Vec<MortonKey>
pub fn complete_tree(keys: &[MortonKey]) -> Vec<MortonKey>
Complete a tree ensuring that the given keys are part of the leafs.
The given keys must not overlap.
Sourcepub fn get_interior_keys(keys: &[MortonKey]) -> HashSet<MortonKey>
pub fn get_interior_keys(keys: &[MortonKey]) -> HashSet<MortonKey>
Get all interior keys for an Octree represented by a list of Morton keys
Adds the root at level 0 if the root is not a leaf if the octree.
If keys
only contains the root of the tree then the returned set is empty.
Sourcepub fn get_interior_and_leaf_keys(keys: &[MortonKey]) -> HashSet<MortonKey>
pub fn get_interior_and_leaf_keys(keys: &[MortonKey]) -> HashSet<MortonKey>
Return interior and leaf keys.
Sourcepub fn is_complete_linear_octree(keys: &[MortonKey]) -> bool
pub fn is_complete_linear_octree(keys: &[MortonKey]) -> bool
Check if a list of Morton keys represent a complete linear tree.
Sourcepub fn balance(keys: &[MortonKey], root: MortonKey) -> Vec<MortonKey>
pub fn balance(keys: &[MortonKey], root: MortonKey) -> Vec<MortonKey>
Balance a list of Morton keys with respect to a root key.
Sourcepub fn is_complete_linear_and_balanced(keys: &[MortonKey]) -> bool
pub fn is_complete_linear_and_balanced(keys: &[MortonKey]) -> bool
Returns true if an Octree is linear, complete, and, balanced.
Trait Implementations§
Source§impl Ord for MortonKey
impl Ord for MortonKey
Source§impl PartialOrd for MortonKey
impl PartialOrd for MortonKey
impl Copy for MortonKey
impl Eq for MortonKey
impl StructuralPartialEq for MortonKey
Auto Trait Implementations§
impl Freeze for MortonKey
impl RefUnwindSafe for MortonKey
impl Send for MortonKey
impl Sync for MortonKey
impl Unpin for MortonKey
impl UnwindSafe for MortonKey
Blanket Implementations§
§impl<Src, Scheme> ApproxFrom<Src, Scheme> for Srcwhere
Scheme: ApproxScheme,
impl<Src, Scheme> ApproxFrom<Src, Scheme> for Srcwhere
Scheme: ApproxScheme,
§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>
§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,
§fn approx_into(self) -> Result<Dst, <Src as ApproxInto<Dst, Scheme>>::Err>
fn approx_into(self) -> Result<Dst, <Src as ApproxInto<Dst, Scheme>>::Err>
§impl<T> AsDatatype for Twhere
T: Equivalence,
impl<T> AsDatatype for Twhere
T: Equivalence,
§type Out = <T as Equivalence>::Out
type Out = <T as Equivalence>::Out
SystemDatatype
or UserDatatype
)§fn as_datatype(&self) -> <T as AsDatatype>::Out
fn as_datatype(&self) -> <T as AsDatatype>::Out
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
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§unsafe fn clone_to_uninit(&self, dst: *mut T)
unsafe fn clone_to_uninit(&self, dst: *mut T)
clone_to_uninit
)§impl<T> Collection for Twhere
T: Equivalence,
impl<T> Collection for Twhere
T: Equivalence,
§impl<T, Dst> ConvAsUtil<Dst> for T
impl<T, Dst> ConvAsUtil<Dst> for T
§impl<T> ConvUtil for T
impl<T> ConvUtil for T
§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>,
§fn approx_as_by<Dst, Scheme>(self) -> Result<Dst, Self::Err>where
Self: Sized + ApproxInto<Dst, Scheme>,
Scheme: ApproxScheme,
fn approx_as_by<Dst, Scheme>(self) -> Result<Dst, Self::Err>where
Self: Sized + ApproxInto<Dst, Scheme>,
Scheme: ApproxScheme,
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>
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>
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