Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changed the definition of order in Raviart-Thomas and Nedelec reffes #212

Merged
merged 1 commit into from
Mar 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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