コード例 #1
0
def merge(lattices, dimension=-1, N=-1):

    # if only one lattice is given, return immediately
    if type(lattices) != list:
        return lattices

    # number of lattices
    n = len(lattices)
    assert n > 0

    # number of batches
    if N == -1:
        N = n
    batches = n // N
    assert n % N == 0

    # all grids need to be the same
    grid = lattices[0].grid
    assert all([lattices[i].grid.obj == grid.obj for i in range(1, n)])

    # allow negative indexing
    if dimension < 0:
        dimension += grid.nd + 1
        assert dimension >= 0
    else:
        assert dimension <= grid.nd

    # infer checkerboarding of new dimension
    cb = [x.checkerboard() for x in lattices]
    if cb[0] is gpt.none:
        assert all([x is gpt.none for x in cb[1:]])
        cb_mask = 0
    else:
        assert all([
            cb[j * N + i] is cb[j * N + i + 1].inv() for i in range(N - 1)
            for j in range(batches)
        ])
        cb_mask = 1

    # otypes must be consistent
    otype = lattices[0].otype
    assert all(
        [lattices[i].otype.__name__ == otype.__name__ for i in range(1, n)])

    # create merged grid
    merged_grid = grid.inserted_dimension(dimension, N, cb_mask=cb_mask)

    # create merged lattices and set checkerboard
    merged_lattices = [gpt.lattice(merged_grid, otype) for i in range(batches)]
    for x in merged_lattices:
        x.checkerboard(cb[0])

    # coordinates of source lattices
    gcoor_zero = gpt.coordinates(lattices[0])
    gcoor_one = gpt.coordinates(
        lattices[1]) if N > 1 and cb_mask == 1 else gcoor_zero
    gcoor = [gcoor_zero, gcoor_one]

    # data transfer
    for i in range(N):
        merged_gcoor = cgpt.coordinates_inserted_dimension(
            gcoor[i % 2], dimension, [i])

        plan = gpt.copy_plan(
            merged_lattices[0],
            lattices[i],
            embed_in_communicator=merged_lattices[0].grid,
        )
        plan.destination += merged_lattices[0].view[merged_gcoor]
        plan.source += lattices[i].view[gcoor[i % 2]]
        plan = plan()

        for j in range(batches):
            plan(merged_lattices[j], lattices[j * N + i])

    # if only one batch, remove list
    if len(merged_lattices) == 1:
        return merged_lattices[0]

    # return
    return merged_lattices
コード例 #2
0
def separate(lattices, dimension=-1):

    # expect list below
    if type(lattices) != list:
        lattices = [lattices]

    # evaluate in case it is an expression
    lattices = [gpt.eval(x) for x in lattices]

    # number of batches to separate
    batches = len(lattices)
    assert batches > 0

    # make sure all have the same grid
    grid = lattices[0].grid
    assert all([lattices[i].grid.obj == grid.obj for i in range(1, batches)])

    # allow negative indexing
    if dimension < 0:
        dimension += grid.nd
        assert dimension >= 0
    else:
        assert dimension < grid.nd

    # number of slices (per batch)
    N = grid.fdimensions[dimension]
    n = N * batches

    # all lattices need to have same checkerboard
    cb = lattices[0].checkerboard()
    assert all([lattices[i].checkerboard() is cb for i in range(1, batches)])

    # all lattices need to have same otype
    otype = lattices[0].otype
    assert all([
        lattices[i].otype.__name__ == otype.__name__
        for i in range(1, batches)
    ])

    # create grid with dimension removed
    separated_grid = grid.removed_dimension(dimension)
    cb_mask = grid.cb.cb_mask[dimension]

    # create separate lattices and set their checkerboard
    separated_lattices = [gpt.lattice(separated_grid, otype) for i in range(n)]
    for i, x in enumerate(separated_lattices):
        j = i % N
        if cb_mask == 0 or j % 2 == 0:
            x.checkerboard(cb)
        else:
            x.checkerboard(cb.inv())

    # construct coordinates
    separated_gcoor_zero = gpt.coordinates(separated_lattices[0])
    separated_gcoor_one = (gpt.coordinates(separated_lattices[1])
                           if N > 1 and cb_mask == 1 else separated_gcoor_zero)
    separated_gcoor = [separated_gcoor_zero, separated_gcoor_one]

    # move data
    for i in range(N):
        gcoor = cgpt.coordinates_inserted_dimension(separated_gcoor[i % 2],
                                                    dimension, [i])

        plan = gpt.copy_plan(separated_lattices[i],
                             lattices[0],
                             embed_in_communicator=lattices[0].grid)
        plan.destination += separated_lattices[i].view[separated_gcoor[i % 2]]
        plan.source += lattices[0].view[gcoor]
        plan = plan()

        for j in range(batches):
            plan(separated_lattices[j * N + i], lattices[j])

    # return
    return separated_lattices