Skip to content

Commit db50471

Browse files
authored
Merge pull request #102 from gridap/unified_fe_constuctor
Unified fe constuctor + zero mean FE Space
2 parents 4922780 + 8b61835 commit db50471

14 files changed

+538
-33
lines changed

src/FESpaces/FEOperators.jl

+14-6
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,11 @@ end
9696

9797
abstract type FESolver end
9898

99-
function solve!(uh::FEFunctionLike,::FESolver,::FEOperator)::Any
99+
function solve!(uh::FEFunctionLike,::FESolver,::FEOperator)::Tuple{FEFunctionLike,Any}
100100
@abstractmethod
101101
end
102102

103-
function solve!(uh::FEFunctionLike,::FESolver,::FEOperator,::Any)
103+
function solve!(uh::FEFunctionLike,::FESolver,::FEOperator,::Any)::FEFunction
104104
@abstractmethod
105105
end
106106

@@ -111,8 +111,8 @@ and returns the solution
111111
function solve(nls::FESolver,op::FEOperator)
112112
U = TrialFESpace(op)
113113
uh = zero(U)
114-
solve!(uh,nls,op)
115-
uh
114+
vh, cache = solve!(uh,nls,op)
115+
vh
116116
end
117117

118118
"""
@@ -245,14 +245,17 @@ function solve!(uh::FEFunctionLike,s::LinearFESolver,o::LinearFEOperator)
245245
ss = symbolic_setup(s.ls,A)
246246
ns = numerical_setup(ss,A)
247247
solve!(x,ns,A,b)
248-
ns
248+
U = TrialFESpace(o)
249+
FEFunction(U,x), ns
249250
end
250251

251252
function solve!(uh::FEFunctionLike,s::LinearFESolver,o::LinearFEOperator,ns::NumericalSetup)
252253
x = free_dofs(uh)
253254
A = o.mat
254255
b = o.vec
255256
solve!(x,ns,A,b)
257+
U = TrialFESpace(o)
258+
FEFunction(U,x)
256259
end
257260

258261
function solve(op::LinearFEOperator)
@@ -347,13 +350,18 @@ end
347350
function solve!(uh::FEFunctionLike,nls::NonLinearFESolver,op::FEOperator)
348351
nlop = NonLinearOpFromFEOp(op)
349352
x = free_dofs(uh)
350-
solve!(x,nls.nls,nlop)
353+
cache = solve!(x,nls.nls,nlop)
354+
U = TrialFESpace(op)
355+
vh = FEFunction(U,x)
356+
vh, cache
351357
end
352358

353359
function solve!(uh::FEFunctionLike,nls::NonLinearFESolver,op::FEOperator,cache::Any)
354360
nlop = NonLinearOpFromFEOp(op)
355361
x = free_dofs(uh)
356362
solve!(x,nls.nls,nlop,cache)
363+
U = TrialFESpace(op)
364+
FEFunction(U,x)
357365
end
358366

359367
end # module FEOperators

src/FESpaces/FESpaceConstructors.jl

+191
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
module FESpaceConstructors
2+
3+
using Gridap
4+
using Gridap.Helpers
5+
import Gridap: FESpace
6+
7+
8+
function FESpace(;kwargs...)
9+
10+
reffe = _get_kwarg(:reffe,kwargs)
11+
@assert isa(reffe,Symbol) "For the moment, reffe can only be a symbol"
12+
13+
14+
model = _get_kwarg(:model,kwargs)
15+
labels = _get_kwarg(:labels,kwargs,nothing)
16+
conformity = _get_kwarg(:conformity,kwargs,true)
17+
18+
diritags = _get_kwarg(:diritags,kwargs,Int[])
19+
dirimasks = _get_kwarg(:dirimasks,kwargs,nothing)
20+
21+
order = _get_kwarg(:order,kwargs)
22+
23+
polytope = _get_polytope(model)
24+
25+
constraint = _get_kwarg(:constraint,kwargs,nothing)
26+
27+
dim = celldim(model)
28+
29+
fespace = nothing
30+
31+
if reffe in [:Lagrangian,:QLagrangian,:PLagrangian]
32+
33+
T = _get_kwarg(:valuetype,kwargs,nothing)
34+
if T == nothing
35+
error("valuetype is a mandatory keyword argument in FESpace constructor for Lagrangian reference FEs")
36+
end
37+
38+
if _is_reffe_lagrangian_compatible_with_polytope(reffe,polytope)
39+
40+
if conformity in [false, :L2]
41+
if labels == nothing
42+
fespace = DLagrangianFESpace(T,model,order,diritags,dirimasks)
43+
else
44+
fespace = DLagrangianFESpace(T,model,labels,order,diritags,dirimasks)
45+
end
46+
47+
elseif conformity in [true, :default, :H1]
48+
if labels == nothing
49+
fespace = CLagrangianFESpace(T,model,order,diritags,dirimasks)
50+
else
51+
fespace = CLagrangianFESpace(T,model,labels,order,diritags,dirimasks)
52+
end
53+
54+
else
55+
56+
s = "Conformity $conformity not implemented for $reffe reference FE on a $(_poly_type(polytope))"
57+
error(s)
58+
59+
end
60+
61+
elseif reffe == :PLagrangian
62+
63+
if conformity in [false, :L2]
64+
65+
_reffe = PDiscRefFE(T,polytope,order)
66+
fespace = DiscFESpace(_reffe,model)
67+
68+
else
69+
70+
s = "Conformity $conformity not possible for $reffe reference FE on a $(_poly_type(polytope))"
71+
error(s)
72+
73+
end
74+
75+
76+
else
77+
error("Reference element $reffe nor implemented on a $(_poly_type(polytope))")
78+
end
79+
80+
elseif reffe == :RaviartThomas
81+
82+
if ! _is_cube(polytope)
83+
error("RaviartThomas reference FEs can only be constructed on top of a ncube. Check your model.")
84+
end
85+
86+
_reffe = RaviartThomasRefFE(polytope,order)
87+
88+
if conformity in [false, :L2]
89+
90+
fespace = DiscFESpace(_reffe,model)
91+
92+
elseif conformity in [true, :default, :HDiv]
93+
94+
if labels == nothing
95+
_labels = FaceLabels(model)
96+
else
97+
_labels = labels
98+
end
99+
100+
grid = Grid(model)
101+
trian = Triangulation(grid)
102+
graph = GridGraph(model)
103+
104+
fespace = ConformingFESpace(_reffe,trian,graph,_labels,diritags)
105+
106+
else
107+
108+
s = "Conformity $conformity not possible for a $reffe reference FE"
109+
error(s)
110+
111+
end
112+
113+
114+
else
115+
error("Reference element $reffe not implemented")
116+
end
117+
118+
@assert fespace != nothing
119+
120+
if constraint == nothing
121+
return fespace
122+
123+
elseif constraint == :zeromean
124+
return ZeroMeanFESpace(fespace,order)
125+
126+
else
127+
error("Unknown constraint value $constraint")
128+
129+
end
130+
131+
end
132+
133+
function _get_kwarg(kwarg,kwargs)
134+
135+
try
136+
return kwargs[kwarg]
137+
catch
138+
s = "The key-word argument $(kwarg) is mandatory in the FESpace constructor"
139+
error(s)
140+
end
141+
142+
end
143+
144+
function _get_kwarg(kwarg,kwargs,value)
145+
146+
try
147+
return kwargs[kwarg]
148+
catch
149+
return value
150+
end
151+
152+
end
153+
154+
function _get_polytope(model)
155+
156+
polys = CellPolytopes(Grid(model))
157+
158+
@notimplementedif ! isa(polys,ConstantCellValue)
159+
160+
polys.value
161+
162+
end
163+
164+
function _is_reffe_lagrangian_compatible_with_polytope(reffe,polytope)
165+
v = (reffe == :Lagrangian)
166+
v = v || (reffe == :QLagrangian && _is_cube(polytope))
167+
v = v || (reffe == :PLagrangian && _is_simplex(polytope))
168+
v
169+
end
170+
171+
_is_cube(p) = all(p.extrusion.array .== HEX_AXIS)
172+
173+
_is_simplex(p) = all(p.extrusion.array .== TET_AXIS)
174+
175+
function _poly_type(p)
176+
177+
if _is_cube(p)
178+
t = :ncube
179+
elseif _is_simplex(p)
180+
t = :simplex
181+
else
182+
@notimplemented
183+
end
184+
185+
return t
186+
187+
end
188+
189+
190+
191+
end # module

0 commit comments

Comments
 (0)