Exemplo n.º 1
0
def build_refinementboxes(domain_box, **kwargs):

    refinement_ratio = kwargs["refinement_ratio"]

    boxes = {}
    for ilvl, boxes_data in kwargs["refinement_boxes"].items():

        level_number = int(ilvl.strip("L")) + 1

        if level_number not in boxes:
            boxes[level_number] = []

        assert isinstance(boxes_data, (list, dict))

        if isinstance(boxes_data, list):
            for _, refinement_box in enumerate(boxes_data):
                refined_box = boxm.refine(refinement_box, refinement_ratio)
                boxes[level_number].append(refined_box)

        else:
            for boxname, lower_upper in boxes_data.items():
                refinement_box = Box(lower_upper[0][0], lower_upper[1][0])
                refined_box = boxm.refine(refinement_box, refinement_ratio)
                boxes[level_number].append(refined_box)

    # coarse level boxes are arbitrarily divided in 2 patches in the middle
    middle_cell = np.round(domain_box.upper / 2)
    lower_box = Box(0, middle_cell)
    upper_box = Box(middle_cell + 1, domain_box.upper)
    boxes[0] = [lower_box, upper_box]

    return boxes
Exemplo n.º 2
0
def build_boxes(domain_box, **kwargs):

    refinement_ratio = kwargs["refinement_ratio"]
    ndim = domain_box.ndim

    boxes = {}
    for ilvl, boxes_data in kwargs["refinement_boxes"].items():

        level_number = int(ilvl.strip("L")) + 1

        if level_number not in boxes:
            boxes[level_number] = []

        assert isinstance(boxes_data, (list, dict))

        if isinstance(boxes_data, list):
            for _, refinement_box in enumerate(boxes_data):
                refined_box = boxm.refine(refinement_box, refinement_ratio)
                boxes[level_number].append(refined_box)

        else:
            for boxname, box in boxes_data.items():
                if isinstance(box, Box):
                    refinement_box = Box(box.lower, box.upper)
                else:
                    refinement_box = Box(box[0], box[1])
                refined_box = boxm.refine(refinement_box, refinement_ratio)
                boxes[level_number].append(refined_box)

    # coarse level boxes are arbitrarily divided in 2 patches in the middle

    if (
        "largest_patch_size" in kwargs
        and (kwargs["largest_patch_size"] == domain_box.upper + 1).all()
    ):
        boxes[0] = [Box(domain_box.lower, domain_box.upper + 1)]

    else:
        if ndim == 1:
            middle_cell = np.round(domain_box.upper / 2)
            lower_box = Box(0, middle_cell)
            upper_box = Box(middle_cell + 1, domain_box.upper)

        if ndim >= 2:
            middle_cell = np.round(domain_box.upper / 2)
            lower_box = Box([0] * ndim, middle_cell - 1)
            upper_box = Box(middle_cell, domain_box.upper)

        boxes[0] = [lower_box, upper_box]

        if ndim >= 2:
            boxes[0].append(
                Box([0, middle_cell[1]], [middle_cell[0] - 1, domain_box.upper[1]])
            )
            boxes[0].append(
                Box([middle_cell[0], 0], [domain_box.upper[0], middle_cell[1] - 1])
            )

    return boxes
Exemplo n.º 3
0
def refine(field, **kwargs):
    """
      optional kwargs
        data : for overriding the field dataset so you don't have to make a temporary copy of a field just to have a different dataset
    """
    assert isinstance(field, FieldData)
    kwarg_keys = ["data"]
    assert any([key in kwarg_keys for key in list(kwargs.keys())])

    refinement_ratio = 2
    primal_directions = field.primal_directions()

    data = kwargs.get("data", field.dataset[:])
    if "data" in kwargs:
        assert data.shape == field.dataset.shape

    fine_box    = boxm.refine(field.box, refinement_ratio)
    fine_layout = GridLayout(fine_box, field.origin, field.layout.dl/refinement_ratio, interp_order=field.layout.interp_order)

    assert field.box.ndim == 1
    fine_data = np.zeros(fine_box.shape + primal_directions + (field.ghosts_nbr[0] * 2))

    ghostX = field.ghosts_nbr[0]
    assert ghostX > 0

    cadence = 2

    if primal_directions[0]:
        fine_data[ghostX:-ghostX:cadence] = data[ghostX:-ghostX] # coarse primal on top of fine
        fine_data[ghostX + 1:-(ghostX - 1):cadence] = 0.5*data[ghostX:-ghostX] + 0.5*data[ghostX + 1:-(ghostX - 1)]
    else:
        fine_data[ghostX:-(ghostX + 1):cadence] = 0.25*data[ghostX - 1:-(ghostX + 1)] + 0.75*data[ghostX:-ghostX]
        fine_data[ghostX + 1:-(ghostX - 1):cadence] = 0.25*data[ghostX + 1:-(ghostX - 1)] + 0.75*data[ghostX:-ghostX]

    return FieldData(fine_layout, field.field_name, data=fine_data)
Exemplo n.º 4
0
def make_fig(hier, fig_name, ilvl, extra_collections=[]):
    if cpp.mpi_rank() == 0:
        l0_in_l1 = [boxm.refine(p.box, 2) for p in hier.level(0).patches]
        collections=[{
            "boxes": l0_in_l1,
            "facecolor": "grey",
        }]
        if 1 in hier.levels():
            l1_over_l0 = [p.box for p in hier.level(1).patches]
            collections += [{
                "boxes": l1_over_l0,
                "facecolor": "yellow",
            }]
        hier.plot_2d_patches(1,
            collections=collections + extra_collections,
        ).savefig(fig_name+".png")
Exemplo n.º 5
0
def build_patch_datas(domain_box, boxes, **kwargs):
    quantities = kwargs["quantities"]
    origin = kwargs["origin"]
    interp_order = kwargs["interp_order"]
    domain_size = kwargs["domain_size"]
    cell_width = kwargs["cell_width"]
    refinement_ratio = kwargs["refinement_ratio"]

    skip_particles = False
    if "particles" in quantities:
        del quantities[quantities.index("particles")]
    else:
        skip_particles = True

    domain_layout = GridLayout(domain_box, origin, cell_width, interp_order)

    coarse_particles = Particles(box=domain_box)

    # copy domain particles and put them in ghost cells
    particle_ghost_nbr = domain_layout.particleGhostNbr(interp_order)
    box_extend = particle_ghost_nbr - 1

    upper_slct_box = Box(domain_box.upper - box_extend, domain_box.upper)
    lower_slct_box = Box(domain_box.lower, domain_box.lower + box_extend)

    if not skip_particles:
        coarse_particles = Particles(box=domain_box)
        upper_cell_particles = coarse_particles.select(upper_slct_box)
        lower_cell_particles = coarse_particles.select(lower_slct_box)

        coarse_particles.add(
            upper_cell_particles.shift_icell(-domain_box.shape()))
        coarse_particles.add(
            lower_cell_particles.shift_icell(domain_box.shape()))

    patch_datas = {}

    for ilvl, lvl_box in boxes.items():

        lvl_cell_width = cell_width / (refinement_ratio**ilvl)

        if not skip_particles:
            if ilvl == 0:
                lvl_particles = coarse_particles
            else:
                level_domain_box = boxm.refine(domain_box, refinement_ratio)
                lvl_ghost_domain_box = boxm.grow(
                    level_domain_box,
                    domain_layout.particleGhostNbr(interp_order))
                lvl_particles = Particles(box=lvl_ghost_domain_box)

        if ilvl not in patch_datas:
            patch_datas[ilvl] = []

        for box in lvl_box:

            ghost_box = boxm.grow(box, 5)
            origin = box.lower * lvl_cell_width
            layout = GridLayout(box, origin, lvl_cell_width, interp_order)

            datas = {
                qty: globals()[qty](ghost_box, layout, domain_size)
                for qty in quantities
            }

            if not skip_particles:
                datas["particles"] = lvl_particles.select(ghost_box)

            boxed_patch_datas = {}
            for qty_name, data in datas.items():
                if qty_name == 'particles':
                    pdata = ParticleData(layout, data, "pop_name")
                else:
                    pdata = FieldData(layout, qty_name, data)

                boxed_patch_datas[qty_name] = pdata

            patch_datas[ilvl].append(boxed_patch_datas)

    return patch_datas
Exemplo n.º 6
0
 def test_box_refinement(self, coarse, exp_refined):
     actual_refined = boxm.refine(coarse, 2)
     self.assertEqual(actual_refined, exp_refined)
Exemplo n.º 7
0
def coarsen(qty, coarseField, fineField, coarseBox, fineData, coarseData):
    coarseLayout = coarseField.layout
    fineLayout = fineField.layout
    ndim = coarseLayout.box.ndim

    nGhosts = coarseLayout.nbrGhostFor(qty)
    coarseStartIndex = coarseLayout.physicalStartIndices(qty)
    fineOffset = fineLayout.box.lower - boxm.refine(coarseLayout.box, 2).lower

    is_primal = []
    for direction in directions[:ndim]:
        is_primal += [gridlayout.yee_element_is_primal(qty, direction)]

    def coarse_indices(dim):
        return np.arange(coarseBox.lower[dim], coarseBox.upper[dim] + 1)

    def fineLocal(coarse_index, dim):
        return fineLayout.AMRIndexToLocal(dim, coarse_index * refinement_ratio)

    def coarseLocal(index, dim):
        return coarseLayout.AMRIndexToLocal(dim, index)

    if ndim == 1:
        for index in coarse_indices(0):
            fineIndex = fineLocal(index, 0)
            coarseLocalIndex = coarseLocal(index, 0)
            if is_primal[0]:
                coarseData[coarseLocalIndex] = (
                    fineData[fineIndex - 1] * .25 + fineData[fineIndex] * .5 + fineData[fineIndex + 1] * .25
                )
            else:
                coarseData[coarseLocalIndex] = (
                    fineData[fineIndex] * .5 + fineData[fineIndex + 1] * .5
                )

    if ndim == 2:
        for indexX in coarse_indices(0):
            fineIndexX = fineLocal(indexX, 0)
            coarseLocalIndexX = coarseLocal(indexX, 0)

            for indexY in coarse_indices(1):
                fineIndexY = fineLocal(indexY, 1)
                coarseLocalIndexY = coarseLocal(indexY, 1)
                left, middle, right = 0, 0, 0
                if all(is_primal):
                    left += fineData[fineIndexX - 1][fineIndexY - 1]  * .25
                    left += fineData[fineIndexX - 1][fineIndexY]      * .5
                    left += fineData[fineIndexX - 1][fineIndexY + 1]  * .25
                    middle += fineData[fineIndexX][fineIndexY - 1]    * .25
                    middle += fineData[fineIndexX][fineIndexY]        * .5
                    middle += fineData[fineIndexX][fineIndexY + 1]    * .25
                    right += fineData[fineIndexX + 1][fineIndexY - 1] * .25
                    right += fineData[fineIndexX + 1][fineIndexY]     * .5
                    right += fineData[fineIndexX + 1][fineIndexY + 1] * .25
                    coarseData[coarseLocalIndexX][coarseLocalIndexY] = (
                        left * .25 + middle * .5 + right * .25
                    )

                if is_primal[0] and not is_primal[1]:
                    left += fineData[fineIndexX - 1][fineIndexY]      * .5
                    left += fineData[fineIndexX - 1][fineIndexY + 1]  * .5
                    middle += fineData[fineIndexX][fineIndexY]        * .5
                    middle += fineData[fineIndexX][fineIndexY + 1]    * .5
                    right += fineData[fineIndexX + 1][fineIndexY]     * .5
                    right += fineData[fineIndexX + 1][fineIndexY + 1] * .5
                    coarseData[coarseLocalIndexX][coarseLocalIndexY] = (
                        left * .25 + middle * .5 + right * .25
                    )

                if not is_primal[0] and is_primal[1]:
                    left += fineData[fineIndexX][fineIndexY - 1]      * .25
                    left += fineData[fineIndexX][fineIndexY]          * .5
                    left += fineData[fineIndexX][fineIndexY + 1]      * .25
                    right += fineData[fineIndexX + 1][fineIndexY - 1] * .25
                    right += fineData[fineIndexX + 1][fineIndexY]     * .5
                    right += fineData[fineIndexX + 1][fineIndexY + 1] * .25
                    coarseData[coarseLocalIndexX][coarseLocalIndexY] = (left * .5 + right * .5)

                if not any(is_primal):
                    left += fineData[fineIndexX][fineIndexY]          * .5
                    left += fineData[fineIndexX][fineIndexY + 1]      * .5
                    right += fineData[fineIndexX + 1][fineIndexY]     * .5
                    right += fineData[fineIndexX + 1][fineIndexY + 1] * .5
                    coarseData[coarseLocalIndexX][coarseLocalIndexY] = (left * .5 + right * .5)
Exemplo n.º 8
0
    def _test_field_coarsening_via_subcycles(self, dim, interp_order,
                                             refinement_boxes, **kwargs):
        print("test_field_coarsening_via_subcycles for dim/interp : {}/{}".
              format(dim, interp_order))

        from tests.amr.data.field.coarsening.test_coarsen_field import coarsen
        from pyphare.pharein import global_vars

        time_step_nbr = 3

        diag_outputs = f"subcycle_coarsening/{dim}/{interp_order}/{self.ddt_test_id()}"
        datahier = self.getHierarchy(
            interp_order,
            refinement_boxes,
            "eb",
            cells=60,
            diag_outputs=diag_outputs,
            time_step=0.001,
            extra_diag_options={"fine_dump_lvl_max": 10},
            time_step_nbr=time_step_nbr,
            largest_patch_size=30,
            ndim=dim,
            **kwargs)

        lvl_steps = global_vars.sim.level_time_steps
        print("LEVELSTEPS === ", lvl_steps)
        assert len(lvl_steps) > 1, "this test makes no sense with only 1 level"

        finestTimeStep = lvl_steps[-1]
        secondFinestTimeStep = lvl_steps[-2]

        finest_level_step_nbr = global_vars.sim.level_step_nbr[-1]
        uniqTimes = set([0])

        for step in range(1, finest_level_step_nbr + 1):
            checkTime = datahier.format_timestamp(finestTimeStep * step)
            self.assertIn(checkTime, datahier.times())
            uniqTimes.add(checkTime)

        self.assertEqual(len(uniqTimes), len(datahier.time_hier.items()))

        syncSteps = global_vars.sim.level_step_nbr[
            -2]  # ignore finest subcycles

        # FIX THIS AFTER NO MORE REGRIDS
        #  SEE: https://github.com/PHAREHUB/PHARE/issues/400
        assert syncSteps % time_step_nbr == 0  # perfect division
        startStep = int(
            syncSteps /
            time_step_nbr) + 1  # skip first coarsest step due to issue 400

        for step in range(startStep, syncSteps + 1):
            checkTime = datahier.format_timestamp(secondFinestTimeStep * step)
            self.assertIn(checkTime, datahier.times())
            nLevels = datahier.levelNbr(checkTime)
            self.assertGreaterEqual(nLevels, 2)
            levelNbrs = datahier.levelNbrs(checkTime)
            finestLevelNbr = max(levelNbrs)
            coarsestLevelNbr = min(levelNbrs)

            for coarseLevelNbr in range(coarsestLevelNbr, finestLevelNbr):
                coarsePatches = datahier.level(coarseLevelNbr,
                                               checkTime).patches
                finePatches = datahier.level(coarseLevelNbr + 1,
                                             checkTime).patches

                for coarsePatch in coarsePatches:
                    for finePatch in finePatches:
                        lvlOverlap = boxm.refine(coarsePatch.box,
                                                 2) * finePatch.box
                        if lvlOverlap is not None:
                            for EM in ["E", "B"]:
                                for xyz in ["x", "y", "z"]:
                                    qty = f"{EM}{xyz}"
                                    coarse_pd = coarsePatch.patch_datas[qty]
                                    fine_pd = finePatch.patch_datas[qty]
                                    coarseBox = boxm.coarsen(lvlOverlap, 2)

                                    coarse_pdDataset = coarse_pd.dataset[:]
                                    fine_pdDataset = fine_pd.dataset[:]

                                    coarseOffset = coarseBox.lower - coarse_pd.layout.box.lower
                                    dataBox_lower = coarseOffset + coarse_pd.layout.nbrGhostFor(
                                        qty)
                                    dataBox = Box(
                                        dataBox_lower,
                                        dataBox_lower + coarseBox.shape - 1)
                                    afterCoarse = np.copy(coarse_pdDataset)

                                    # change values that should be updated to make failure obvious
                                    assert (dim < 3)  # update
                                    if dim == 1:
                                        afterCoarse[dataBox.
                                                    lower[0]:dataBox.upper[0] +
                                                    1] = -144123
                                    if dim == 2:
                                        afterCoarse[
                                            dataBox.lower[0]:dataBox.upper[0] +
                                            1,
                                            dataBox.lower[1]:dataBox.upper[1] +
                                            1] = -144123

                                    coarsen(qty, coarse_pd, fine_pd, coarseBox,
                                            fine_pdDataset, afterCoarse)
                                    np.testing.assert_allclose(
                                        coarse_pdDataset,
                                        afterCoarse,
                                        atol=1e-16,
                                        rtol=0)
Exemplo n.º 9
0
def refine(field, **kwargs):
    """
    optional kwargs
      data : for overriding the field dataset so you don't have to make a temporary copy of a field just to have a different dataset
    """
    assert isinstance(field, FieldData)
    kwarg_keys = ["data"]
    assert any([key in kwarg_keys for key in list(kwargs.keys())])

    refinement_ratio = 2
    primal_directions = field.primal_directions()

    data = kwargs.get("data", field.dataset[:])
    if "data" in kwargs:
        assert data.shape == field.dataset.shape

    fine_layout = GridLayout(
        boxm.refine(field.box, refinement_ratio),
        field.origin,
        field.layout.dl / refinement_ratio,
        interp_order=field.layout.interp_order,
    )

    # fine box has extra ghosts for padding against coarser such that at the normal number of ghosts are filled
    fine_box = boxm.shrink(boxm.refine(field.ghost_box, refinement_ratio),
                           field.ghosts_nbr)
    fine_data = np.zeros(fine_box.shape + primal_directions +
                         (field.ghosts_nbr * 2))

    ghostX = field.ghosts_nbr[0]
    assert ghostX > 1

    cadence = 2
    assert cadence == refinement_ratio

    gX = 2  # level 0 ghost buffer from edge of normal coarse data box
    rgX = 4  # level 1 ghost buffer from edge of extra large fine data box

    if field.box.ndim == 1:
        if primal_directions[0]:
            # coarse primal on top of fine
            fine_data[rgX:-rgX:cadence] = data[gX:-gX]
            fine_data[rgX +
                      1:-(rgX - 1):cadence] = (0.5 * data[gX:-gX] +
                                               0.5 * data[gX + 1:-(gX - 1)])
        else:
            fine_data[rgX:-(rgX + 1):cadence] = (
                0.25 * data[gX - 1:-(gX + 1)] + 0.75 * data[gX:-gX])
            fine_data[rgX +
                      1:-(rgX - 1):cadence] = (0.25 * data[gX + 1:-(gX - 1)] +
                                               0.75 * data[gX:-gX])

    if fine_box.ndim > 1:
        assert field.ghosts_nbr[1] > 1
        gY = 2
        rgY = 4
        cad = cadence

    if fine_box.ndim == 2:
        if all(primal_directions):
            fine_data[rgX:-rgX:cad, rgY:-rgY:cad] = data[gX:-gX, gY:-gY]
            fine_data[rgX + 1:-(rgX - 1):cad,
                      rgY:-rgY:cad] = (0.5 * data[gX:-gX, gY:-gY] +
                                       0.5 * data[gX + 1:-(gX - 1), gY:-gY])
            fine_data[rgX:-rgX:cad, rgY + 1:-(rgY - 1):cad] = (
                0.5 * data[gX:-gX, gY:-gY] +
                0.5 * data[gX:-gX, gY + 1:-(gY - 1)])
            fine_data[rgX + 1:-(rgX - 1):cad, rgY + 1:-(rgY - 1):cad] = (
                0.25 * data[gX:-gX, gY:-gY] +
                0.25 * data[gX + 1:-(gX - 1), gY:-gY] +
                0.25 * data[gX:-gX, gY + 1:-(gY - 1)] +
                0.25 * data[gX + 1:-(gX - 1), gY + 1:-(gY - 1)])

        elif primal_directions[0] and not primal_directions[1]:
            fine_data[rgX:-rgX:cad,
                      rgY:-rgY:cad] = (0.25 * data[gX:-gX, gY - 1:-(gY + 1)] +
                                       0.75 * data[gX:-gX, gY:-gY])
            fine_data[rgX + 1:-(rgX - 1):cad, rgY:-rgY:cad] = 0.75 * (
                0.5 * data[gX + 1:-(gX - 1), gY:-gY] +
                0.5 * data[gX:-gX, gY:-gY]) + 0.25 * (
                    0.5 * data[gX + 1:-(gX - 1), gY - 1:-(gY + 1)] +
                    0.5 * data[gX:-gX, gY - 1:-(gY + 1)])
            fine_data[rgX:-rgX:cad, rgY + 1:-(rgY - 1):cad] = (
                0.25 * data[gX:-gX, gY + 1:-(gY - 1)] +
                0.75 * data[gX:-gX, gY:-gY])
            fine_data[rgX + 1:-(rgX - 1):cad,
                      rgY + 1:-(rgY - 1):cad] = 0.75 * (
                          0.5 * data[gX + 1:-(gX - 1), gY:-gY] +
                          0.5 * data[gX:-gX, gY:-gY]) + 0.25 * (
                              0.5 * data[gX + 1:-(gX - 1), gY + 1:-(gY - 1)] +
                              0.5 * data[gX:-gX, gY + 1:-(gY - 1)])

        elif not primal_directions[0] and primal_directions[1]:
            fine_data[rgX:-rgX:cad,
                      rgY:-rgY:cad] = (0.25 * data[gX - 1:-(gX + 1), gY:-gY] +
                                       0.75 * data[gX:-gX, gY:-gY])
            fine_data[rgX + 1:-(rgX - 1):cad,
                      rgY:-rgY:cad] = (0.25 * data[gX + 1:-(gX - 1), gY:-gY] +
                                       0.75 * data[gX:-gX, gY:-gY])
            fine_data[rgX:-rgX:cad, rgY + 1:-(rgY - 1):cad] = 0.5 * (
                0.25 * data[gX - 1:-(gX + 1), gY:-gY] +
                0.75 * data[gX:-gX, gY:-gY]) + 0.5 * (
                    0.25 * data[gX - 1:-(gX + 1), gY + 1:-(gY - 1)] +
                    0.75 * data[gX:-gX, gY + 1:-(gY - 1)])
            fine_data[rgX + 1:-(rgX - 1):cad, rgY + 1:-(rgY - 1):cad] = 0.5 * (
                0.25 * data[gX + 1:-(gX - 1), gY:-gY] +
                0.75 * data[gX:-gX, gY:-gY]) + 0.5 * (
                    0.25 * data[gX + 1:-(gX - 1), gY + 1:-(gY - 1)] +
                    0.75 * data[gX:-gX, gY + 1:-(gY - 1)])

        elif not any(primal_directions):
            fine_data[rgX:-rgX:cad, rgY:-rgY:cad] = 0.75 * (
                0.25 * data[gX - 1:-(gX + 1), gY:-gY] +
                0.75 * data[gX:-gX, gY:-gY]) + 0.25 * (
                    0.25 * data[gX - 1:-(gX + 1), gY - 1:-(gY + 1)] +
                    0.75 * data[gX:-gX, gY - 1:-(gY + 1)])
            fine_data[rgX + 1:-(rgX - 1):cad, rgY:-rgY:cad] = 0.75 * (
                0.25 * data[gX + 1:-(gX - 1), gY:-gY] +
                0.75 * data[gX:-gX, gY:-gY]) + 0.25 * (
                    0.25 * data[gX + 1:-(gX - 1), gY - 1:-(gY + 1)] +
                    0.75 * data[gX:-gX, gY - 1:-(gY + 1)])
            fine_data[rgX:-rgX:cad, rgY + 1:-(rgY - 1):cad] = 0.75 * (
                0.25 * data[gX - 1:-(gX + 1), gY:-gY] +
                0.75 * data[gX:-gX, gY:-gY]) + 0.25 * (
                    0.25 * data[gX - 1:-(gX + 1), gY + 1:-(gY - 1)] +
                    0.75 * data[gX:-gX, gY + 1:-(gY - 1)])
            fine_data[rgX + 1:-(rgX - 1):cad,
                      rgY + 1:-(rgY - 1):cad] = 0.75 * (
                          0.25 * data[gX + 1:-(gX - 1), gY:-gY] +
                          0.75 * data[gX:-gX, gY:-gY]) + 0.25 * (
                              0.25 * data[gX + 1:-(gX - 1), gY + 1:-(gY - 1)] +
                              0.75 * data[gX:-gX, gY + 1:-(gY - 1)])

    # the fine data is ghost_nbr larger than expected to include ghost values from the coarser, so we drop the outer values
    if field.box.ndim == 1:
        fine_data = fine_data[field.ghosts_nbr[0]:-field.ghosts_nbr[0]]
    elif field.box.ndim == 2:
        fine_data = fine_data[field.ghosts_nbr[0]:-field.ghosts_nbr[0],
                              field.ghosts_nbr[1]:-field.ghosts_nbr[1], ]
    elif field.box.ndim == 3:
        fine_data = fine_data[field.ghosts_nbr[0]:-field.ghosts_nbr[0],
                              field.ghosts_nbr[1]:-field.ghosts_nbr[1],
                              field.ghosts_nbr[2]:-field.ghosts_nbr[2], ]
    return FieldData(fine_layout, field.field_name, data=fine_data)