def test_l2l(npoints, octree, l2l): parent_key = 9 child_key = hilbert.get_children(parent_key)[-1] x0 = octree.center r0 = octree.radius parent_center = hilbert.get_center_from_key(parent_key, x0, r0) child_center = hilbert.get_center_from_key(child_key, x0, r0) parent_level = hilbert.get_level(parent_key) child_level = hilbert.get_level(child_key) parent_equivalent_density = np.ones(shape=(npoints)) operator_idx = (child_key % 8) - 1 child_equivalent_density = np.matmul(l2l[operator_idx], parent_equivalent_density) child_equivalent_surface = operator.scale_surface( surface=SURFACE, radius=r0, level=child_level, center=child_center, alpha=2.95 ) parent_equivalent_surface = operator.scale_surface( surface=SURFACE, radius=r0, level=parent_level, center=parent_center, alpha=2.95 ) local_point = np.array([list(child_center)]) parent_direct = operator.p2p( kernel_function=KERNEL_FUNCTION, targets=local_point, sources=parent_equivalent_surface, source_densities=parent_equivalent_density ) child_direct = operator.p2p( kernel_function=KERNEL_FUNCTION, targets=local_point, sources=child_equivalent_surface, source_densities=child_equivalent_density ) assert np.isclose(parent_direct.density, child_direct.density, rtol=RTOL)
def test_m2m(npoints, octree, m2m): parent_key = 0 child_key = hilbert.get_children(parent_key)[0] x0 = octree.center r0 = octree.radius parent_center = hilbert.get_center_from_key(parent_key, x0, r0) child_center = hilbert.get_center_from_key(child_key, x0, r0) parent_level = hilbert.get_level(parent_key) child_level = hilbert.get_level(child_key) operator_idx = (child_key % 8) -1 child_equivalent_density = np.ones(shape=(npoints)) parent_equivalent_density = np.matmul(m2m[operator_idx], child_equivalent_density) distant_point = np.array([[1e3, 0, 0]]) child_equivalent_surface = operator.scale_surface( surface=SURFACE, radius=r0, level=child_level, center=child_center, alpha=1.05 ) parent_equivalent_surface = operator.scale_surface( surface=SURFACE, radius=r0, level=parent_level, center=parent_center, alpha=1.05 ) parent_direct = operator.p2p( kernel_function=KERNEL_FUNCTION, targets=distant_point, sources=parent_equivalent_surface, source_densities=parent_equivalent_density ) child_direct = operator.p2p( kernel_function=KERNEL_FUNCTION, targets=distant_point, sources=child_equivalent_surface, source_densities=child_equivalent_density ) assert np.isclose(parent_direct.density, child_direct.density, rtol=RTOL)
def test_interaction_list_assignment(tree): """Check that the interaction list has been correctly assigned.""" source_nodes_set = set(tree.non_empty_source_nodes) for target_index, target in enumerate(tree.non_empty_target_nodes): level = hilbert.get_level(target) if level < 2: continue parent = hilbert.get_parent(target) parent_index = tree.target_node_to_index[parent] parent_neighbors = tree.target_neighbors[parent_index] target_neighbors = tree.target_neighbors[ tree.target_node_to_index[target]] for neighbor_index in range(27): parent_neighbor = parent_neighbors[neighbor_index] if parent_neighbors[neighbor_index] == -1: # The corresponding neighbor has no sources. assert np.all(tree.interaction_list[target_index, neighbor_index] == -1) else: # There are sources in the neighbor for child_index, child in enumerate( hilbert.get_children(parent_neighbor)): if child in source_nodes_set and child not in set( target_neighbors): assert tree.interaction_list[target_index, neighbor_index, child_index] == child # pylint: disable=C0301 else: assert tree.interaction_list[target_index, neighbor_index, child_index] == -1 # pylint: disable=C0301
def test_m2l(npoints, octree, m2l_operators): # pick a target box on level 2 or below x0 = octree.center r0 = octree.radius target_key = 72 source_level = target_level = hilbert.get_level(target_key) m2l = m2l_operators.operators[source_level] target_index = hilbert.remove_level_offset(target_key) target_center = hilbert.get_center_from_key(target_key, x0, r0) interaction_list = hilbert.get_interaction_list(target_key) # pick a source box in target's interaction list source_key = interaction_list[2] source_center = hilbert.get_center_from_key(source_key, x0, r0) # get the operator index from current level lookup table index_to_key = m2l_operators.index_to_key[target_level][target_index] source_index = np.where(source_key == index_to_key)[0][0] # place unit densities on source box # source_equivalent_density = np.ones(shape=(npoints)) source_equivalent_density = np.random.rand(npoints) source_equivalent_surface = operator.scale_surface( surface=SURFACE, radius=r0, level=source_level, center=source_center, alpha=1.05 ) m2l_matrix = m2l[target_index][source_index] target_equivalent_density = np.matmul(m2l_matrix, source_equivalent_density) target_equivalent_surface = operator.scale_surface( surface=SURFACE, radius=r0, level=target_level, center=target_center, alpha=2.95 ) local_point = np.array([list(target_center)]) target_direct = operator.p2p( kernel_function=KERNEL_FUNCTION, targets=local_point, sources=target_equivalent_surface, source_densities=target_equivalent_density ) source_direct = operator.p2p( kernel_function=KERNEL_FUNCTION, targets=local_point, sources=source_equivalent_surface, source_densities=source_equivalent_density ) assert np.isclose(target_direct.density, source_direct.density, rtol=RTOL)
def test_get_level(key, level): assert hilbert.get_level(key) == level
def numba_compute_interaction_list(targets, target_neighbors, source_node_to_index, target_node_to_index): """ Compute the interaction list for all given target nodes. Parameters: ----------- targets : np.array(shape=(ntargets,), dtype=np.int64) Target nodes, referenced by Hilbert key, for which interaction lists are being computed. target_neighbors : np.array(shape=(ntargets, 27), dtype=np.int64) Contains information on non-empty source neighbor nodes of each target, computed via `numba_compute_neighbors`. source_node_to_index : np.array(shape=(nsources,), dtype=np.int64) target_node_to_index : np.array(shape=(ntargets,), dtype=np.int64) Returns: -------- np.array(shape=(ntargets, 27, 8), dtype=np.int64) Interaction list, each target in n targets has an associated (27, 8) matrix associated with it. """ ntargets = len(targets) interaction_list = -1 * np.ones((ntargets, 27, 8), dtype=np.int64) for target_index, target in enumerate(targets): target_level = hilbert.get_level(target) if target_level >= 2: # Find parent parent = hilbert.get_parent(target) # Find parent neighbors parent_index = target_node_to_index[parent] parent_neighbors = target_neighbors[parent_index] for parent_neighbor_index, parent_neighbor in enumerate( parent_neighbors): if parent_neighbor != -1: parent_neighbor_children = hilbert.get_children( parent_neighbor) for neigbhor_child_index, neighbor_child in enumerate( parent_neighbor_children): is_neighbor = _is_neighbor( target_neighbors=target_neighbors, target_index=target_index, key=neighbor_child) if source_node_to_index[ neighbor_child] != -1 and ~is_neighbor: interaction_list[ target_index, parent_neighbor_index, neigbhor_child_index] = neighbor_child return interaction_list
def compute_m2l_matrices( target, kernel, surface, alpha_inner, x0, r0, dc2e_v, dc2e_u, interaction_list, ): """ Data has to be passed to each process in order to compute the m2l matrices associated with a given target key. This method takes the required data and computes all the m2l matrices for a given target. Parameters: ----------- target : np.int64 Target Hilbert Key. kernel : function surface : np.array(shape=(n, 3), dtype=np.float64) alpha_inner : np.float64 Ratio between side length of shifted/scaled node and original node. x0 : np.array(shape=(1, 3), dtype=np.float64) Center of Octree's root node. r0 : np.float64 Half side length of Octree's root node. dc2e_v : np.array(shape=(n, n)) First component of the inverse of the downward-check-to-equivalent Gram matrix at level 0. dc2e_v : np.array(shape=(n, n)) Second component of the inverse of the downward-check-to-equivalent Gram matrix at level 0. Returns: -------- list[np.array(shape=(n, n))] List of all m2l matrices associated with this target. """ # Get level level = hilbert.get_level(target) # Container for results m2l_matrices = [] # Increment counter, and print progress increment_m2l_counter() log_m2l_progress(M2L_COUNTER.value, level) # Compute target check surface target_center = hilbert.get_center_from_key(key=target, x0=x0, r0=r0) target_check_surface = operator.scale_surface(surface=surface, radius=r0, level=level, center=target_center, alpha=alpha_inner) # Compute m2l matrices for source in interaction_list: source_center = hilbert.get_center_from_key(key=source, x0=x0, r0=r0) source_equivalent_surface = operator.scale_surface( surface=surface, radius=r0, level=level, center=source_center, alpha=alpha_inner) se2tc = operator.gram_matrix(kernel_function=kernel, sources=source_equivalent_surface, targets=target_check_surface) scale = (1 / kernel.scale)**(level) tmp = np.matmul(dc2e_u, se2tc) m2l_matrix = np.matmul(scale * dc2e_v, tmp) m2l_matrices.append(m2l_matrix) return m2l_matrices