diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ea60816..0796f8fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,8 @@ # Changelog + +## [1.15.0] + - add and export `explode` function that produces a grid with all adjacencies removed + ## [1.14.2] - 2025-11-25 - less allocations in gFindLocal diff --git a/Project.toml b/Project.toml index 42e505df..c18a3330 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "ExtendableGrids" uuid = "cfc395e8-590f-11e8-1f13-43a2532b2fa8" authors = ["Juergen Fuhrmann ", "Christian Merdon ", "Johannes Taraz ", "Patrick Jaap "] -version = "1.14.2" +version = "1.15.0" [deps] AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c" diff --git a/docs/src/more.md b/docs/src/more.md index 57073e4c..675f104d 100644 --- a/docs/src/more.md +++ b/docs/src/more.md @@ -5,3 +5,9 @@ Modules = [ExtendableGrids] Pages = ["derived.jl","more.jl"] ``` + +## Additional Functions + +```@docs +explode +``` diff --git a/src/ExtendableGrids.jl b/src/ExtendableGrids.jl index be3d404a..07a1a5f8 100644 --- a/src/ExtendableGrids.jl +++ b/src/ExtendableGrids.jl @@ -78,7 +78,7 @@ export num_cellregions, num_bfaceregions, num_bedgeregions export gridcomponents export isconsistent, dangling_nodes export seemingly_equal, numbers_match -export trim!, trim +export trim!, trim, explode include("partitioning.jl") export PColorPartitions, PartitionCells, PartitionBFaces, PartitionNodes, NodePermutation, PartitionEdges diff --git a/src/extendablegrid.jl b/src/extendablegrid.jl index edf42691..a77c5d8d 100644 --- a/src/extendablegrid.jl +++ b/src/extendablegrid.jl @@ -823,3 +823,118 @@ function trim(grid::ExtendableGrid; keep = []) return grid_copy end + + +""" +$(TYPEDSIGNATURES) + +Remove all adjacency information from a grid, creating independent cells by duplicating coordinates +and assigning new node indices while keeping the original coordinates. + +This function creates a new grid where each cell has its own independent set of nodes by duplicating +the coordinate information and creating new node indices. The original coordinates are preserved, +but adjacency information is removed. + +# Arguments +- `grid::ExtendableGrid`: The input grid to be processed + +# Returns +- `::ExtendableGrid`: A new grid with duplicated coordinates and independent cells +""" +function explode(grid::ExtendableGrid) + # create a new grid with the same type parameters + Tc = coord_type(grid) + Ti = index_type(grid) + new_grid = ExtendableGrid{Tc, Ti}() + + # get original coordinates and cell-node adjacency + coords = grid[Coordinates] + cellnodes = grid[CellNodes] + + # create new coordinates array by duplicating nodes for each cell + n_cells = num_cells(grid) + nodes_per_cell = size(cellnodes, 1) + new_coords = similar(coords, size(coords, 1), n_cells * nodes_per_cell) + + # create new cell-node adjacency where each cell gets its own nodes + new_cellnodes = similar(cellnodes) + + # fill new coordinates and cell-node adjacency + for icell in 1:n_cells + for inode in 1:nodes_per_cell + original_node = cellnodes[inode, icell] + new_node = (icell - 1) * nodes_per_cell + inode + new_coords[:, new_node] = coords[:, original_node] + new_cellnodes[inode, icell] = new_node + end + end + + # assign the new coordinates and cell-node adjacency + new_grid[Coordinates] = new_coords + new_grid[CellNodes] = new_cellnodes + + # reference original grid as parent + new_grid[ParentGrid] = grid + new_grid[CellParents] = collect(Ti, 1:n_cells) + + # copy other components + if haskey(grid, CellGeometries) + new_grid[CellGeometries] = grid[CellGeometries] + end + if haskey(grid, CellRegions) + new_grid[CellRegions] = grid[CellRegions] + end + + # handle boundary face nodes and regions + if haskey(grid, BFaceNodes) + # create new boundary face nodes by duplicating for each cell + bfacenodes = grid[BFaceNodes] + bfacecells = grid[BFaceCells] + n_bfaces = num_bfaces(grid) + nodes_per_bface = size(bfacenodes, 1) + new_bfacenodes = similar(bfacenodes) + + # map boundary face nodes to new node indices using cell information + for ibface in 1:n_bfaces + # get the cell this boundary face belongs to + cell_id = bfacecells[1, ibface] # first entry is the cell ID + for inode in 1:nodes_per_bface + original_node = bfacenodes[inode, ibface] + # find the local node index within the cell + local_node_id = -1 + for icell_node in 1:nodes_per_cell + if cellnodes[icell_node, cell_id] == original_node + local_node_id = icell_node + break + end + end + if local_node_id > 0 + # calculate new node index based on cell and local node position + new_node = (cell_id - 1) * nodes_per_cell + local_node_id + new_bfacenodes[inode, ibface] = new_node + else + error("Could not find node $original_node in cell $cell_id") + end + end + end + + new_grid[BFaceNodes] = new_bfacenodes + end + + # transfer other components + for Component in [ + BFaceRegions, + CellGeometries, + BFaceGeometries, + CoordinateSystem, + ] + + if haskey(grid, Component) + new_grid[Component] = grid[Component] + end + + end + + + return new_grid +end diff --git a/test/test_explode.jl b/test/test_explode.jl new file mode 100644 index 00000000..dfdca8da --- /dev/null +++ b/test/test_explode.jl @@ -0,0 +1,25 @@ +using ExtendableGrids +using Test + +@testset "explode function tests" begin + # create a grid + grid = uniform_refine(grid_unitcube(Tetrahedron3D), 3) + + # Test explode function + exploded_grid = explode(grid) + + # Verify results + @test num_cells(exploded_grid) == num_cells(grid) + @test num_nodes(exploded_grid) == 4 * num_cells(grid) # 4 tetrahedron corners for each cell + + # Verify coordinates are preserved + original_coords = Set([Tuple(grid[Coordinates][:, i]) for i in 1:size(grid[Coordinates], 2)]) + exploded_coords = Set([Tuple(exploded_grid[Coordinates][:, i]) for i in 1:size(exploded_grid[Coordinates], 2)]) + @test original_coords == exploded_coords + + # Verify regions are preserved + @test exploded_grid[CellRegions] == grid[CellRegions] + + # Verify parent relation + @test exploded_grid[ParentGrid] === grid +end