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

Constant fespaces #166

Merged
merged 22 commits into from
Nov 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- Added support for automatic differentiation with ForwardDiff. Since PR[#167](https://github.com/gridap/GridapDistributed.jl/pull/167).
- Added ConstantFESpaces. Since PR[#166](https://github.com/gridap/GridapDistributed.jl/pull/166).

## [0.4.5] 2024-10-08

Expand Down
48 changes: 32 additions & 16 deletions src/Adaptivity.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@

const DistributedAdaptedDiscreteModel{Dc,Dp} = GenericDistributedDiscreteModel{Dc,Dp,<:AbstractArray{<:AdaptedDiscreteModel{Dc,Dp}}}

struct DistributedAdaptedDiscreteModelCache{A,B,C}
model_metadata::A
parent_metadata::B
parent_gids::C
end

function DistributedAdaptedDiscreteModel(
model :: DistributedDiscreteModel,
parent :: DistributedDiscreteModel,
Expand All @@ -12,29 +18,36 @@ function DistributedAdaptedDiscreteModel(
AdaptedDiscreteModel(model,parent,glue)
end
gids = get_cell_gids(model)
metadata = hasproperty(model,:metadata) ? model.metadata : nothing
metadata = DistributedAdaptedDiscreteModelCache(
model.metadata,parent.metadata,get_cell_gids(parent)
)
return GenericDistributedDiscreteModel(models,gids;metadata)
end

function Adaptivity.get_model(model::DistributedAdaptedDiscreteModel)
GenericDistributedDiscreteModel(
map(get_model,local_views(model)),
get_cell_gids(model);
metadata = hasproperty(model,:metadata) ? model.metadata : nothing
metadata = model.metadata.model_metadata
)
end

function Adaptivity.get_parent(model::DistributedAdaptedDiscreteModel)
msg = " Error: Cannot get global parent model. \n
We do not keep the global ids of the parent model within the children.\n
You can extract the local parents with map(get_parent,local_views(model))"
@notimplemented msg
GenericDistributedDiscreteModel(
map(get_parent,local_views(model)),
model.metadata.parent_gids;
metadata = model.metadata.parent_metadata
)
end

function Adaptivity.get_adaptivity_glue(model::DistributedAdaptedDiscreteModel)
return map(Adaptivity.get_adaptivity_glue,local_views(model))
end

function Adaptivity.is_child(m1::DistributedDiscreteModel,m2::DistributedDiscreteModel)
reduce(&,map(Adaptivity.is_child,local_views(m1),local_views(m2)))
end

function Adaptivity.refine(
cmodel::DistributedAdaptedDiscreteModel{Dc},args...;kwargs...
) where Dc
Expand All @@ -48,7 +61,7 @@ function Adaptivity.refine(
fmodel = GenericDistributedDiscreteModel(
map(get_model,local_views(_fmodel)),
get_cell_gids(_fmodel);
metadata=_fmodel.metadata
metadata=_fmodel.metadata.model_metadata
)
glues = get_adaptivity_glue(_fmodel)
return DistributedAdaptedDiscreteModel(fmodel,cmodel,glues)
Expand Down Expand Up @@ -132,11 +145,7 @@ end
function redistribute(model::DistributedAdaptedDiscreteModel,args...;kwargs...)
# Local cmodels are AdaptedDiscreteModels. To correctly dispatch, we need to
# extract the underlying models, then redistribute.
_model = GenericDistributedDiscreteModel(
map(get_model,local_views(model)),
get_cell_gids(model);
metadata=model.metadata
)
_model = get_model(model)
return redistribute(_model,args...;kwargs...)
end

Expand Down Expand Up @@ -507,7 +516,7 @@ end
# Cartesian Model uniform refinement

function Adaptivity.refine(
cmodel::DistributedDiscreteModel{Dc},
cmodel::DistributedCartesianDiscreteModel{Dc},
refs::Integer = 2
) where Dc
Adaptivity.refine(cmodel,Tuple(fill(refs,Dc)))
Expand Down Expand Up @@ -592,7 +601,9 @@ function Adaptivity.refine(
end

fgids = get_cell_gids(fmodel)
metadata = fmodel.metadata
metadata = DistributedAdaptedDiscreteModelCache(
fmodel.metadata,cmodel.metadata,get_cell_gids(cmodel)
)
return GenericDistributedDiscreteModel(fmodels,fgids;metadata)
end

Expand Down Expand Up @@ -909,7 +920,10 @@ function Adaptivity.refine(
) where Dc
fmodels, f_own_to_local = refine_local_models(cmodel,args...;kwargs...)
fgids = refine_cell_gids(cmodel,fmodels,f_own_to_local)
return GenericDistributedDiscreteModel(fmodels,fgids)
metadata = DistributedAdaptedDiscreteModelCache(
nothing,cmodel.metadata,get_cell_gids(cmodel)
)
return GenericDistributedDiscreteModel(fmodels,fgids;metadata)
end

"""
Expand Down Expand Up @@ -978,7 +992,9 @@ function refine_local_models(

# Filter out local models
filtered_fmodels = map(fmodels,f_own_or_ghost_ids) do fmodel,f_own_or_ghost_ids
model = DiscreteModelPortion(get_model(fmodel),f_own_or_ghost_ids).model
model = UnstructuredDiscreteModel( # Necessary to keep the same type
DiscreteModelPortion(get_model(fmodel),f_own_or_ghost_ids)
)
parent = get_parent(fmodel)

_glue = get_adaptivity_glue(fmodel)
Expand Down
7 changes: 3 additions & 4 deletions src/CellData.jl
Original file line number Diff line number Diff line change
Expand Up @@ -362,10 +362,9 @@ struct DistributedInterpolable{Tx,Ty,A} <: Function
interps::A
function DistributedInterpolable(interps::AbstractArray{<:Interpolable})
Tx,Ty = map(interps) do I
fi = I.uh
trian = get_triangulation(fi)
trian = get_triangulation(I.uh)
x = mean(testitem(get_cell_coordinates(trian)))
return typeof(x), return_type(fi,x)
return typeof(x), return_type(I,x)
end |> tuple_of_arrays
Tx = getany(Tx)
Ty = getany(Ty)
Expand Down Expand Up @@ -418,7 +417,7 @@ function Arrays.evaluate!(cache,I::DistributedInterpolable{Tx,Ty},x::AbstractVec
end
if inside
ids[k] = i
vals[k] = yi
vals[k] = copy(yi)
k += 1
end
end
Expand Down
48 changes: 48 additions & 0 deletions src/FESpaces.jl
Original file line number Diff line number Diff line change
Expand Up @@ -869,3 +869,51 @@ function _compute_new_distributed_fixedval(
c = reduce(+,c_i,init=zero(eltype(c_i)))
return c
end

"""
ConstantFESpace(
model::DistributedDiscreteModel;
constraint_type=:global,
kwargs...
)

Distributed equivalent to `ConstantFESpace(model;kwargs...)`.

With `constraint_type=:global`, a single dof is shared by all processors.
This creates a global constraint, which is NOT scalable in parallel. Use at your own peril.

With `constraint_type=:local`, a single dof is owned by each processor and shared with no one else.
This space is locally-constant in each processor, and therefore scalable (but not equivalent
to its serial counterpart).
"""
function FESpaces.ConstantFESpace(
model::DistributedDiscreteModel;
constraint_type=:global,kwargs...
)
@assert constraint_type ∈ [:global,:local]
if constraint_type == :global
msg = "ConstantFESpace is NOT scalable in parallel. For testing purposes only."
@warn msg
end

spaces = map(local_views(model)) do model
ConstantFESpace(model;kwargs...)
end

# Single dof, owned by processor 1 (ghost for all other processors)
nranks = length(spaces)
cell_gids = get_cell_gids(model)
indices = map(partition(cell_gids)) do cell_indices
me = part_id(cell_indices)
if constraint_type == :global
LocalIndices(1,me,Int[1],Int32[1])
else
LocalIndices(nranks,me,Int[me],Int32[me])
end
end
gids = PRange(indices)

trian = DistributedTriangulation(map(get_triangulation,spaces),model)
vector_type = _find_vector_type(spaces,gids)
return DistributedSingleFieldFESpace(spaces,gids,trian,vector_type)
end
54 changes: 48 additions & 6 deletions src/Geometry.jl
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,8 @@ function Geometry.get_background_model(a::DistributedTriangulation)
end

function Geometry.num_cells(a::DistributedTriangulation{Df}) where Df
gids = get_face_gids(a.model,Df)
model = get_background_model(a)
gids = get_face_gids(model,Df)
n_loc_ocells = map(local_views(a),partition(gids)) do a, gids
glue = get_glue(a,Val(Df))
@assert isa(glue,FaceToFaceGlue)
Expand Down Expand Up @@ -504,11 +505,21 @@ function Geometry.BoundaryTriangulation(
BoundaryTriangulation(no_ghost,model;kwargs...)
end

function Geometry.BoundaryTriangulation(
trian::DistributedTriangulation;kwargs...)
BoundaryTriangulation(no_ghost,trian;kwargs...)
end

function Geometry.SkeletonTriangulation(
model::DistributedDiscreteModel;kwargs...)
SkeletonTriangulation(no_ghost,model;kwargs...)
end

function Geometry.SkeletonTriangulation(
trian::DistributedTriangulation;kwargs...)
SkeletonTriangulation(no_ghost,trian;kwargs...)
end

function Geometry.Triangulation(
portion,::Type{ReferenceFE{Dt}},model::DistributedDiscreteModel{Dm};kwargs...) where {Dt,Dm}
# Generate global ordering for the faces of dimension Dt (if needed)
Expand Down Expand Up @@ -537,6 +548,33 @@ function Geometry.SkeletonTriangulation(
DistributedTriangulation(trians,model)
end

# NOTE: The following constructors require adding back the ghost cells:
# Potentially, the input `trian` has had some/all of its ghost cells removed. If we do not
# add them back, some skeleton facets might look like boundary facets to the local constructors...
function Geometry.BoundaryTriangulation(
portion,trian::DistributedTriangulation;kwargs...
)
model = get_background_model(trian)
gids = get_cell_gids(model)
ghosted_trian = add_ghost_cells(trian)
trians = map(local_views(ghosted_trian),partition(gids)) do trian, gids
BoundaryTriangulation(portion,gids,trian;kwargs...)
end
DistributedTriangulation(trians,model)
end

function Geometry.SkeletonTriangulation(
portion,trian::DistributedTriangulation;kwargs...
)
model = get_background_model(trian)
gids = get_cell_gids(model)
ghosted_trian = add_ghost_cells(trian)
trians = map(local_views(ghosted_trian),partition(gids)) do trian, gids
SkeletonTriangulation(portion,gids,trian;kwargs...)
end
DistributedTriangulation(trians,model)
end

function Geometry.Triangulation(
portion,gids::AbstractLocalIndices, args...;kwargs...)
trian = Triangulation(args...;kwargs...)
Expand All @@ -562,8 +600,8 @@ function Geometry.InterfaceTriangulation(
end

function Geometry.InterfaceTriangulation(a::DistributedTriangulation,b::DistributedTriangulation)
trians = map(InterfaceTriangulation,a.trians,b.trians)
@assert a.model === b.model
trians = map(InterfaceTriangulation,a.trians,b.trians)
DistributedTriangulation(trians,a.model)
end

Expand Down Expand Up @@ -623,15 +661,19 @@ function remove_ghost_cells(trian::Triangulation,gids)
remove_ghost_cells(glue,trian,gids)
end

function remove_ghost_cells(trian::Union{SkeletonTriangulation,BoundaryTriangulation},gids)
function remove_ghost_cells(
trian::Union{SkeletonTriangulation,BoundaryTriangulation,Geometry.CompositeTriangulation},
gids
)
model = get_background_model(trian)
Dm = num_cell_dims(model)
glue = get_glue(trian,Val(Dm))
remove_ghost_cells(glue,trian,gids)
end

function remove_ghost_cells(
trian::AdaptedTriangulation{Dc,Dp,<:Union{SkeletonTriangulation,BoundaryTriangulation}},gids) where {Dc,Dp}
trian::AdaptedTriangulation{Dc,Dp,<:Union{SkeletonTriangulation,BoundaryTriangulation}},gids
) where {Dc,Dp}
remove_ghost_cells(trian.trian,gids)
end

Expand Down Expand Up @@ -679,7 +721,7 @@ function _find_owned_skeleton_facets(glue,gids)
end

function add_ghost_cells(dtrian::DistributedTriangulation)
dmodel = dtrian.model
dmodel = get_background_model(dtrian)
add_ghost_cells(dmodel,dtrian)
end

Expand Down Expand Up @@ -729,7 +771,7 @@ function add_ghost_cells(
end

function generate_cell_gids(dtrian::DistributedTriangulation)
dmodel = dtrian.model
dmodel = get_background_model(dtrian)
generate_cell_gids(dmodel,dtrian)
end

Expand Down
2 changes: 1 addition & 1 deletion test/AdaptivityCartesianTests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ function main(distribute,ncells,isperiodic)
fine_adaptivity_glue = get_adaptivity_glue(redist_child_1)

# Redistribute by dispatching on the DistributedCartesianDescriptor
pdesc = redist_child_1.metadata
pdesc = redist_child_1.metadata.model_metadata
redist_child_2, redist_glue_child = redistribute(child,pdesc)

# Tests
Expand Down
38 changes: 38 additions & 0 deletions test/ConstantFESpacesTests.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
module ConstantFESpacesTests

using Test
using Gridap
using GridapDistributed, PartitionedArrays

using Gridap.FESpaces, Gridap.Arrays, Gridap.Algebra

function main(distribute,np)
@assert prod(np) == 4
ranks = distribute(LinearIndices((prod(np),)))

model = CartesianDiscreteModel(ranks,np,(0,1,0,1),(10,10))

Ω = Triangulation(model)
dΩ = Measure(Ω,2)

reffe = ReferenceFE(lagrangian, Float64, 1)
U = FESpace(model,reffe)
V = ConstantFESpace(model)
X = MultiFieldFESpace([U,V])

gids = get_free_dof_ids(V)
@test length(gids) == 1

a((u,λ),(v,μ)) = ∫(u*v + λ*v + μ*u)dΩ
A = assemble_matrix(a,X,X)

V2 = ConstantFESpace(model;constraint_type=:local)
X2 = MultiFieldFESpace([U,V2])

gids = get_free_dof_ids(V2)
@test length(gids) == 4

A2 = assemble_matrix(a,X2,X2)
end

end
11 changes: 8 additions & 3 deletions test/GeometryTests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,19 @@ function main(distribute,parts)
add_tag!(labels,"fluid",[fluid])
cell_to_entity
end
cell_gids=get_cell_gids(model)
vcache=PartitionedArrays.p_vector_cache(cell_to_entity,partition(cell_gids))
assemble!((a,b)->b, cell_to_entity, map(reverse,vcache) ) |> wait # Make tags consistent
cell_gids = get_cell_gids(model)
consistent!(PVector(cell_to_entity,partition(cell_gids))) |> wait # Make tags consistent

Ωs = Interior(model,tags="solid")
Ωf = Interior(model,tags="fluid")
Γfs = Interface(Ωf,Ωs)

# CompositeTriangulations
Γf = Boundary(Ωf)
Λf = Skeleton(Ωf)
Λs = Skeleton(Ωs)
Γs = Boundary(Ωs)

end

function test_local_part_face_labelings_consistency(lmodel::CartesianDiscreteModel{D},gids,gmodel) where {D}
Expand Down
1 change: 1 addition & 0 deletions test/TestApp/src/TestApp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ module TestApp
include("../../BlockSparseMatrixAssemblersTests.jl")
include("../../VisualizationTests.jl")
include("../../AutodiffTests.jl")
include("../../ConstantFESpacesTests.jl")
end
Loading
Loading