def METHOD_NAME(sub_grid, parent_grid, parent_grid_boundary_info, new_boundary_type=None):
    """Derives a |BoundaryInfo| for a :class:`SubGrid`.
    Parameters
    ----------
    sub_grid
        The :class:`SubGrid` for which a |BoundaryInfo| is created.
    parent_grid
        The parent |Grid|.
    parent_grid_boundary_info
        The |BoundaryInfo| of the parent |Grid| from which to derive the |BoundaryInfo|
    new_boundary_type
        The boundary type which is assigned to the new boundaries of `subgrid`. If
        `None`, no boundary type is assigned.
    Returns
    -------
    |BoundaryInfo| associated with sub_grid.
    """
    boundary_types = parent_grid_boundary_info.boundary_types
    masks = {}
    for codim in range(1, sub_grid.dim + 1):
        parent_indices = sub_grid.parent_indices(codim)[sub_grid.boundaries(codim)]
        new_boundaries = np.where(np.logical_not(parent_grid.boundary_mask(codim)[parent_indices]))
        new_boundaries_sg_indices = sub_grid.boundaries(codim)[new_boundaries]
        for t in boundary_types:
            m = parent_grid_boundary_info.mask(t, codim)[sub_grid.parent_indices(codim)]
            if t == new_boundary_type:
                m[new_boundaries_sg_indices] = True
            if codim == 1:
                masks[t] = [m]
            else:
                masks[t].append(m)
        if new_boundary_type is not None and new_boundary_type not in boundary_types:
            m = np.zeros(sub_grid.size(codim), dtype=np.bool)
            m[new_boundaries_sg_indices] = True
            if codim == 1:
                masks[new_boundary_type] = [m]
            else:
                masks[new_boundary_type].append(m)
    return GenericBoundaryInfo(sub_grid, masks)