diff --git a/.gitignore b/.gitignore index 6527b61c..079af296 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ /docs/site/ /tmp/ *.vtu +*.pvtu diff --git a/NEWS.md b/NEWS.md index b7bbbac6..c6900506 100644 --- a/NEWS.md +++ b/NEWS.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Support for periodic boundary conditions for `CartesianDiscreteModel`. Since PR [#79](https://github.com/gridap/GridapDistributed.jl/pull/79) - Skeleton documentation and some content. Since PR [#77](https://github.com/gridap/GridapDistributed.jl/pull/77) + - Added `interpolate_everywhere` and `interpolate_dirichlet` functions. Since PR [#74](https://github.com/gridap/GridapDistributed.jl/pull/74) ### Fixed - Visualization of functions and numbers. Since PR [#78](https://github.com/gridap/GridapDistributed.jl/pull/78) diff --git a/src/FESpaces.jl b/src/FESpaces.jl index c5477a3b..ec165f59 100644 --- a/src/FESpaces.jl +++ b/src/FESpaces.jl @@ -277,18 +277,45 @@ function FESpaces.get_free_dof_ids(fs::DistributedSingleFieldFESpace) fs.gids end +function FESpaces.get_dirichlet_dof_values(U::DistributedSingleFieldFESpace) + map_parts(get_dirichlet_dof_values,U.spaces) +end + +function FESpaces.FEFunction( + f::DistributedSingleFieldFESpace,free_values::AbstractVector,isconsistent=false) + _EvaluationFunction(FEFunction,f,free_values,isconsistent) +end + function FESpaces.FEFunction( + f::DistributedSingleFieldFESpace,free_values::AbstractVector, + dirichlet_values::AbstractPData{<:AbstractVector},isconsistent=false) + _EvaluationFunction(FEFunction,f,free_values,dirichlet_values,isconsistent) +end + +function FESpaces.EvaluationFunction( + f::DistributedSingleFieldFESpace,free_values::AbstractVector,isconsistent=false) + _EvaluationFunction(EvaluationFunction,f,free_values,isconsistent) +end + +function FESpaces.EvaluationFunction( + f::DistributedSingleFieldFESpace,free_values::AbstractVector, + dirichlet_values::AbstractPData{<:AbstractVector},isconsistent=false) + _EvaluationFunction(EvaluationFunction,f,free_values,dirichlet_values,isconsistent) +end + +function _EvaluationFunction(func, f::DistributedSingleFieldFESpace,free_values::AbstractVector,isconsistent=false) local_vals = consistent_local_views(free_values,f.gids,isconsistent) - fields = map_parts(FEFunction,f.spaces,local_vals) + fields = map_parts(func,f.spaces,local_vals) metadata = DistributedFEFunctionData(free_values) DistributedCellField(fields,metadata) end -function FESpaces.EvaluationFunction( - f::DistributedSingleFieldFESpace,free_values::AbstractVector,isconsistent=false) +function _EvaluationFunction(func, + f::DistributedSingleFieldFESpace,free_values::AbstractVector, + dirichlet_values::AbstractPData{<:AbstractVector},isconsistent=false) local_vals = consistent_local_views(free_values,f.gids,isconsistent) - fields = map_parts(EvaluationFunction,f.spaces,local_vals) + fields = map_parts(func,f.spaces,local_vals,dirichlet_values) metadata = DistributedFEFunctionData(free_values) DistributedCellField(fields,metadata) end @@ -322,6 +349,20 @@ function FESpaces.TrialFESpace(fun,f::DistributedSingleFieldFESpace) DistributedSingleFieldFESpace(spaces,f.gids,f.vector_type) end +function FESpaces.TrialFESpace!(f::DistributedSingleFieldFESpace,fun) + spaces = map_parts(f.spaces) do s + TrialFESpace!(s,fun) + end + DistributedSingleFieldFESpace(spaces,f.gids,f.vector_type) +end + +function FESpaces.HomogeneousTrialFESpace(f::DistributedSingleFieldFESpace) + spaces = map_parts(f.spaces) do s + HomogeneousTrialFESpace(s) + end + DistributedSingleFieldFESpace(spaces,f.gids,f.vector_type) +end + function generate_gids( model::DistributedDiscreteModel, spaces::AbstractPData{<:SingleFieldFESpace}) @@ -343,6 +384,56 @@ function FESpaces.interpolate!( FEFunction(f,free_values) end +function FESpaces.interpolate!( + u::DistributedCellField,free_values::AbstractVector,f::DistributedSingleFieldFESpace) + map_parts(local_views(u),f.spaces,local_views(free_values)) do ui,V,vec + interpolate!(ui,vec,V) + end + FEFunction(f,free_values) +end + +function FESpaces.interpolate_dirichlet(u, f::DistributedSingleFieldFESpace) + free_values = zero_free_values(f) + dirichlet_values = get_dirichlet_dof_values(f) + interpolate_dirichlet!(u,free_values,dirichlet_values,f) +end + +function FESpaces.interpolate_dirichlet!( + u, free_values::AbstractVector, + dirichlet_values::AbstractPData{<:AbstractVector}, + f::DistributedSingleFieldFESpace) + map_parts(f.spaces,local_views(free_values),dirichlet_values) do V,fvec,dvec + interpolate_dirichlet!(u,fvec,dvec,V) + end + FEFunction(f,free_values,dirichlet_values) +end + +function FESpaces.interpolate_everywhere(u, f::DistributedSingleFieldFESpace) + free_values = zero_free_values(f) + dirichlet_values = get_dirichlet_dof_values(f) + interpolate_everywhere!(u,free_values,dirichlet_values,f) +end + +function FESpaces.interpolate_everywhere!( + u, free_values::AbstractVector, + dirichlet_values::AbstractPData{<:AbstractVector}, + f::DistributedSingleFieldFESpace) + map_parts(f.spaces,local_views(free_values),dirichlet_values) do V,fvec,dvec + interpolate_everywhere!(u,fvec,dvec,V) + end + FEFunction(f,free_values,dirichlet_values) +end + +function FESpaces.interpolate_everywhere!( + u::DistributedCellField, free_values::AbstractVector, + dirichlet_values::AbstractPData{<:AbstractVector}, + f::DistributedSingleFieldFESpace) + map_parts(local_views(u),f.spaces,local_views(free_values),dirichlet_values) do ui,V,fvec,dvec + interpolate_everywhere!(ui,fvec,dvec,V) + end + FEFunction(f,free_values,dirichlet_values) +end + # Factories function FESpaces.FESpace(model::DistributedDiscreteModel,reffe;kwargs...) diff --git a/src/MultiField.jl b/src/MultiField.jl index 212b2e2e..afc0c84b 100644 --- a/src/MultiField.jl +++ b/src/MultiField.jl @@ -24,6 +24,9 @@ MultiField.num_fields(m::DistributedMultiFieldFEFunction) = length(m.field_fe_fu Base.iterate(m::DistributedMultiFieldFEFunction) = iterate(m.field_fe_fun) Base.iterate(m::DistributedMultiFieldFEFunction,state) = iterate(m.field_fe_fun,state) Base.getindex(m::DistributedMultiFieldFEFunction,field_id::Integer) = m.field_fe_fun[field_id] + +local_views(a::Vector{<:DistributedCellField}) = [ai.fields for ai in a] + """ """ struct DistributedMultiFieldFESpace{A,B,C,D} <: DistributedFESpace @@ -118,6 +121,63 @@ function FESpaces.interpolate!(objects,free_values::AbstractVector,fe::Distribut end DistributedMultiFieldFEFunction(field_fe_fun,part_fe_fun,free_values) end + +function FESpaces.interpolate_everywhere(objects,fe::DistributedMultiFieldFESpace) + free_values = zero_free_values(fe) + local_vals = consistent_local_views(free_values,fe.gids,true) + part_fe_fun = map_parts(local_vals,local_views(fe)) do x,f + interpolate!(objects,x,f) + end + field_fe_fun = DistributedSingleFieldFEFunction[] + for i in 1:num_fields(fe) + free_values_i = restrict_to_field(fe,free_values,i) + fe_space_i = fe.field_fe_space[i] + dirichlet_values_i = zero_dirichlet_values(fe_space_i) + fe_fun_i = interpolate_everywhere!(objects[i], free_values_i,dirichlet_values_i,fe_space_i) + push!(field_fe_fun,fe_fun_i) + end + DistributedMultiFieldFEFunction(field_fe_fun,part_fe_fun,free_values) +end + +function FESpaces.interpolate_everywhere!( + objects,free_values::AbstractVector, + dirichlet_values::Vector{AbstractPData{<:AbstractVector}}, + fe::DistributedMultiFieldFESpace) + local_vals = consistent_local_views(free_values,fe.gids,true) + part_fe_fun = map_parts(local_vals,local_views(fe)) do x,f + interpolate!(objects,x,f) + end + field_fe_fun = DistributedSingleFieldFEFunction[] + for i in 1:num_fields(fe) + free_values_i = restrict_to_field(fe,free_values,i) + dirichlet_values_i = dirichlet_values[i] + fe_space_i = fe.field_fe_space[i] + fe_fun_i = interpolate_everywhere!(objects[i], free_values_i,dirichlet_values_i,fe_space_i) + push!(field_fe_fun,fe_fun_i) + end + DistributedMultiFieldFEFunction(field_fe_fun,part_fe_fun,free_values) +end + +function FESpaces.interpolate_everywhere( + objects::Vector{<:DistributedCellField},fe::DistributedMultiFieldFESpace) + local_objects = local_views(objects) + local_spaces = local_views(fe) + part_fe_fun = map_parts(local_spaces,local_objects...) do f,o... + interpolate_everywhere(o,f) + end + free_values = zero_free_values(fe) + field_fe_fun = DistributedSingleFieldFEFunction[] + for i in 1:num_fields(fe) + free_values_i = restrict_to_field(fe,free_values,i) + fe_space_i = fe.field_fe_space[i] + dirichlet_values_i = get_dirichlet_dof_values(fe_space_i) + fe_fun_i = interpolate_everywhere!(objects[i], free_values_i,dirichlet_values_i,fe_space_i) + push!(field_fe_fun,fe_fun_i) + end + DistributedMultiFieldFEFunction(field_fe_fun,part_fe_fun,free_values) +end + + """ """ struct DistributedMultiFieldFEBasis{A,B} <: GridapType diff --git a/test/FESpacesTests.jl b/test/FESpacesTests.jl index cb5f96b0..5bfe48be 100644 --- a/test/FESpacesTests.jl +++ b/test/FESpacesTests.jl @@ -34,9 +34,26 @@ function main(parts,das) uh = interpolate(u,U) eh = u - uh + uh_dir = interpolate_dirichlet(u,U) + free_values = zero_free_values(U) + dirichlet_values = get_dirichlet_dof_values(U) + uh_dir2 = interpolate_dirichlet!(u,free_values,dirichlet_values,U) + + uh_everywhere = interpolate_everywhere(u,U) + uh_everywhere_ = interpolate_everywhere!(u,free_values,dirichlet_values,U) + eh2 = u - uh_everywhere + + uh_everywhere2 = interpolate_everywhere(uh_everywhere,U) + uh_everywhere2_ = interpolate_everywhere!(uh_everywhere,free_values,dirichlet_values,U) + eh3 = u - uh_everywhere2 + dΩ = Measure(Ω,3) cont = ∫( abs2(eh) )dΩ + cont2 = ∫( abs2(eh2) )dΩ + cont3 = ∫( abs2(eh3) )dΩ @test sqrt(sum(cont)) < 1.0e-9 + @test sqrt(sum(cont2)) < 1.0e-9 + @test sqrt(sum(cont3)) < 1.0e-9 # Assembly Ωass = Triangulation(das,model)