Skip to content

Commit

Permalink
Merge pull request #396 from gridap/fe_space_with_dof_potentially_rem…
Browse files Browse the repository at this point in the history
…oved

Generalization of FESpaceWithLastDofRemoved
  • Loading branch information
fverdugo authored Sep 11, 2020
2 parents ce0e1f1 + df737b8 commit fbea57c
Show file tree
Hide file tree
Showing 13 changed files with 334 additions and 155 deletions.
5 changes: 5 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ 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).

## Unreleased

### Added
- Added VectorWithEntryInserted and VectorWithEntryRemoved. Since PR [#401](https://github.com/gridap/Gridap.jl/pull/401/)

## [0.14.0] - 2020-08-27

### Removed
Expand Down
8 changes: 8 additions & 0 deletions src/Arrays/Arrays.jl
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ export autodiff_array_gradient
export autodiff_array_jacobian
export autodiff_array_hessian

export VectorWithEntryRemoved
export VectorWithEntryInserted

import Base: size
import Base: getindex, setindex!
import Base: similar
Expand Down Expand Up @@ -158,4 +161,9 @@ include("VectorsOfBlockArrayCoo.jl")

include("Autodiff.jl")

include("VectorsWithEntryRemoved.jl")

include("VectorsWithEntryInserted.jl")


end # module
38 changes: 38 additions & 0 deletions src/Arrays/VectorsWithEntryInserted.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
mutable struct VectorWithEntryInserted{T,A} <: AbstractVector{T}
a::A
index::Int
value::T
function VectorWithEntryInserted(a::AbstractVector,index::Integer,value)
A = typeof(a)
T = eltype(a)
@assert 1 <= index <= length(a)+1
new{T,A}(a,index,value)
end
end

Base.IndexStyle(::Type{<:VectorWithEntryInserted}) = IndexLinear()

function Base.getindex(v::VectorWithEntryInserted,i::Integer)
i < v.index ? v.a[i] :
(i==v.index ? v.value : v.a[i-1])
end

Base.size(v::VectorWithEntryInserted) = (length(v.a)+1,)

function array_cache(v::VectorWithEntryInserted)
array_cache(v.a)
end

function getindex!(cache,v::VectorWithEntryInserted,i::Integer)
i < v.index ? getindex!(cache,v.a,i) :
(i==v.index ? v.value : getindex!(cache,v.a,i-1))
end

function Base.sum(a::VectorWithEntryInserted)
sum(a.a) + a.value
end

function Base.setindex!(a::VectorWithEntryInserted,v,i::Integer)
i < a.index ? (a.a[i] = v) :
(i==a.index ? a.value = v : a.a[i-1]=v)
end
34 changes: 34 additions & 0 deletions src/Arrays/VectorsWithEntryRemoved.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
struct VectorWithEntryRemoved{T,A} <: AbstractVector{T}
a::A
index::Int
function VectorWithEntryRemoved(a::AbstractVector,index::Integer)
A = typeof(a)
T = eltype(a)
@assert 1 <= index <= length(a)
new{T,A}(a,index)
end
end

Base.IndexStyle(::Type{<:VectorWithEntryRemoved}) = IndexLinear()

function Base.getindex(v::VectorWithEntryRemoved,i::Integer)
i < v.index ? v.a[i] : v.a[i+1]
end

Base.size(v::VectorWithEntryRemoved) = (length(v.a)-1,)

function array_cache(v::VectorWithEntryRemoved)
array_cache(v.a)
end

function getindex!(cache,v::VectorWithEntryRemoved,i::Integer)
i < v.index ? getindex!(cache,v.a,i) : getindex!(cache,v.a,i+1)
end

function Base.sum(a::VectorWithEntryRemoved)
sum(a.a) - a.a[a.index]
end

function Base.setindex!(a::VectorWithEntryRemoved,v,i::Integer)
i < a.index ? (a.a[i] = v) : (a.a[i+1] = v)
end
5 changes: 3 additions & 2 deletions src/FESpaces/FESpaces.jl
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,8 @@ export collect_cell_jacobian
export collect_cell_jacobian_and_residual
export collect_cell_residual

export FESpaceWithLastDofRemoved
export FESpaceWithConstantFixed

export ZeroMeanFESpace
export CLagrangianFESpace
export ConformingFESpace
Expand Down Expand Up @@ -252,7 +253,7 @@ include("FEOperatorsFromTerms.jl")

include("FESolvers.jl")

include("FESpacesWithLastDofRemoved.jl")
include("FESpacesWithConstantFixed.jl")

include("ZeroMeanFESpaces.jl")

Expand Down
180 changes: 180 additions & 0 deletions src/FESpaces/FESpacesWithConstantFixed.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
abstract type ConstantApproach end;
struct FixConstant <: ConstantApproach end;
struct DoNotFixConstant <: ConstantApproach end;

#"""
# struct FESpaceWithConstantFixed{CS,<:ConstantApproach} <: SingleFieldFESpace
# space::SingleFieldFESpace
# constraint_style::Val{CS}
# dof_to_fix::Int
# end
#"""
struct FESpaceWithConstantFixed{CS,CA<:ConstantApproach} <: SingleFieldFESpace
space::SingleFieldFESpace
constraint_style::Val{CS}
dof_to_fix::Int
@doc """
FESpaceWithConstantFixed(space::SingleFieldFESpace, fix_constant::Bool,
dof_to_fix::Int=num_free_dofs(space))
"""
function FESpaceWithConstantFixed(space::SingleFieldFESpace,
fix_constant::Bool,
dof_to_fix::Int=num_free_dofs(space))
cs = constraint_style(space)
CS = get_val_parameter(cs)
if (fix_constant && num_dirichlet_dofs(space)==0)
new{CS,FixConstant}(space,cs,dof_to_fix)
else
new{CS,DoNotFixConstant}(space,cs,dof_to_fix)
end
end
end

# Genuine functions
function num_free_dofs(f::FESpaceWithConstantFixed{CS,FixConstant}) where {CS}
num_free_dofs(f.space)-1
end

function num_free_dofs(f::FESpaceWithConstantFixed{CS,DoNotFixConstant}) where {CS}
num_free_dofs(f.space)
end

function zero_free_values(f::FESpaceWithConstantFixed)
zeros(num_free_dofs(f))
end

function get_cell_dofs(f::FESpaceWithConstantFixed{CS,FixConstant}) where {CS}
cell_dofs = get_cell_dofs(f.space)
CellDofsWithDofFixed(cell_dofs,f.dof_to_fix)
end

function get_cell_dofs(f::FESpaceWithConstantFixed{CS,DoNotFixConstant}) where {CS}
get_cell_dofs(f.space)
end


num_dirichlet_dofs(f::FESpaceWithConstantFixed{CS,FixConstant}) where {CS} = 1

num_dirichlet_dofs(f::FESpaceWithConstantFixed{CS,DoNotFixConstant}) where {CS} = 0

function zero_dirichlet_values(f::FESpaceWithConstantFixed)
T = Float64 # TODO
zeros(T,num_dirichlet_dofs(f))
end


num_dirichlet_tags(f::FESpaceWithConstantFixed{CS,FixConstant}) where {CS} = 1

num_dirichlet_tags(f::FESpaceWithConstantFixed{CS,DoNotFixConstant}) where {CS} = 0

get_dirichlet_dof_tag(f::FESpaceWithConstantFixed{CS,FixConstant}) where {CS} = Int8[1,]

get_dirichlet_dof_tag(f::FESpaceWithConstantFixed{CS,DoNotFixConstant}) where {CS} = Int8[]

function scatter_free_and_dirichlet_values(
f::FESpaceWithConstantFixed{CS,FixConstant},fv,dv) where {CS}
@assert length(dv) == 1
_dv = similar(dv,eltype(dv),0)
_fv = VectorWithEntryInserted(fv,f.dof_to_fix,dv[1])
scatter_free_and_dirichlet_values(f.space,_fv,_dv)
end

function scatter_free_and_dirichlet_values(
f::FESpaceWithConstantFixed{CS,DoNotFixConstant},fv,dv) where {CS}
@assert length(dv) == 0
scatter_free_and_dirichlet_values(f.space,fv,dv)
end

function gather_free_and_dirichlet_values(
f::FESpaceWithConstantFixed{CS,FixConstant},cv) where {CS}
_fv, _dv = gather_free_and_dirichlet_values(f.space,cv)
@assert length(_dv) == 0
fv = VectorWithEntryRemoved(_fv,f.dof_to_fix)
dv = _fv[f.dof_to_fix:f.dof_to_fix]
(fv, dv)
end

function gather_free_and_dirichlet_values(
f::FESpaceWithConstantFixed{CS,DoNotFixConstant},cv) where {CS}
gather_free_and_dirichlet_values(f.space,cv)
end

function gather_free_and_dirichlet_values!(
fv,dv,f::FESpaceWithConstantFixed{CS,FixConstant},cv) where {CS}
_fv, _dv = gather_free_and_dirichlet_values(f.space,cv)
@assert length(_dv) == 0
fv .= VectorWithEntryRemoved(_fv,f.dof_to_fix)
dv[1] = _fv[f.dof_to_fix]
(fv, dv)
end

function gather_free_and_dirichlet_values!(
fv,dv,f::FESpaceWithConstantFixed{CS,DoNotFixConstant},cv) where {CS}
gather_free_and_dirichlet_values(f.space,cv)
end

function TrialFESpace(f::FESpaceWithConstantFixed{CS,CA}) where {CS,CA}
U = TrialFESpace(f.space)
FESpaceWithConstantFixed(U,CA==FixConstant,f.dof_to_fix)
end

# Delegated functions

function get_cell_basis(f::FESpaceWithConstantFixed)
get_cell_basis(f.space)
end

function get_cell_dof_basis(f::FESpaceWithConstantFixed)
get_cell_dof_basis(f.space)
end

get_cell_axes(t::FESpaceWithConstantFixed)= get_cell_axes(t.space)

get_cell_axes_with_constraints(t::FESpaceWithConstantFixed)= get_cell_axes_with_constraints(t.space)

CellData.CellField(t::FESpaceWithConstantFixed,cell_vals) = CellField(t.space,cell_vals)

constraint_style(::Type{<:FESpaceWithConstantFixed{CS}}) where CS = Val{CS}()

# Helpers

struct CellDofsWithDofFixed{A<:AbstractArray} <: AbstractVector{Vector{Int}}
cell_dofs::A
dof_to_fix::Int
end

Base.size(a::CellDofsWithDofFixed) = (length(a.cell_dofs),)

Base.IndexStyle(::Type{<:CellDofsWithDofFixed}) = IndexLinear()

function Base.getindex(a::CellDofsWithDofFixed,i::Integer)
cache = array_cache(a)
getindex!(cache,a,i)
end

function array_cache(a::CellDofsWithDofFixed)
@assert eltype(a.cell_dofs) == Vector{Int}
b = testitem(a.cell_dofs)
c = CachedArray(b)
cache = array_cache(a.cell_dofs)
(c, cache)
end

@inline function getindex!(d,a::CellDofsWithDofFixed,i::Integer)
c, cache = d
b = getindex!(cache,a.cell_dofs,i)
setsize!(c,size(b))
r = c.array
for j in 1:length(b)
bj = b[j]
if bj == a.dof_to_fix
rj = -1
elseif bj < a.dof_to_fix
rj = bj
else
rj = bj-1
end
r[j] = rj
end
r
end
Loading

0 comments on commit fbea57c

Please sign in to comment.