Files
JuliaFEM.jl/src/elements_nurbs.jl
T
Jukka Aho c307c1482c Testing/code coverage (#83)
Change the code coverage to green. 

* removed duplicate code

* Removed unused code

* removed unmaintained code

* DCTI + DVTI refactored

* discrete fields refactored and tested

* fields are now tested quite well.

* Removed obsolete code not used anywhere

* Element descriptions to common dictionary

* size in global const dictionary also

* Added coverage to sparse tools and removed couple unused functions

* get nonzero rows from SparseMatrixCSC

* bugfix: extending element basis now working and tested

* Removed two unused functions from elements.jl

* removed useless function

* Useless conversion

* remove elasticity assembly using ForwardDiff because it's not used anywhere'

* Added basic testing for NURBS. Fixed bug in NSolid interpolation.

* removed unused functions

* Removed some debug stuff

* renamed file

* removed field assembly posthook, i think not good idea at all

* test for nnz(K) == 0 and automatic determination of dofs

* Testing that solver is throwing error if having problems with boundary assembly

* Removed some unused options. Refactoring.

* Moved solver non-related code to elements.jl

* Removed custom exception (no need)

* unneeded postprocess code

* More tests for NURBS elements.

* Removed unfinished .mail parser

* proper use of Logging package

* also read results

* renamed test file

* create_surface_elements accepts surface name in String now

* bugfix: remove zero rows from constraint matrix after manually removing dofs from some boundary assemblies.

* New test, displacement 3d patch test

* skip displacement field in surface element splitting if not defined

* test element splitting and linear surface elements, fails.

* Bugfix: Xdmf, not XDMF

* removed nonworking tests, requires bugfix

* abaqus_read_results is not working -> bug
2017-01-30 12:28:33 +02:00

150 lines
4.0 KiB
Julia

# This file is a part of JuliaFEM.
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
using ForwardDiff
# TODO: evaluate partial derivatives of basis functions without forwarddiff
""" NURBS segment. """
type NSeg <: AbstractElement
order :: Int
knots :: Vector{Float64}
weights :: Vector{Float64}
end
function NSeg()
NSeg(1,
[-1.0, -1.0, 1.0, 1.0],
ones(4))
end
type NSurf <: AbstractElement
order_u :: Int
order_v :: Int
knots_u :: Vector{Float64}
knots_v :: Vector{Float64}
weights :: Matrix{Float64}
end
function NSurf()
NSurf(1, 1,
[-1.0, -1.0, 1.0, 1.0],
[-1.0, -1.0, 1.0, 1.0],
ones(2, 2))
end
type NSolid <: AbstractElement
order_u :: Int
order_v :: Int
order_w :: Int
knots_u :: Vector{Float64}
knots_v :: Vector{Float64}
knots_w :: Vector{Float64}
weights :: Array{Float64, 3}
end
function NSolid()
NSolid(1, 1, 1,
[-1.0, -1.0, 1.0, 1.0],
[-1.0, -1.0, 1.0, 1.0],
[-1.0, -1.0, 1.0, 1.0],
ones(2, 2, 2))
end
function NURBS(i, p, u, t)
p == 0 && return t[i] <= u <= t[i+1] ? 1.0 : 0.0
anom = u-t[i]
adenom = t[i+p]-t[i]
a = isapprox(adenom, 0.0) ? 0.0 : anom/adenom
bnom = t[i+p+1]-u
bdenom = t[i+p+1]-t[i+1]
b = isapprox(bdenom, 0.0) ? 0.0 : bnom/bdenom
result = a*NURBS(i,p-1,u,t) + b*NURBS(i+1,p-1,u,t)
return result
end
function get_basis(element::Element{NSeg}, xi::Vector, time)
pu = element.properties.order
tu = element.properties.knots
w = element.properties.weights
nu = length(tu)-pu-1
u = xi[1]
N = vec([w[j]*NURBS(j,pu,u,tu) for j=1:nu])'
return N/sum(N)
end
function get_basis(element::Element{NSurf}, xi::Vector, time)
pu = element.properties.order_u
pv = element.properties.order_v
tu = element.properties.knots_u
tv = element.properties.knots_v
w = element.properties.weights
nu = length(tu)-pu-1
nv = length(tv)-pv-1
u, v = xi
N = vec([w[i,j]*NURBS(i,pu,u,tu)*NURBS(j,pv,v,tv) for i=1:nu, j=1:nv])'
return N / sum(N)
end
function get_basis(element::Element{NSolid}, xi::Vector, time)
pu = element.properties.order_u
pv = element.properties.order_v
pw = element.properties.order_w
tu = element.properties.knots_u
tv = element.properties.knots_v
tw = element.properties.knots_w
weights = element.properties.weights
nu = length(tu)-pu-1
nv = length(tv)-pv-1
nw = length(tw)-pw-1
u, v, w = xi
N = vec([weights[i,j,k]*NURBS(i,pu,u,tu)*NURBS(j,pv,v,tv)*NURBS(k,pw,w,tw) for i=1:nu, j=1:nv, k=1:nw])'
return N / sum(N)
end
# TODO: evaluate partial derivatives of basis functions without forwarddiff
""" Evaluate partial derivatives of basis functions using ForwardDiff. """
function get_dbasis{E<:Union{NSeg, NSurf, NSolid}}(element::Element{E}, ip, time)
xi = isa(ip, IP) ? ip.coords : ip
basis(xi) = vec(get_basis(element, xi, time))
return ForwardDiff.jacobian(basis, xi)'
end
function length(element::Element{NSeg})
nu = length(element.properties.knots) - element.properties.order - 1
return nu
end
function size(element::Element{NSeg})
return (1, length(element))
end
function length(element::Element{NSurf})
nu = length(element.properties.knots_u) - element.properties.order_u - 1
nv = length(element.properties.knots_v) - element.properties.order_v - 1
return nu*nv
end
function size(element::Element{NSurf})
return (2, length(element))
end
function length(element::Element{NSolid})
nu = length(element.properties.knots_u) - element.properties.order_u - 1
nv = length(element.properties.knots_v) - element.properties.order_v - 1
nw = length(element.properties.knots_w) - element.properties.order_w - 1
return nu*nv*nw
end
function size(element::Element{NSolid})
return (3, length(element))
end
function is_nurbs(element::Element)
return false
end
function is_nurbs{E<:Union{NSeg, NSurf, NSolid}}(element::Element{E})
return true
end