diff --git a/boxtree/traversal.py b/boxtree/traversal.py index 6960e45c79cb9343ddc5711ad82ec16c164eddeb..9f032a9475541dcfbff1041597bcf486344838c8 100644 --- a/boxtree/traversal.py +++ b/boxtree/traversal.py @@ -789,16 +789,47 @@ void generate(LIST_ARG_DECL USER_ARG_DECL box_id_t target_box_number) %endfor ; - // l^2 distance between source box and target box. - // Negative indicates overlap. - coord_t l_2_box_dist = + <% assert not sources_have_extent %> + + // We're considering convergence of a multipole + // in the (square) source box at all locations + // in the (round) target box. We need + + // src_box_l2_radius + // / d_2(src_box_center, tgt_box) <= sqrt(d)/3 + + // <=> + + // src_box_linf_radius * sqrt(d) + // / d_2(src_box_center, tgt_box) <= sqrt(d)/3 + + // <=> + + // 3 * src_box_linf_radius + // <= d_2(src_box_center, tgt_box) + + // <=> + + // 3 * src_box_linf_radius + // <= d_2(src_box_center, tgt_box_center) + // - sqrt(d) * tgt_stickout_l_inf_rad + + // <=> (because why not) + + // 2 * src_box_linf_radius + // <= d_2(src_box_center, tgt_box_center) + // - sqrt(d) * tgt_stickout_l_inf_rad + // - src_box_linf_radius + + coord_t rhs = sqrt(l_2_squared_center_dist) - sqrt((coord_t) (${dimensions})) * tgt_stickout_l_inf_rad - source_l_inf_rad; - meets_sep_crit = l_2_box_dist >= - (2 - 8 * COORD_T_MACH_EPS) * source_l_inf_rad; + meets_sep_crit = ( + (2 - 8 * COORD_T_MACH_EPS) * source_l_inf_rad + <= rhs); } %else: @@ -921,6 +952,24 @@ inline bool meets_sep_bigger_criterion( coord_vec_t source_center, int source_level, coord_t stick_out_factor) { + <% + assert not sources_have_extent + %> + + // What we are interested in ensuring is that + + // (*) + // d_2(src_box, tgt_center) + // >= 3 * (radius of tgt box potentially + // including stick-out) + + // (because convergence factors are in l^2, + // irrespective of how we measure) + + // Since d_2(a, b) >= d_inf(a, b), ensuring that + // (*) holds with d_inf implies that it also holds + // with d_2. + coord_t target_rad = LEVEL_TO_RAD(target_level); coord_t source_rad = LEVEL_TO_RAD(source_level); coord_t max_allowed_center_l_inf_dist = (