Skip to content

Commit bae237e

Browse files
committed
Efficient interpolation of constant functions in FE spaces
1 parent e9dfac4 commit bae237e

7 files changed

Lines changed: 135 additions & 8 deletions

File tree

src/FESpaces/CLagrangianFESpaces.jl

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,14 @@ apply_constraints_cols(
125125
celldofids(fesp::CLagrangianFESpace) = fesp.cell_to_dofs
126126

127127
function interpolate_values(fesp::CLagrangianFESpace,fun::Function)
128+
_interpolate_values(fesp,fun)
129+
end
130+
131+
function interpolate_values(fesp::CLagrangianFESpace{D,Z,T},val::T) where {D,Z,T}
132+
_interpolate_values(fesp,val)
133+
end
134+
135+
function _interpolate_values(fesp,fun)
128136
zh = zero(fesp)
129137
fdof_to_val = free_dofs(zh)
130138
ddof_to_val = diri_dofs(zh)
@@ -133,6 +141,14 @@ function interpolate_values(fesp::CLagrangianFESpace,fun::Function)
133141
end
134142

135143
function interpolate_diri_values(fesp::CLagrangianFESpace, funs::Vector{<:Function})
144+
_interpolate_diri_values(fesp, funs)
145+
end
146+
147+
function interpolate_diri_values(fesp::CLagrangianFESpace{D,Z,T},vals::Vector{T}) where {D,Z,T}
148+
_interpolate_diri_values(fesp, vals)
149+
end
150+
151+
function _interpolate_diri_values(fesp, funs)
136152

137153
T = value_type(fesp)
138154
E = eltype(T)
@@ -373,7 +389,7 @@ end
373389
function _fill_interpolated_vals!(fdof_to_val,ddof_to_val,fesp,fun)
374390

375391
x = points(fesp.grid)
376-
fx = fun.(x)
392+
fx = _eval_bc(fun,x)
377393
T = value_type(fesp)
378394
@assert eltype(fx) == T
379395
z = zero(T)
@@ -388,6 +404,10 @@ function _fill_interpolated_vals!(fdof_to_val,ddof_to_val,fesp,fun)
388404

389405
end
390406

407+
_eval_bc(fun::Function,x) = fun.(x)
408+
409+
_eval_bc(val,x) = fill(val,length(x))
410+
391411
function _fill_interpolated_vals_kernel!(
392412
fdof_to_val,
393413
ddof_to_val,
@@ -432,7 +452,7 @@ function _fill_diri_values!(
432452
label = node_to_label[node]
433453
if label in tag_to_labels[diritag]
434454
x = node_to_coords[node]
435-
fx = fun(x)
455+
fx = _eval(fun,x)
436456
comp_to_dof = node_and_comp_to_dof[node]
437457
for comp in eachindex(fx)
438458
mask = dirimask[comp]
@@ -449,6 +469,10 @@ function _fill_diri_values!(
449469

450470
end
451471

472+
@inline _eval(fun::Function,x) = fun(x)
473+
474+
@inline _eval(val,x) = val
475+
452476
function _same_order(order,co)
453477
@notimplemented
454478
end

src/FESpaces/ConformingFESpaces.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,19 @@ function interpolate_values(this::ConformingFESpace,f::Function)
111111
_interpolate_values(this,f)
112112
end
113113

114+
function interpolate_values(this::ConformingFESpace{D,Z,T},val::T) where {D,Z,T}
115+
fun(x) = val
116+
interpolate_values(this,fun)
117+
end
118+
114119
function interpolate_diri_values(this::ConformingFESpace, funs::Vector{<:Function})
115120
_interpolate_diri_values(this,funs)
116121
end
117122

123+
function interpolate_diri_values(this::ConformingFESpace{D,Z,T}, vals::Vector{T}) where {D,Z,T}
124+
_interpolate_diri_values(this,vals)
125+
end
126+
118127
function CellField(
119128
fespace::ConformingFESpace{D,Z,T},
120129
free_dofs::AbstractVector{E},

src/FESpaces/ConstrainedFESpaces.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,19 @@ function interpolate_values(this::ConstrainedFESpace,fun::Function)
8585
(freevals[this.is_free], dirivals)
8686
end
8787

88+
function interpolate_values(this::ConstrainedFESpace{D,Z,T},val::T) where {D,Z,T}
89+
freevals, dirivals = interpolate_values(this.fespace,val)
90+
(freevals[this.is_free], dirivals)
91+
end
92+
8893
function interpolate_diri_values(this::ConstrainedFESpace, funs::Vector{<:Function})
8994
interpolate_diri_values(this.fespace,funs)
9095
end
9196

97+
function interpolate_diri_values(this::ConstrainedFESpace{D,Z,T}, vals::Vector{T}) where {D,Z,T}
98+
interpolate_diri_values(this.fespace,vals)
99+
end
100+
92101
function CellField(
93102
this::ConstrainedFESpace{D,Z,T},
94103
free_dofs::AbstractVector{E},

src/FESpaces/DLagrangianFESpaces.jl

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ using Gridap.CLagrangianFESpaces: _S
99
using Gridap.CLagrangianFESpaces: _compute_comp_to_dof
1010
using Gridap.CLagrangianFESpaces: _setup_grid
1111
using Gridap.CLagrangianFESpaces: _setup_masks
12+
using Gridap.CLagrangianFESpaces: _eval
13+
using Gridap.CLagrangianFESpaces: _eval_bc
1214
using Gridap.ConformingFESpaces: _CellField
1315
using Gridap.BoundaryGrids: _setup_tags
1416

@@ -132,6 +134,14 @@ function CellField(
132134
end
133135

134136
function interpolate_values(fesp::DLagrangianFESpace,fun::Function)
137+
_interpolate_values(fesp,fun)
138+
end
139+
140+
function interpolate_values(fesp::DLagrangianFESpace{D,Z,T},val::T) where {D,Z,T}
141+
_interpolate_values(fesp,val)
142+
end
143+
144+
function _interpolate_values(fesp::DLagrangianFESpace,fun)
135145

136146
zh = zero(fesp)
137147
fdof_to_val = free_dofs(zh)
@@ -140,7 +150,7 @@ function interpolate_values(fesp::DLagrangianFESpace,fun::Function)
140150
lnode_and_comp_to_ldof = fesp.reffe.dofbasis.node_and_comp_to_dof
141151
cell_to_dofs = fesp.cell_to_dofs
142152
cell_to_nodes = cells(fesp.grid)
143-
node_comp_to_val = fun.(node_to_coords)
153+
node_comp_to_val = _eval_bc(fun,node_to_coords)
144154

145155
_fill_interpolated_vals!(
146156
fdof_to_val,
@@ -154,6 +164,14 @@ function interpolate_values(fesp::DLagrangianFESpace,fun::Function)
154164
end
155165

156166
function interpolate_diri_values(fesp::DLagrangianFESpace, funs::Vector{<:Function})
167+
_interpolate_diri_values(fesp, funs)
168+
end
169+
170+
function interpolate_diri_values(fesp::DLagrangianFESpace{D,Z,T}, vals::Vector{T}) where {D,Z,T}
171+
_interpolate_diri_values(fesp, vals)
172+
end
173+
174+
function _interpolate_diri_values(fesp::DLagrangianFESpace, funs)
157175

158176
T = value_type(fesp)
159177
E = eltype(T)
@@ -216,7 +234,7 @@ function _fill_diri_values!(
216234
if label in tag_to_labels[diritag]
217235

218236
coords = node_to_coords[node]
219-
comp_to_val = fun(coords)
237+
comp_to_val = _eval(fun,coords)
220238

221239
for comp in eachindex(dirimask)
222240
mask = dirimask[comp]

src/FESpaces/DiscFESpaces.jl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,20 @@ function interpolate_values(this::DiscFESpace,fun::Function)
7171
_setup_interpolate_values(this, fun)
7272
end
7373

74+
function interpolate_values(this::DiscFESpace{D,Z,T},val::T) where {D,Z,T}
75+
fun(x) = val
76+
_setup_interpolate_values(this, fun)
77+
end
78+
7479
function interpolate_diri_values(this::DiscFESpace, funs::Vector{<:Function})
80+
_interpolate_diri_values(this::DiscFESpace, funs)
81+
end
82+
83+
function interpolate_diri_values(this::DiscFESpace{D,Z,T}, vals::Vector{T}) where {D,Z,T}
84+
_interpolate_diri_values(this::DiscFESpace, vals)
85+
end
86+
87+
function _interpolate_diri_values(this::DiscFESpace, funs)
7588
@assert length(funs) == 0
7689
T = value_type(this)
7790
E = dof_type(T)

src/FESpaces/FESpaces.jl

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ function interpolate_values(::FESpace,::Function)::Tuple{Vector{E},Vector{E}} wh
7171
@abstractmethod
7272
end
7373

74+
function interpolate_values(::FESpace{D,Z,T},::T) where {D,Z,T}
75+
@abstractmethod
76+
end
77+
7478
"""
7579
Given a FESpace and its array of labels that represent the Dirichlet boundary
7680
in the geometrical model and an array of functions for every Dirichlet
@@ -81,11 +85,20 @@ function interpolate_diri_values(::FESpace, funs::Vector{<:Function})::Vector{E}
8185
@abstractmethod
8286
end
8387

88+
function interpolate_diri_values( ::FESpace{D,Z,T}, ::Vector{T}) where {D,Z,T}
89+
@abstractmethod
90+
end
91+
8492
function interpolate_diri_values(this::FESpace, fun::Function)
8593
tags = diri_tags(this)
8694
interpolate_diri_values(this,fill(fun,length(tags)))
8795
end
8896

97+
function interpolate_diri_values(this::FESpace{D,Z,T}, val::T) where {D,Z,T}
98+
tags = diri_tags(this)
99+
interpolate_diri_values(this,fill(val,length(tags)))
100+
end
101+
89102
"""
90103
Returns the CellField that represents the FE function thorough its free and
91104
dirichlet values. E = eltype(T)
@@ -111,27 +124,40 @@ function TestFESpace(this::FESpace{D,Z,T}) where {D,Z,T}
111124
return FESpaceWithDirichletData(this, dv)
112125
end
113126

114-
function TrialFESpace( this::FESpace, funs::Vector{<:Function}=Function[]) where {D}
127+
function TrialFESpace( this::FESpace, funs::Vector{<:Function}=Function[])
128+
_TrialFESpace(this,funs)
129+
end
130+
131+
function TrialFESpace( this::FESpace{D,Z,T}, vals::Vector{T}) where {D,Z,T}
132+
_TrialFESpace(this,vals)
133+
end
134+
135+
function _TrialFESpace( this, funs)
115136
tags = diri_tags(this)
116137
@assert length(tags) == length(funs)
117138
dv = interpolate_diri_values(this,funs)
118139
return FESpaceWithDirichletData(this, dv)
119140
end
120141

121-
function TrialFESpace( this::FESpace, fun::Function) where {D}
142+
function TrialFESpace( this::FESpace, fun::Function)
122143
dv = interpolate_diri_values(this,fun)
123144
return FESpaceWithDirichletData(this, dv)
124145
end
125146

147+
function TrialFESpace( this::FESpace{D,Z,T}, val::T) where {D,Z,T}
148+
dv = interpolate_diri_values(this,val)
149+
return FESpaceWithDirichletData(this, dv)
150+
end
151+
126152
# Testers
127153

128154
function test_fe_space(
129-
fespace::FESpace{D,Z},
155+
fespace::FESpace{D,Z,T},
130156
nfree::Integer,
131157
ndiri::Integer,
132158
cellmat::CellMatrix,
133159
cellvec::CellVector,
134-
ufun::Function) where {D,Z}
160+
ufun::Function) where {D,Z,T}
135161

136162
@test num_free_dofs(fespace) == nfree
137163
@test num_diri_dofs(fespace) == ndiri
@@ -160,6 +186,13 @@ function test_fe_space(
160186
@test length(freevals) == nfree
161187
@test length(dirivals) == ndiri
162188

189+
z = zero(T)
190+
freevals, dirivals = interpolate_values(fespace,z)
191+
@test isa(freevals,AbstractVector)
192+
@test isa(dirivals,AbstractVector)
193+
@test length(freevals) == nfree
194+
@test length(dirivals) == ndiri
195+
163196
dirivals = interpolate_diri_values(fespace,ufun)
164197
@test isa(dirivals,AbstractVector)
165198
@test length(dirivals) == ndiri
@@ -170,6 +203,10 @@ function test_fe_space(
170203
trian = Triangulation(fespace)
171204
@test isa(trian,Triangulation{Z,D})
172205

206+
dirivals = interpolate_diri_values(fespace,z)
207+
@test isa(dirivals,AbstractVector)
208+
@test length(dirivals) == ndiri
209+
173210
end
174211

175212
# Helpers
@@ -216,6 +253,11 @@ function interpolate_values(f::FESpaceWithDirichletData,fun::Function)
216253
free_vals, f.diri_dofs
217254
end
218255

256+
function interpolate_values(f::FESpaceWithDirichletData{D,Z,T},val::T) where {D,Z,T}
257+
free_vals, _ = interpolate_values(f.fespace,val)
258+
free_vals, f.diri_dofs
259+
end
260+
219261
function CellField(
220262
f::FESpaceWithDirichletData{D,Z,T},free_dofs::AbstractVector{E},diri_dofs::AbstractVector{E})where {D,Z,T,E}
221263
CellField(f.fespace,free_dofs,f.diri_dofs)
@@ -231,4 +273,8 @@ function interpolate_diri_values(f::FESpaceWithDirichletData, funs::Vector{<:Fun
231273
f.diri_dofs
232274
end
233275

276+
function interpolate_diri_values(f::FESpaceWithDirichletData{D,Z,T}, vals::Vector{T}) where {D,Z,T}
277+
f.diri_dofs
278+
end
279+
234280
end # module FESpaces

test/FESpacesTests/FESpacesTests.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,13 @@ test_fe_space(V,5,4,mmat,bvec,fun)
2929
U = TrialFESpace(fespace,fun)
3030
test_fe_space(U,5,4,mmat,bvec,fun)
3131

32+
fun(x) = x[1] + x[2]
33+
z = 2.0
34+
U = TrialFESpace(fespace,z)
35+
test_fe_space(U,5,4,mmat,bvec,fun)
36+
37+
U = TrialFESpace(fespace,[z,z,z,z])
38+
test_fe_space(U,5,4,mmat,bvec,fun)
39+
3240
end # module
3341

0 commit comments

Comments
 (0)