From ca607a7c72aad8dbb845be8f8c3a9ac1e858e845 Mon Sep 17 00:00:00 2001 From: Juan Ignacio Polanco Date: Tue, 5 Nov 2024 17:08:54 +0100 Subject: [PATCH 1/4] Allow passing cells in non-concrete container type Fixes #155 --- src/gridtypes/unstructured/unstructured.jl | 27 ++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/gridtypes/unstructured/unstructured.jl b/src/gridtypes/unstructured/unstructured.jl index a2a5e66d..5c8e72fa 100644 --- a/src/gridtypes/unstructured/unstructured.jl +++ b/src/gridtypes/unstructured/unstructured.jl @@ -143,6 +143,21 @@ function vtk_grid(dtype::VTKUnstructuredGrid, filename::AbstractString, vtk end +# If the type of `cells` is not concrete, then try to guess the actual cell type and convert +# the vector to a concrete type. +# This usually happens when a user initialises a cell vector as MeshCell[] (which is not +# completely inferred) and then pushes cells into that vector. +function _adapt_cells(cells::AbstractVector) + if isconcretetype(eltype(cells)) + cells + elseif !isempty(cells) + CellType = typeof(first(cells)) # concrete cell type (assume container is homogeneous) + convert(Vector{CellType}, cells) + else + throw(ArgumentError("concrete cell type cannot be determined (cells vector is empty)")) + end +end + # Variant of vtk_grid with 2-D array "points". # size(points) = (dim, num_points), with dim ∈ {1, 2, 3} """ @@ -157,8 +172,9 @@ Create an unstructured mesh image data (`.vtu`) file. `X` is a matrix with each column containing the Cartesian coordinates of a point """ function vtk_grid(filename::AbstractString, points::AbstractArray{T,2}, - cells::CellVector, args...; kwargs...) where T + cells_in::CellVector, args...; kwargs...) where T dim, Npts = size(points) + cells = _adapt_cells(cells_in) gtype = grid_type(eltype(cells)) if dim == 3 @@ -200,11 +216,12 @@ Create an unstructured mesh image data (`.vtu`) file. """ function vtk_grid(filename::AbstractString, x::AbstractVector{T}, y::AbstractVector{T}, z::AbstractVector{T}, - cells::CellVector, args...; kwargs...) where {T} + cells_in::CellVector, args...; kwargs...) where {T} if !(length(x) == length(y) == length(z)) throw(DimensionMismatch("length of x, y and z arrays must be the same.")) end points = (x, y, z) + cells = _adapt_cells(cells_in) gtype = grid_type(eltype(cells)) vtk_grid(gtype, filename, points, cells, args...; kwargs...) end @@ -236,7 +253,8 @@ Create an unstructured mesh image data (`.vtu`) file. `xs` is a vector of coordinates, such as a vector of `SVector{3}` elements. """ function vtk_grid(filename::AbstractString, xs::AbstractVector, - cells::CellVector, args...; kwargs...) + cells_in::CellVector, args...; kwargs...) + cells = _adapt_cells(cells_in) gtype = grid_type(eltype(cells)) vtk_grid(gtype, filename, xs, cells, args...; kwargs...) end @@ -244,9 +262,10 @@ end # Variant with 4-D Array (for "pseudo-unstructured" datasets, i.e., those that # actually have a 3D structure) -- maybe this variant should be removed... function vtk_grid(filename::AbstractString, points::AbstractArray{T,4}, - cells::CellVector, args...; kwargs...) where T + cells_in::CellVector, args...; kwargs...) where T dim, Ni, Nj, Nk = size(points) points_r = reshape(points, dim, Ni * Nj * Nk) + cells = _adapt_cells(cells_in) gtype = grid_type(eltype(cells)) vtk_grid(gtype, filename, points_r, cells, args...; kwargs...) end From 4ce22f35fe8319ae043ec3b4b081350307d0c164 Mon Sep 17 00:00:00 2001 From: Juan Ignacio Polanco Date: Wed, 6 Nov 2024 11:46:22 +0100 Subject: [PATCH 2/4] Use identity.(cells) --- src/gridtypes/unstructured/unstructured.jl | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/gridtypes/unstructured/unstructured.jl b/src/gridtypes/unstructured/unstructured.jl index 5c8e72fa..b1e463d8 100644 --- a/src/gridtypes/unstructured/unstructured.jl +++ b/src/gridtypes/unstructured/unstructured.jl @@ -150,11 +150,8 @@ end function _adapt_cells(cells::AbstractVector) if isconcretetype(eltype(cells)) cells - elseif !isempty(cells) - CellType = typeof(first(cells)) # concrete cell type (assume container is homogeneous) - convert(Vector{CellType}, cells) else - throw(ArgumentError("concrete cell type cannot be determined (cells vector is empty)")) + identity.(cells) # tighten the element type of the container end end From 890a7941ce2ae68f470a57aa12cf8f4274e075e5 Mon Sep 17 00:00:00 2001 From: Juan Ignacio Polanco Date: Wed, 6 Nov 2024 12:12:18 +0100 Subject: [PATCH 3/4] Show error if cells element type is not concrete --- src/gridtypes/unstructured/unstructured.jl | 40 +++++++++++++--------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/src/gridtypes/unstructured/unstructured.jl b/src/gridtypes/unstructured/unstructured.jl index b1e463d8..91760653 100644 --- a/src/gridtypes/unstructured/unstructured.jl +++ b/src/gridtypes/unstructured/unstructured.jl @@ -143,16 +143,24 @@ function vtk_grid(dtype::VTKUnstructuredGrid, filename::AbstractString, vtk end -# If the type of `cells` is not concrete, then try to guess the actual cell type and convert -# the vector to a concrete type. -# This usually happens when a user initialises a cell vector as MeshCell[] (which is not -# completely inferred) and then pushes cells into that vector. -function _adapt_cells(cells::AbstractVector) - if isconcretetype(eltype(cells)) - cells +# If the type of `cells` is not concrete, throw an error describing the proper (type stable) +# way of initialising a vector of cells to be passed to vtk_grid. +function check_cells(cells::AbstractVector) + isconcretetype(eltype(cells)) && return nothing + s = if isempty(cells) + "" # we can't guess the cell type else - identity.(cells) # tighten the element type of the container + CellType = typeof(first(cells)) # try guessing cell type from first cell + """ + Try initialising it as: + + cells = $(string(CellType))[] + + before appending cells to it. + """ end + s = replace(s, "VTKBase." => "") # e.g. VTKBase.PolyData.Polys => PolyData.Polys + throw(ArgumentError("The concrete cell type cannot be inferred from the given `cells` vector.$s")) end # Variant of vtk_grid with 2-D array "points". @@ -169,9 +177,9 @@ Create an unstructured mesh image data (`.vtu`) file. `X` is a matrix with each column containing the Cartesian coordinates of a point """ function vtk_grid(filename::AbstractString, points::AbstractArray{T,2}, - cells_in::CellVector, args...; kwargs...) where T + cells::CellVector, args...; kwargs...) where T dim, Npts = size(points) - cells = _adapt_cells(cells_in) + check_cells(cells) gtype = grid_type(eltype(cells)) if dim == 3 @@ -213,12 +221,12 @@ Create an unstructured mesh image data (`.vtu`) file. """ function vtk_grid(filename::AbstractString, x::AbstractVector{T}, y::AbstractVector{T}, z::AbstractVector{T}, - cells_in::CellVector, args...; kwargs...) where {T} + cells::CellVector, args...; kwargs...) where {T} if !(length(x) == length(y) == length(z)) throw(DimensionMismatch("length of x, y and z arrays must be the same.")) end points = (x, y, z) - cells = _adapt_cells(cells_in) + check_cells(cells) gtype = grid_type(eltype(cells)) vtk_grid(gtype, filename, points, cells, args...; kwargs...) end @@ -250,8 +258,8 @@ Create an unstructured mesh image data (`.vtu`) file. `xs` is a vector of coordinates, such as a vector of `SVector{3}` elements. """ function vtk_grid(filename::AbstractString, xs::AbstractVector, - cells_in::CellVector, args...; kwargs...) - cells = _adapt_cells(cells_in) + cells::CellVector, args...; kwargs...) + check_cells(cells) gtype = grid_type(eltype(cells)) vtk_grid(gtype, filename, xs, cells, args...; kwargs...) end @@ -259,10 +267,10 @@ end # Variant with 4-D Array (for "pseudo-unstructured" datasets, i.e., those that # actually have a 3D structure) -- maybe this variant should be removed... function vtk_grid(filename::AbstractString, points::AbstractArray{T,4}, - cells_in::CellVector, args...; kwargs...) where T + cells::CellVector, args...; kwargs...) where T dim, Ni, Nj, Nk = size(points) points_r = reshape(points, dim, Ni * Nj * Nk) - cells = _adapt_cells(cells_in) + check_cells(cells) gtype = grid_type(eltype(cells)) vtk_grid(gtype, filename, points_r, cells, args...; kwargs...) end From bd8b593ea1626ba618d03b15f0f4ba721f174932 Mon Sep 17 00:00:00 2001 From: Juan Ignacio Polanco Date: Wed, 6 Nov 2024 13:00:40 +0100 Subject: [PATCH 4/4] We don't need `string` --- src/gridtypes/unstructured/unstructured.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gridtypes/unstructured/unstructured.jl b/src/gridtypes/unstructured/unstructured.jl index 91760653..bcb89817 100644 --- a/src/gridtypes/unstructured/unstructured.jl +++ b/src/gridtypes/unstructured/unstructured.jl @@ -154,7 +154,7 @@ function check_cells(cells::AbstractVector) """ Try initialising it as: - cells = $(string(CellType))[] + cells = $(CellType)[] before appending cells to it. """