Thanks to visit codestin.com
Credit goes to github.com

Skip to content

bug: flopy.utils.cvfdutil.gridlist_to_disv_gridprops not working for nested grids with arbitrary levels of refinement #2263

Description

@dbrakenhoff

Describe the bug
Creating a nested grid using flopy.utils.cvfdutil.gridlist_to_disv_gridprops does not work correctly when larger cells are connected to 4 or more smaller cells. In that situation vertices are left out of the larger cells, causing the hydraulic connection between the "non-refined" cells and the "refined" cells to be incorrect.

This is caused by the fact that the vertex-to-cell mapping isn't updated as vertices are added to larger cells. This works fine as long as each larger cell shares corner vertices with the smaller cells it is connected to. For a quadtree refinement this works fine, and one refinement level extra (3 cells) is also fine, as the 3rd cell is implicitly added by handling the two smaller cells that share corner vertices with the larger cell.

As an example where this doesn't work, consider the following grid (a 1 to 5 cell refinement):
image

The algorithm does the following:

  • The vertex list for cell 11 is updated with vertex 38 when it's processing vertex 14 (vertex 14 is shared by 4 cells, including cells 11 and 24).
  • The vertex-to-cell mapping for vertex 38 only contains cells 24 and 29.
  • So once it processes vertex 38, it never realizes that this vertex is also used by cell 11.
  • Hence, vertices 47 and 53 are never added to the vertex list for cell 11.

Cell 11 ends up missing vertices on the shared face between the outer and inner grids:
image

To Fix
The simple fix that solved my particular case was to update the vertex-to-cell mapping as vertices are added to the larger cell. Not sure if this is sufficiently robust for all cases, but perhaps it's a good start for supporting arbitrary refinement.

Update function segment_face to accept vertex_cell_dict and icell1 so it updates the vertex-cell mapping when vertices are added to a cell. See the single line addition at the bottom:

def segment_face(ivert, ivlist1, ivlist2, vertices, vertex_cell_dict, icell1):
    # go through ivlist1 and find faces that have ivert
    faces_to_check = []
    for ipos in range(len(ivlist1) - 1):
        face = (ivlist1[ipos], ivlist1[ipos + 1])
        if ivert in face:
            faces_to_check.append(face)

    # go through ivlist2 and find points to check
    points_to_check = []
    for ipos in range(len(ivlist2) - 1):
        if ivlist2[ipos] == ivert:
            points_to_check.append(ivlist2[ipos + 1])
        elif ivlist2[ipos + 1] == ivert:
            points_to_check.append(ivlist2[ipos])

    for face in faces_to_check:
        iva, ivb = face
        x, y = vertices[iva]
        a = Point(x, y)
        x, y = vertices[ivb]
        b = Point(x, y)
        for ivc in points_to_check:
            if ivc not in face:
                x, y = vertices[ivc]
                c = Point(x, y)
                if isBetween(a, b, c):
                    ipos = ivlist1.index(ivb)
                    if ipos == 0:
                        ipos = len(ivlist1) - 1
                    ivlist1.insert(ipos, ivc)
                    vertex_cell_dict[ivc].append(icell1)  # <-- update vertex-cell mapping
                    return True

    return False

Then in to_cvfd() (L244-245) pass those arguments to segment_face

                        # don't share a face, so need to segment if necessary
                        segmented = segment_face(
                            ivert,
                            ivertlist1,
                            ivertlist2,
                            vertexdict_keys,
                            vertex_cell_dict,  # pass vertex_cell_dict to update cells using added vertices
                            icell1,  # pass cell number to update vertex_cell_dict
                        )

To Reproduce
Steps to reproduce the behavior, see notebook:
nested_mf6_grids.zip

Expected behavior
It would be nice if arbitrary levels of refinement were supported by this utility function.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions