Skip to content

Commit

Permalink
Merge pull request #212 from gridap/changing_RT_order_definition
Browse files Browse the repository at this point in the history
Changed the definition of order in Raviart-Thomas and Nedelec reffes
  • Loading branch information
fverdugo authored Mar 17, 2020
2 parents 877ebbe + 8b6d39e commit 4435c9f
Show file tree
Hide file tree
Showing 12 changed files with 146 additions and 32 deletions.
10 changes: 8 additions & 2 deletions src/Polynomials/QCurlGradMonomialBases.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,14 @@ end
Returns a `QCurlGradMonomialBasis` object. `D` is the dimension
of the coordinate space and `T` is the type of the components in the vector-value.
The `order` argument has the following meaning: the divergence of the functions in this basis
is in the Q space of degree `order`.
"""
function QCurlGradMonomialBasis{D}(::Type{T},order::Int) where {D,T}
@assert T<:Real "T needs to be <:Real since represents the type of the components of the vector value"
_t = tfill(order,Val{D-1}())
t = (order+1,_t...)
_order = order+1
_t = tfill(_order,Val{D-1}())
t = (_order+1,_t...)
terms = CartesianIndices(t)
perms = _prepare_perms(D)
QCurlGradMonomialBasis(T,order,terms,perms)
Expand Down Expand Up @@ -53,3 +56,6 @@ get_value_type(::QCurlGradMonomialBasis{D,T}) where {D,T} = T
num_terms(f::QCurlGradMonomialBasis{D,T}) where {D,T}
"""
num_terms(f::QCurlGradMonomialBasis{D,T}) where {D,T} = length(f.qgrad.terms)*D

get_order(f::QCurlGradMonomialBasis{D,T}) where {D,T} = get_order(f.qgrad)

28 changes: 18 additions & 10 deletions src/Polynomials/QGradMonomialBases.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,31 @@ end
Returns a `QGradMonomialBasis` object. `D` is the dimension
of the coordinate space and `T` is the type of the components in the vector-value.
The `order` argument has the following meaning: the curl of the functions in this basis
is in the Q space of degree `order`.
"""
function QGradMonomialBasis{D}(::Type{T},order::Int) where {D,T}
@assert T<:Real "T needs to be <:Real since represents the type of the components of the vector value"
_t = tfill(order+1,Val{D-1}())
t = (order,_t...)
_order = order + 1
_t = tfill(_order+1,Val{D-1}())
t = (_order,_t...)
terms = CartesianIndices(t)
perms = _prepare_perms(D)
QGradMonomialBasis(T,order,terms,perms)
end

"""
num_terms(f::QGradMonomialBasis{D,T}) where {D,T}
"""
num_terms(f::QGradMonomialBasis{D,T}) where {D,T} = length(f.terms)*D

get_order(f::QGradMonomialBasis) = f.order

function field_cache(f::QGradMonomialBasis{D,T},x) where {D,T}
@assert D == length(eltype(x)) "Incorrect number of point components"
np = length(x)
ndof = _ndofs_qgrad(f)
n = 1 + f.order
n = 1 + f.order+1
V = VectorValue{D,T}
r = CachedArray(zeros(V,(np,ndof)))
v = CachedArray(zeros(V,(ndof,)))
Expand All @@ -48,13 +58,13 @@ function evaluate_field!(cache,f::QGradMonomialBasis{D,T},x) where {D,T}
r, v, c = cache
np = length(x)
ndof = _ndofs_qgrad(f)
n = 1 + f.order
n = 1 + f.order+1
setsize!(r,(np,ndof))
setsize!(v,(ndof,))
setsize!(c,(D,n))
for i in 1:np
@inbounds xi = x[i]
_evaluate_nd_qgrad!(v,xi,f.order,f.terms,f.perms,c)
_evaluate_nd_qgrad!(v,xi,f.order+1,f.terms,f.perms,c)
for j in 1:ndof
@inbounds r[i,j] = v[j]
end
Expand All @@ -66,7 +76,7 @@ function gradient_cache(f::QGradMonomialBasis{D,T},x) where {D,T}
@assert D == length(eltype(x)) "Incorrect number of point components"
np = length(x)
ndof = _ndofs_qgrad(f)
n = 1 + f.order
n = 1 + f.order+1
xi = testitem(x)
V = VectorValue{D,T}
G = gradient_type(V,xi)
Expand All @@ -81,15 +91,15 @@ function evaluate_gradient!(cache,f::QGradMonomialBasis{D,T},x) where {D,T}
r, v, c, g = cache
np = length(x)
ndof = _ndofs_qgrad(f)
n = 1 + f.order
n = 1 + f.order+1
setsize!(r,(np,ndof))
setsize!(v,(ndof,))
setsize!(c,(D,n))
setsize!(g,(D,n))
V = VectorValue{D,T}
for i in 1:np
@inbounds xi = x[i]
_gradient_nd_qgrad!(v,xi,f.order,f.terms,f.perms,c,g,V)
_gradient_nd_qgrad!(v,xi,f.order+1,f.terms,f.perms,c,g,V)
for j in 1:ndof
@inbounds r[i,j] = v[j]
end
Expand All @@ -99,8 +109,6 @@ end

# Helpers

#_ndofs_qgrad(f::QGradMonomialBasis{D}) where D = D*f.order*(f.order+1)^(D-1)

_ndofs_qgrad(f::QGradMonomialBasis{D}) where D = D*(length(f.terms))

function _prepare_perms(D)
Expand Down
15 changes: 9 additions & 6 deletions src/ReferenceFEs/NedelecRefFEs.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
"""
NedelecRefFE(::Type{et},p::Polytope,order::Integer) where et
The `order` argument has the following meaning: the curl of the functions in this basis
is in the Q space of degree `order`.
"""
# @santiagobadia : Project, go to complex numbers
function NedelecRefFE(::Type{et},p::Polytope,order::Integer) where et
Expand Down Expand Up @@ -48,7 +51,7 @@ function _Nedelec_nodes_and_moments(::Type{et}, p::Polytope, order::Integer) whe
nf_nodes[erange] = ecips
nf_moments[erange] = emoments

if ( num_dims(p) == 3 && order > 1)
if ( num_dims(p) == 3 && order > 0)

fcips, fmoments = _Nedelec_face_values(p,et,order)
frange = get_dimrange(p,D-1)
Expand All @@ -57,7 +60,7 @@ function _Nedelec_nodes_and_moments(::Type{et}, p::Polytope, order::Integer) whe

end

if (order > 1)
if (order > 0)

ccips, cmoments = _Nedelec_cell_values(p,et,order)
crange = get_dimrange(p,D)
Expand All @@ -79,7 +82,7 @@ function _Nedelec_edge_values(p,et,order)
egeomap = _ref_face_to_faces_geomap(p,ep)

# Compute integration points at all polynomial edges
degree = order*2
degree = (order+1)*2
equad = Quadrature(ep,degree)
cips = get_coordinates(equad)
wips = get_weights(equad)
Expand All @@ -88,7 +91,7 @@ function _Nedelec_edge_values(p,et,order)
c_eips, ecips, ewips = _nfaces_evaluation_points_weights(p, egeomap, cips, wips)

# Edge moments, i.e., M(Ei)_{ab} = q_RE^a(xgp_REi^b) w_Fi^b t_Ei ⋅ ()
eshfs = MonomialBasis(et,ep,order-1)
eshfs = MonomialBasis(et,ep,order)
emoments = _Nedelec_edge_moments(p, eshfs, c_eips, ecips, ewips)

return ecips, emoments
Expand Down Expand Up @@ -116,7 +119,7 @@ function _Nedelec_face_values(p,et,order)
fgeomap = _ref_face_to_faces_geomap(p,fp)

# Compute integration points at all polynomial edges
degree = order*2
degree = (order+1)*2
fquad = Quadrature(fp,degree)
fips = get_coordinates(fquad)
wips = get_weights(fquad)
Expand Down Expand Up @@ -156,7 +159,7 @@ end
function _Nedelec_cell_values(p,et,order)

# Compute integration points at interior
degree = 2*order
degree = 2*(order+1)
iquad = Quadrature(p,degree)
ccips = get_coordinates(iquad)
cwips = get_weights(iquad)
Expand Down
11 changes: 7 additions & 4 deletions src/ReferenceFEs/RaviartThomasRefFEs.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@

"""
RaviartThomasRefFE(::Type{et},p::Polytope,order::Integer) where et
The `order` argument has the following meaning: the divergence of the functions in this basis
is in the Q space of degree `order`.
"""
function RaviartThomasRefFE(::Type{et},p::Polytope,order::Integer) where et

Expand Down Expand Up @@ -48,7 +51,7 @@ function _RT_nodes_and_moments(::Type{et}, p::Polytope, order::Integer) where et
nf_nodes[frange] = fcips
nf_moments[frange] = fmoments

if (order > 1)
if (order > 0)
ccips, cmoments = _RT_cell_values(p,et,order)
crange = get_dimrange(p,D)
nf_nodes[crange] = ccips
Expand Down Expand Up @@ -115,7 +118,7 @@ function _RT_face_values(p,et,order)
# the one of the points in the polytope after applying the geopmap
# (fcips), and the weights for these nodes (fwips, a constant cell array)
# Nodes (fcips)
degree = order*2
degree = (order+1)*2
fquad = Quadrature(fp,degree)
fips = get_coordinates(fquad)
wips = get_weights(fquad)
Expand All @@ -124,7 +127,7 @@ function _RT_face_values(p,et,order)

# Moments (fmoments)
# The RT prebasis is expressed in terms of shape function
fshfs = MonomialBasis(et,fp,order-1)
fshfs = MonomialBasis(et,fp,order)

# Face moments, i.e., M(Fi)_{ab} = q_RF^a(xgp_RFi^b) w_Fi^b n_Fi ⋅ ()
fmoments = _RT_face_moments(p, fshfs, c_fips, fcips, fwips)
Expand All @@ -142,7 +145,7 @@ end
# It provides for every cell the nodes and the moments arrays
function _RT_cell_values(p,et,order)
# Compute integration points at interior
degree = 2*order
degree = 2*(order+1)
iquad = Quadrature(p,degree)
ccips = get_coordinates(iquad)
cwips = get_weights(iquad)
Expand Down
2 changes: 1 addition & 1 deletion test/FESpacesTests/CurlConformingFESpacesTests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ partition = (3,3,3)
model = CartesianDiscreteModel(domain,partition)
trian = get_triangulation(model)

order = 3
order = 2

u(x) = VectorValue(x[1]*x[1],x[1]*x[1]*x[1],0.0)
# u(x) = x
Expand Down
2 changes: 1 addition & 1 deletion test/FESpacesTests/DivConformingFESpacesTests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ partition = (3,3)
model = CartesianDiscreteModel(domain,partition)
trian = get_triangulation(model)

order = 2
order = 1

u(x) = x

Expand Down
6 changes: 3 additions & 3 deletions test/GridapTests/DarcyTests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ f(x) = u(x) + ∇p(x)

domain = (0,1,0,1)
partition = (4,4)
order = 2
order = 1
model = CartesianDiscreteModel(domain,partition)

V = FESpace(
reffe=:RaviartThomas, order=order, valuetype=VectorValue{2,Float64},
conformity=:Hdiv, model=model, dirichlet_tags=[5,6])

Q = FESpace(
reffe=:QLagrangian, order=order-1, valuetype=Float64,
reffe=:QLagrangian, order=order, valuetype=Float64,
conformity=:L2, model=model)

U = TrialFESpace(V,u)
Expand All @@ -41,7 +41,7 @@ quad = CellQuadrature(trian,degree)

neumanntags = [7,8]
btrian = BoundaryTriangulation(model,neumanntags)
degree = 2*order
degree = 2*(order+1)
bquad = CellQuadrature(btrian,degree)
nb = get_normal_vector(btrian)

Expand Down
19 changes: 17 additions & 2 deletions test/PolynomialsTests/QCurlGradMonomialBasesTests.jl
Original file line number Diff line number Diff line change
@@ -1,14 +1,29 @@
module QCurlGradMonomialBasesTests

using Test
using Gridap.TensorValues
using Gridap.Fields
using Gridap.Polynomials

xi = Point(2,3)
np = 5
x = fill(xi,np)

order = 0
D = 2
T = Float64
V = VectorValue{D,T}
G = gradient_type(V,xi)
b = QCurlGradMonomialBasis{D}(T,order)

@test num_terms(b) == 4
@test get_order(b) == 0

xi = Point(2,3,5)
np = 5
x = fill(xi,np)

order = 1
order = 0
D = 3
T = Float64
V = VectorValue{D,T}
Expand All @@ -35,7 +50,7 @@ xi = Point(2,3)
np = 5
x = fill(xi,np)

order = 2
order = 1
D = 2
T = Float64
V = VectorValue{D,T}
Expand Down
20 changes: 18 additions & 2 deletions test/PolynomialsTests/QGradMonomialBasesTests.jl
Original file line number Diff line number Diff line change
@@ -1,14 +1,30 @@
module QGradMonomialBasesTests

using Test
using Gridap.TensorValues
using Gridap.Fields
using Gridap.Polynomials

xi = Point(2,3)
np = 5
x = fill(xi,np)

order = 0
D = 2
T = Float64
V = VectorValue{D,T}
G = gradient_type(V,xi)
b = QGradMonomialBasis{D}(T,order)

@test num_terms(b) == 4
@test b.order == 0
@test get_order(b) == 0

xi = Point(2,3,5)
np = 5
x = fill(xi,np)

order = 1
order = 0
D = 3
T = Float64
V = VectorValue{D,T}
Expand Down Expand Up @@ -43,7 +59,7 @@ xi = Point(2,3)
np = 5
x = fill(xi,np)

order = 2
order = 1
D = 2
T = Float64
V = VectorValue{D,T}
Expand Down
46 changes: 46 additions & 0 deletions test/ReferenceFEsTests/NedelecRefFEsTests.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
module NedelecRefFEsTest

using Test
using Gridap.Polynomials
using Gridap.Fields
using Gridap.TensorValues
using Gridap.Fields: MockField
using Gridap.ReferenceFEs

p = QUAD
D = num_dims(QUAD)
et = Float64
order = 0

reffe = NedelecRefFE(et,p,order)
test_reference_fe(reffe)
@test num_terms(get_prebasis(reffe)) == 4
@test get_order(get_prebasis(reffe)) == 0
@test num_dofs(reffe) == 4

p = QUAD
D = num_dims(QUAD)
et = Float64
order = 1

reffe = NedelecRefFE(et,p,order)
test_reference_fe(reffe)
@test num_terms(get_prebasis(reffe)) == 12
@test num_dofs(reffe) == 12
@test get_order(get_prebasis(reffe)) == 1

prebasis = get_prebasis(reffe)
dof_basis = get_dof_basis(reffe)

v = VectorValue(3.0,0.0)
field = MockField{D}(v)

cache = dof_cache(dof_basis,field)
r = evaluate_dof!(cache, dof_basis, field)
test_dof(dof_basis,field,r)

cache = dof_cache(dof_basis,prebasis)
r = evaluate_dof!(cache, dof_basis, prebasis)
test_dof(dof_basis,prebasis,r)

end # module
Loading

0 comments on commit 4435c9f

Please sign in to comment.