Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
dbrakenhoff opened this issue Jul 10, 2024 · 1 comment · Fixed by #2271
Labels

Comments

@dbrakenhoff
Copy link
Contributor

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.

@langevin-usgs
Copy link
Contributor

Excellent, @dbrakenhoff. Good find. Thanks for reporting this. Feel free to submit a PR or I can try to take a look the week after next.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants