Skip to content

10. Cut cells ​

A conservative cut-cell solver needs, for every cell the wall crosses, the fluid fraction of the cell, the fluid fraction of each face, and the separate fluid pieces when the wall splits a cell. FOSSIL computes them exactly from the geometry. This chapter does it in 2-D on the section of chapter 7 and in 3-D on the dragon.

f90
use fossil, only : surface_stl_object, curve_object, cut_cells_2d_t, cut_cells_3d_t, cut_cells_3d, STATUS_OK
use penf,   only : I4P, R8P

implicit none
type(curve_object)       :: section
type(surface_stl_object) :: surface
type(cut_cells_2d_t)     :: cut2
type(cut_cells_3d_t)     :: cut3
real(R8P)                :: x(49), h
integer(I4P)             :: i, k, c(3), p, status

call section%load_from_file(file_name='dragon-section.dat', status=status)
if (status /= STATUS_OK) error stop 'cannot load dragon-section.dat'
x = [(-0.6_R8P + 0.025_R8P * i, i = 0, 48)]                  ! cell edges: 48 cells per direction, h = 0.025
h = 0.025_R8P
call section%cut_cells(x=x, y=x, cut=cut2)
print '(A,I0,A,I0)', '2-D: cut cells ', count(cut2%alpha > 0._R8P .and. cut2%alpha < 1._R8P), &
                     ', cells with 2+ pieces ', count(cut2%pieces > 1)
print '(A,F10.6,A,F10.6)', '     solid area ', sum(1._R8P - cut2%alpha) * h**2, '  curve area ', section%get_area()
c(1:2) = maxloc(cut2%wet_length)
print '(A,I0,A,I0,A,F8.5,A,4F8.5)', '     cell (', c(1), ',', c(2), ') alpha ', cut2%alpha(c(1), c(2)), &
                                    '  apertures ', cut2%aperture(:, c(1), c(2))
  • cut_cells(x=, y=, cut=) takes the cell edges of a block, strictly increasing in each direction, and fills a cut_cells_2d_t. The fluid is outside the solid. Per cell (nx × ny arrays):
    • alpha: the fluid area fraction, 1 in the fluid, 0 in the solid;
    • aperture(4, :, :): the fluid fraction of the four edges, in the order -u, +u, -v, +v;
    • centroid, wet_length, wet_centroid, wet_normal: the fluid centroid and the wetted wall;
    • pieces: the number of separate fluid pieces of the cell, with their measures in piece_area, piece_centroid, ... from index first_piece.
  • The topology is exact (the crossings are decided with the exact orient2d, a point on a grid line belongs to the low cell), the measures exact to round-off. A cell whose boundary does not close (an open loop) is flagged in closed, with alpha = -1.

the 2-D cut cells around the dragon section, each cell shaded by its fluid fraction alpha from cream (solid, 0) to sepia (fluid, 1), the section drawn on top, and the two cells holding two fluid pieces outlined in yellow

f90
call surface%load_from_file(file_name='dragon-placed.stl', guess_format=.true.)
call cut_cells_3d(surface=surface, x=x(1:49:2), y=x(1:49:2), z=x(1:49:2), cut=cut3)    ! 24^3 cells, h = 0.05
print '(A,I0,A,I0,A,I0)', '3-D: cut cells ', count(cut3%alpha > 0._R8P .and. cut3%alpha < 1._R8P), &
                          ', flagged ', count(cut3%pieces < 0), ', cells with 2+ pieces ', count(cut3%pieces > 1)
c = findloc(cut3%pieces, 2)                                   ! the first cell with two fluid pieces
p = cut3%first_piece(c(1), c(2), c(3))
print '(A,I0,A,I0,A,I0,A,F8.5,A,2F8.5)', '     cell (', c(1), ',', c(2), ',', c(3), ') alpha ', &
   cut3%alpha(c(1), c(2), c(3)), '  pieces ', (cut3%piece_volume(p + k) / 0.05_R8P**3, k = 0, 1)
  • cut_cells_3d(surface=, x=, y=, z=, cut=) is a free routine (from use fossil), with a cut_cells_3d_t result: alpha (volume fraction), face_x, face_y, face_z (face fractions), the wetted area, centroid and normal, and the fluid pieces: pieces(i, j, k), numbered from first_piece(i, j, k), each with piece_volume, piece_centroid, its wall terms and piece_face(6, :), the fluid fraction of its six faces.
  • pieces = -1 flags a cell that cannot be trusted: a boundary edge of the mesh crosses it, or its faces do not close. Such a cell has no measures.

the 3-D cells below z = 0 that are not all fluid, drawn as cubes shaded by their fluid fraction: the solid interior cream on the cut plane, the cut cells around it towards sepia, the flagged cells in ember; the dragon above z = 0 as a translucent ghost

The top of the cubes is the plane of the 2-D section: the solid inside, the cut cells around it. The ember cells are flagged, where an open edge of the dragon crosses them.

Running it ​

$ tut10_cut_cells
2-D: cut cells 91, cells with 2+ pieces 2
     solid area   0.072609  curve area   0.072609
     cell (23,41) alpha  0.33034  apertures  0.61695 0.85409 0.00000 0.49297
3-D: cut cells 895, flagged 17, cells with 2+ pieces 75
     cell (13,7,6) alpha  0.06856  pieces  0.06533 0.00323
  • 2-D: 91 cells are cut, 2 of them hold two fluid pieces. Summed over the block, the solid area equals the area of the curve to the printed digits. The cell with the longest wall, (23, 41), is 33 % fluid; its -v edge is entirely solid.
  • 3-D: 895 cells are cut and 75 have two or more fluid pieces. 17 are flagged: the dragon is open (chapter 2), and the cells at its open edges get no measures.
  • In cell (13, 7, 6) the fluid is 6.856 % of the cell, in two pieces of 6.533 % and 0.323 %: their volumes add up to the cell's.

What you learned

curve%cut_cells and cut_cells_3d give exact fluid fractions, apertures and fluid pieces per cell, and flag the cells an open surface makes untrustworthy. Reference: Cut-cell geometry.

Next: 11. Moving bodies.