diff --git a/NEWS.md b/NEWS.md index b109d01..08bf90b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.4.1] 2024-06-25 + +### Fixed + +- Fixed bug in block-assembly whenever owners of touched dofs were not present in the local portion of the FESpace. Since PR[#147](https://github.com/gridap/GridapDistributed.jl/pull/147). + ## [0.4.0] 2024-04-12 ### Changed diff --git a/Project.toml b/Project.toml index 9c0da0a..4353b29 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "GridapDistributed" uuid = "f9701e48-63b3-45aa-9a63-9bc6c271f355" authors = ["S. Badia ", "A. F. Martin ", "F. Verdugo "] -version = "0.4.0" +version = "0.4.1" [deps] BlockArrays = "8e7c35d0-a365-5155-bbbb-fb81a777f24e" diff --git a/src/Algebra.jl b/src/Algebra.jl index cd1a163..57bcbac 100644 --- a/src/Algebra.jl +++ b/src/Algebra.jl @@ -1129,25 +1129,29 @@ function _setup_prange(dofs_gids_prange::PRange,gids;ghost=true,owners=nothing,k end end -function _setup_prange(dofs_gids_prange::AbstractVector{<:PRange}, - gids::AbstractMatrix; - ax=:rows,ghost=true,owners=nothing) +function _setup_prange( + dofs_gids_prange::AbstractVector{<:PRange}, + gids::AbstractMatrix; + ax=:rows,ghost=true,owners=nothing +) @check ax ∈ (:rows,:cols) block_ids = LinearIndices(dofs_gids_prange) + pvcat(x) = map(xi -> vcat(xi...), to_parray_of_arrays(x)) - gids_ax_slice, _owners = map(block_ids,dofs_gids_prange) do id,prange - gids_ax_slice = (ax == :rows) ? gids[id,:] : gids[:,id] - _owners = nothing - if ghost - gids_ax_slice = map(x -> union(x...), to_parray_of_arrays(gids_ax_slice)) - if !isa(owners,Nothing) # Recompute owners for the union - _owners = get_gid_owners(gids_ax_slice,prange) - end + gids_union, owners_union = map(block_ids,dofs_gids_prange) do id, prange + gids_slice = (ax == :rows) ? gids[id,:] : gids[:,id] + gids_union = pvcat(gids_slice) + + owners_union = nothing + if !isnothing(owners) + owners_slice = (ax == :rows) ? owners[id,:] : owners[:,id] + owners_union = pvcat(owners_slice) end - return gids_ax_slice, _owners + + return gids_union, owners_union end |> tuple_of_arrays - return map((p,g,o) -> _setup_prange(p,g;ghost=ghost,owners=o),dofs_gids_prange,gids_ax_slice,_owners) + return map((p,g,o) -> _setup_prange(p,g;ghost=ghost,owners=o),dofs_gids_prange,gids_union,owners_union) end # Create PRange for the rows of the linear system diff --git a/test/BlockSparseMatrixAssemblersTests.jl b/test/BlockSparseMatrixAssemblersTests.jl index c9c3384..82bafc9 100644 --- a/test/BlockSparseMatrixAssemblersTests.jl +++ b/test/BlockSparseMatrixAssemblersTests.jl @@ -9,6 +9,11 @@ using GridapDistributed using PartitionedArrays using GridapDistributed: BlockPVector, BlockPMatrix +get_edge_measures(Ω::Triangulation,dΩ) = sqrt∘CellField(get_array(∫(1)dΩ),Ω) +function get_edge_measures(Ω::GridapDistributed.DistributedTriangulation,dΩ) + return sqrt∘CellField(map(get_array,local_views(∫(1)*dΩ)),Ω) +end + function is_same_vector(x::BlockPVector,y::PVector,Ub,U) y_fespace = GridapDistributed.change_ghost(y,U.gids) x_fespace = GridapDistributed.change_ghost(x,Ub.gids) @@ -33,7 +38,7 @@ function is_same_matrix(Ab::BlockPMatrix,A::PSparseMatrix,Xb,X) return is_same_vector(yb,y,Xb,X) end -function _main(n_spaces,mfs,weakform,Ω,dΩ,U,V) +function _main(n_spaces,mfs,weakform,U,V) biform, liform = weakform # Normal assembly @@ -94,13 +99,14 @@ function main(distribute,parts) ranks = distribute(LinearIndices((prod(parts),))) model = CartesianDiscreteModel(ranks,parts,(0,1,0,1),(8,8)) - Ω = Triangulation(model) + # Conforming tests sol(x) = sum(x) reffe = LagrangianRefFE(Float64,QUAD,1) - V = FESpace(Ω, reffe; dirichlet_tags="boundary") + V = FESpace(model, reffe; dirichlet_tags="boundary") U = TrialFESpace(sol,V) + Ω = Triangulation(model) dΩ = Measure(Ω, 2) biform2((u1,u2),(v1,v2)) = ∫(∇(u1)⋅∇(v1) + u2⋅v2 + u1⋅v2)*dΩ liform2((v1,v2)) = ∫(v1 + v2)*dΩ @@ -109,9 +115,37 @@ function main(distribute,parts) for (n_spaces,weakform) in zip([2,3],[(biform2,liform2),(biform3,liform3)]) for mfs in [BlockMultiFieldStyle(),BlockMultiFieldStyle(2,(1,n_spaces-1))] - _main(n_spaces,mfs,weakform,Ω,dΩ,U,V) + _main(n_spaces,mfs,weakform,U,V) end end + + # Non-conforming tests (tests whether we can fetch neighbors from non-ghosts) + reffe = ReferenceFE(raviart_thomas,Float64,0) + D = FESpace(model,reffe; dirichlet_tags="boundary") + + β_U = 100.0 + Γ = Boundary(model) + Λ = Skeleton(model) + n_Γ = get_normal_vector(Γ) + n_Λ = get_normal_vector(Λ) + dΓ = Measure(Γ,2) + dΛ = Measure(Λ,2) + h_e_Λ = get_edge_measures(Λ,dΛ) + h_e_Γ = get_edge_measures(Γ,dΓ) + lap_dg(u,v) = ∫(∇(u)⊙∇(v))dΩ - + ∫(jump(v⊗n_Λ)⊙(mean(∇(u))))dΛ - + ∫(mean(∇(v))⊙jump(u⊗n_Λ))dΛ - + ∫(v⋅(∇(u)⋅n_Γ))dΓ - + ∫((∇(v)⋅n_Γ)⋅u)dΓ + + ∫(jump(v⊗n_Λ)⊙((β_U/h_e_Λ*jump(u⊗n_Λ))))dΛ + + ∫(v⋅(β_U/h_e_Γ*u))dΓ + + f = VectorValue(1.0,1.0) + biform4((u1,u2),(v1,v2)) = lap_dg(u1,v1) + lap_dg(u1,v1) + ∫(u2⋅v2)*dΩ + liform4((v1,v2)) = ∫(v1⋅f)*dΩ + _main(2,BlockMultiFieldStyle(),(biform4,liform4),D,D) end +main(DebugArray, (2,2)) + end \ No newline at end of file