def _test_levelghostparticles_have_correct_split_from_coarser_particle(self, dim, interp_order, refinement_boxes): print("test_levelghostparticles_have_correct_split_from_coarser_particle for dim/interp : {}/{}".format(dim, interp_order)) datahier = self.getHierarchy(interp_order, refinement_boxes, "particles", cells=30) from pyphare.pharein.global_vars import sim assert sim is not None and len(sim.cells) == dim particle_level_ghost_boxes_per_level = level_ghost_boxes(datahier, "particles") self.assertTrue(len(particle_level_ghost_boxes_per_level.items()) > 0) for ilvl, particle_gaboxes in particle_level_ghost_boxes_per_level.items(): self.assertTrue(ilvl > 0) # has no level 0 coarse_particles = self._domainParticles_for(datahier, ilvl - 1) self.assertTrue(all([particles.size() > 0 for k, particles in coarse_particles.items()])) coarse_split_particles = {k: particles.split(sim) for k, particles in coarse_particles.items()} for k, particles in coarse_particles.items(): self.assertTrue(coarse_split_particles[k].size() > 0) self.assertTrue(coarse_split_particles[k].size() == particles.size() * sim.refined_particle_nbr) for pop_name, gaboxes in particle_gaboxes.items(): for gabox in gaboxes: gabox_patchData = gabox["pdata"] for ghostBox in gabox["boxes"]: part1 = gabox_patchData.dataset.select(ghostBox) part2 = coarse_split_particles[pop_name].select(ghostBox) self.assertEqual(part1, part2)
def _test_levelghostparticles_have_correct_split_from_coarser_particle( self, datahier): dim = datahier.level(0).patches[0].box.ndim from pyphare.pharein.global_vars import sim assert sim is not None assert len(sim.cells) == dim particle_level_ghost_boxes_per_level = level_ghost_boxes( datahier, "particles") self.assertTrue(len(particle_level_ghost_boxes_per_level.items()) > 0) for ilvl, particle_gaboxes in particle_level_ghost_boxes_per_level.items( ): self.assertTrue(ilvl > 0) # has no level 0 lvlParticles = self._domainParticles_for(datahier, ilvl - 1) for pop_name, gaboxes_list in particle_gaboxes.items(): coarse_particles = lvlParticles[pop_name] self.assertTrue(coarse_particles.size() > 0) coarse_split_particles = coarse_particles.split(sim) self.assertTrue(coarse_split_particles.size() > 0) self.assertTrue( coarse_split_particles.size() == coarse_particles.size() * sim.refined_particle_nbr) for gabox in gaboxes_list: gabox_patchData = gabox["pdata"] for ghostBox in gabox["boxes"]: part1 = gabox_patchData.dataset.select(ghostBox) part2 = coarse_split_particles.select(ghostBox) self.assertEqual(part1, part2)
def test_level_ghost_boxes(self, refinement_boxes, expected): print("ParticleLevelGhostGeometryTest.test_level_ghost_boxes") dim, interp_order, nbr_cells = (2, 1, [20] * 2) hierarchy = self.setup_hierarchy( dim, interp_order, nbr_cells, refinement_boxes, quantities="particles" ) lvl_gaboxes = level_ghost_boxes(hierarchy, "particles") for ilvl in range(1, len(hierarchy.patch_levels)): self.assertEqual(len(lvl_gaboxes[ilvl].keys()), 1) key = list(lvl_gaboxes[ilvl].keys())[0] ghost_area_box_list = sum( # aggregate to single list [actual["boxes"] for actual in lvl_gaboxes[ilvl][key]], [] ) fig = hierarchy.plot_2d_patches( ilvl, collections=[ { "boxes": ghost_area_box_list, "facecolor": "yellow", }, { "boxes": [p.box for p in hierarchy.level(ilvl).patches], "facecolor": "grey", }, ], title="".join( [str(box) + "," for box in refinement_boxes["L" + str(ilvl - 1)]] ), ) fig.savefig(f"{type(self).__name__}_lvl_{ilvl}_{self._testMethodName}.png") self.assertEqual(expected[ilvl], ghost_area_box_list)
def test_level_ghost_boxes_do_not_overlap_patch_interiors(self): hierarchy = self.basic_hierarchy() lvl_gaboxes = level_ghost_boxes(hierarchy, "particles") for ilvl in range(1, len(hierarchy.patch_levels)): qtyNbr = len(lvl_gaboxes[ilvl].keys()) self.assertEqual(qtyNbr, 1) key = list(lvl_gaboxes[ilvl].keys())[0] for pdatainfo in lvl_gaboxes[ilvl][key]: for box in pdatainfo["boxes"]: for patch in hierarchy.patch_levels[ilvl].patches: self.assertIsNone(patch.box * box)
def test_particle_level_ghost_boxes_do_not_overlap_patch_interiors(self): print( "GeometryTest.test_particle_level_ghost_boxes_do_not_overlap_patch_interiors" ) hierarchy = super().basic_hierarchy() lvl_gboxes = level_ghost_boxes(hierarchy, "particles") assert len(lvl_gboxes) > 0 for ilvl, pdatainfos in lvl_gboxes.items(): assert len(pdatainfos) > 0 for particles_id, gaboxes_list in pdatainfos.items(): assert len(gaboxes_list) > 0 for pdatainfo in gaboxes_list: for box in pdatainfo["boxes"]: for patch in hierarchy.patch_levels[ilvl].patches: self.assertIsNone(patch.box * box)
def test_level_ghostboxes(self, refinement_boxes, expected): dim, interp_order, nbr_cells = (1, 1, 20) hierarchy = self.setup_hierarchy( dim, interp_order, nbr_cells, refinement_boxes, quantities="Bx" ) lvl_gaboxes = level_ghost_boxes(hierarchy, "Bx") for ilvl in range(1, len(hierarchy.patch_levels)): qtyNbr = len(lvl_gaboxes[ilvl].keys()) self.assertEqual(qtyNbr, 1) key = list(lvl_gaboxes[ilvl].keys())[0] ghost_area_boxes = sum( # aggregate to single list [actual["boxes"] for actual in lvl_gaboxes[ilvl][key]], [] ) self.assertEqual(expected[ilvl], ghost_area_boxes)
def test_level_ghost_boxes(self): hierarchy = self.basic_hierarchy() expected = { 1: [ { "boxes": [ Box(9, 9), ] }, { "boxes": [ Box(60, 60), ] }, { "boxes": [ Box(63, 63), ] }, { "boxes": [ Box(112, 112), ] }, ] } lvl_gaboxes = level_ghost_boxes(hierarchy, "particles") for ilvl in range(1, len(hierarchy.patch_levels)): qtyNbr = len(lvl_gaboxes[ilvl].keys()) self.assertEqual(qtyNbr, 1) key = list(lvl_gaboxes[ilvl].keys())[0] for actual, exp in zip(lvl_gaboxes[ilvl][key], expected[ilvl]): act_boxes = actual["boxes"] exp_boxes = exp["boxes"] for act_box, exp_box in zip(act_boxes, exp_boxes): self.assertEqual(act_box, exp_box)
def base_test_field_level_ghosts_via_subcycles_and_coarser_interpolation( self, L0_datahier, L0L1_datahier, quantities=None): if quantities is None: quantities = [ f"{EM}{xyz}" for EM in ["E", "B"] for xyz in ["x", "y", "z"] ] from tests.amr.data.field.refine.test_refine_field import refine_time_interpolate from pyphare.pharein import global_vars def assert_time_in_hier(*ts): for t in ts: self.assertIn(L0L1_datahier.format_timestamp(t), L0L1_datahier.times()) checks = 0 ndim = global_vars.sim.ndim lvl_steps = global_vars.sim.level_time_steps assert len( lvl_steps ) == 2, "this test is only configured for L0 -> L1 refinement comparisons" coarse_ilvl = 0 fine_ilvl = 1 coarsest_time_before = 0 # init coarsest_time_after = coarsest_time_before + lvl_steps[coarse_ilvl] assert_time_in_hier(coarsest_time_before, coarsest_time_after) fine_subcycle_times = [] for fine_subcycle in range(global_vars.sim.level_step_nbr[fine_ilvl] + 1): fine_subcycle_time = coarsest_time_before + (lvl_steps[fine_ilvl] * fine_subcycle) assert_time_in_hier(fine_subcycle_time) fine_subcycle_times += [fine_subcycle_time] interpolated_fields = refine_time_interpolate(L0_datahier, quantities, coarse_ilvl, coarsest_time_before, coarsest_time_after, fine_subcycle_times) error_boxes = [] checks = 0 for fine_subcycle_time in fine_subcycle_times: fine_level_qty_ghost_boxes = level_ghost_boxes( L0L1_datahier, quantities, fine_ilvl, fine_subcycle_time) for qty in quantities: for fine_level_ghost_box_data in fine_level_qty_ghost_boxes[ qty]: fine_subcycle_pd = fine_level_ghost_box_data["pdata"] for fine_level_ghost_box_info in fine_level_ghost_box_data[ "boxes"]: # trim the border level ghost nodes from the primal fields to ignore them in comparison checks fine_level_ghost_boxes = fine_level_ghost_box_info - boxm.grow( fine_subcycle_pd.box, fine_subcycle_pd.primal_directions()) if ndim == 1: self.assertEqual( len(fine_level_ghost_boxes), 1) # should not be possibly > 1 in 1d np.testing.assert_equal( fine_level_ghost_boxes[0].shape, fine_level_ghost_box_info.shape - fine_subcycle_pd.primal_directions()) for fine_level_ghost_box in fine_level_ghost_boxes: upper_dims = fine_level_ghost_box.lower > fine_subcycle_pd.box.upper for refinedInterpolatedField in interpolated_fields[ qty][fine_subcycle_time]: lvlOverlap = refinedInterpolatedField.box * fine_level_ghost_box if lvlOverlap is not None: box = lvlOverlap fine_ghostbox_data = fine_subcycle_pd[box] refinedInterpGhostBox_data = refinedInterpolatedField[ box] assert fine_ghostbox_data.shape == refinedInterpGhostBox_data.shape fine_ds = fine_subcycle_pd.dataset if ndim == 1: # verify selecting start/end of L1 dataset from ghost box if upper_dims[0]: assert all( fine_ghostbox_data == fine_ds[-fine_ghostbox_data. shape[0]:]) else: assert all( fine_ghostbox_data == fine_ds[:fine_ghostbox_data. shape[0]]) assert refinedInterpGhostBox_data.shape == fine_subcycle_pd.ghosts_nbr assert fine_ghostbox_data.shape == fine_subcycle_pd.ghosts_nbr try: np.testing.assert_allclose( fine_ghostbox_data, refinedInterpGhostBox_data, atol=1e-15, rtol=0) except AssertionError as e: print( f"FAIL level ghost subcycle_coarsening qty {qty}", e) if self.rethrow_: raise e error_boxes += diff_boxes( fine_ghostbox_data, refinedInterpGhostBox_data, box, atol=1e-15) checks += 1 if len(error_boxes): return error_boxes return checks
def _test_field_level_ghosts_via_subcycles_and_coarser_interpolation( self, ndim, interp_order, refinement_boxes): """ This test runs two virtually identical simulations for one step. L0_datahier has no refined levels L0L1_datahier has one refined level This is done to compare L0 values that haven't received the coarsened values of L1 because there is no L1, to the level field ghost of L1 of L0L1_datahier The simulations are no longer comparable after the first advance, so this test cannot work beyond that. """ print("test_field_coarsening_via_subcycles for dim/interp : {}/{}". format(ndim, interp_order)) from tests.amr.data.field.refine.test_refine_field import refine_time_interpolate from pyphare.pharein import global_vars import random rando = random.randint(0, 1e10) def _getHier(diag_dir, boxes=[]): return self.getHierarchy( interp_order, boxes, "eb", cells=60, time_step_nbr=1, largest_patch_size=15, diag_outputs=diag_dir, extra_diag_options={"fine_dump_lvl_max": 10}, time_step=0.001, model_init={"seed": rando}, ndim=ndim) def assert_time_in_hier(*ts): for t in ts: self.assertIn(L0L1_datahier.format_timestamp(t), L0L1_datahier.times()) L0_datahier = _getHier( f"phare_lvl_ghost_interpolation_L0_diags/{ndim}/{interp_order}/{self.ddt_test_id()}" ) L0L1_datahier = _getHier( f"phare_lvl_ghost_interpolation_L0L1_diags/{ndim}/{interp_order}/{self.ddt_test_id()}", refinement_boxes) lvl_steps = global_vars.sim.level_time_steps assert len( lvl_steps ) == 2, "this test is only configured for L0 -> L1 refinement comparisons" coarse_ilvl = 0 fine_ilvl = 1 coarsest_time_before = 0 # init coarsest_time_after = coarsest_time_before + lvl_steps[coarse_ilvl] assert_time_in_hier(coarsest_time_before, coarsest_time_after) fine_subcycle_times = [] for fine_subcycle in range(global_vars.sim.level_step_nbr[fine_ilvl] + 1): fine_subcycle_time = coarsest_time_before + (lvl_steps[fine_ilvl] * fine_subcycle) assert_time_in_hier(fine_subcycle_time) fine_subcycle_times += [fine_subcycle_time] quantities = [ f"{EM}{xyz}" for EM in ["E", "B"] for xyz in ["x", "y", "z"] ] interpolated_fields = refine_time_interpolate(L0_datahier, quantities, coarse_ilvl, coarsest_time_before, coarsest_time_after, fine_subcycle_times) checks = 0 for fine_subcycle_time in fine_subcycle_times: fine_level_qty_ghost_boxes = level_ghost_boxes( L0L1_datahier, quantities, fine_ilvl, fine_subcycle_time) for qty in quantities: for fine_level_ghost_box_data in fine_level_qty_ghost_boxes[ qty]: fine_subcycle_pd = fine_level_ghost_box_data["pdata"] for fine_level_ghost_box_info in fine_level_ghost_box_data[ "boxes"]: # trim the border level ghost nodes from the primal fields to ignore them in comparison checks fine_level_ghost_boxes = fine_level_ghost_box_info - boxm.grow( fine_subcycle_pd.box, fine_subcycle_pd.primal_directions()) if ndim == 1: self.assertEqual( len(fine_level_ghost_boxes), 1) # should not be possibly > 1 in 1d np.testing.assert_equal( fine_level_ghost_boxes[0].shape, fine_level_ghost_box_info.shape - fine_subcycle_pd.primal_directions()) for fine_level_ghost_box in fine_level_ghost_boxes: upper_dims = fine_level_ghost_box.lower > fine_subcycle_pd.box.upper for refinedInterpolatedField in interpolated_fields[ qty][fine_subcycle_time]: # level_ghost_boxes() includes periodic shifts, which we want to ignore here I think is_periodic_shifted = refinedInterpolatedField.box * fine_subcycle_pd.box is None lvlOverlap = refinedInterpolatedField.ghost_box * fine_level_ghost_box if lvlOverlap is not None and not is_periodic_shifted: fine_ghostbox_data = fine_subcycle_pd[ fine_level_ghost_box] refinedInterpGhostBox_data = refinedInterpolatedField[ fine_level_ghost_box] fine_ds = fine_subcycle_pd.dataset if ndim == 1: # verify selecting start/end of L1 dataset from ghost box if upper_dims[0]: assert all( fine_ghostbox_data == fine_ds[-fine_ghostbox_data. shape[0]:]) else: assert all( fine_ghostbox_data == fine_ds[:fine_ghostbox_data. shape[0]]) assert refinedInterpGhostBox_data.shape == fine_subcycle_pd.ghosts_nbr assert fine_ghostbox_data.shape == fine_subcycle_pd.ghosts_nbr np.testing.assert_allclose( fine_ghostbox_data, refinedInterpGhostBox_data, atol=1e-15, rtol=0) checks += 1 self.assertGreater(checks, len(refinement_boxes["L0"]) * len(quantities))