Calculate shape functions using FEMBasis.jl

A lot of code is moved to FEMBasis.jl regarding
calculating basis / shape functions of finite elements.

* add FEMBasis to REQUIRE
* remove obsolete files
* remove obsolete test files
* make integration point iterable
* loosen type definitions
* get length of element rather from basis than connectivity
* calculate midpoint of reference element
* wrong input argument to eval_basis! fixed
This commit is contained in:
Jukka Aho
2017-08-05 11:33:43 +03:00
parent dcd24e8e01
commit fffb0071a0
16 changed files with 85 additions and 1231 deletions
+7 -6
View File
@@ -19,6 +19,12 @@ import Base: getindex, setindex!, convert, length, size, isapprox, similar,
start, first, next, done, last, endof, vec, ==, +, -, *, /, haskey, copy,
push!, isempty, empty!, append!, sparse, full, read
using FEMBasis
using FEMBasis: AbstractBasis
using FEMQuad
using AbaqusReader
using AsterReader
using Logging
Logging.configure(level=INFO)
@@ -45,7 +51,7 @@ export AbstractPoint, Point, IntegrationPoint, IP, Node
### ELEMENTS ###
include("elements.jl") # common element routines
export Node, AbstractElement, Element, update!, get_connectivity, get_basis,
export Node, Element, update!, get_connectivity, get_basis,
get_dbasis, inside, get_local_coordinates, get_element_type,
filter_by_element_type, get_element_id
@@ -62,11 +68,6 @@ export Poi1,
Wedge6,
Hex8, Hex20, Hex27
include("elements_nurbs.jl")
export NSeg, NSurf, NSolid, is_nurbs
#include("hierarchical.jl") # P-elements
include("integrate.jl") # default integration points for elements
export get_integration_points
+15 -4
View File
@@ -1,9 +1,7 @@
# This file is a part of JuliaFEM.
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
abstract type AbstractElement end
type Element{E<:AbstractElement}
type Element{E<:AbstractBasis}
id :: Int
connectivity :: Vector{Int}
integration_points :: Vector{IP}
@@ -17,10 +15,23 @@ Examples
--------
julia> element = Element(Tri3, [1, 2, 3])
"""
function Element{E<:AbstractElement}(::Type{E}, connectivity::Vector{Int})
function Element{E<:AbstractBasis}(::Type{E}, connectivity::Vector{Int})
return Element{E}(-1, connectivity, [], Dict(), E())
end
"""
length(element::Element)
Return the number of nodes in element.
"""
function length{B}(element::Element{B})
return length(B)
end
function size{B}(element::Element{B})
return size(B)
end
function getindex(element::Element, field_name::AbstractString)
return element.fields[field_name]
end
+25 -589
View File
@@ -1,66 +1,11 @@
# This file is a part of JuliaFEM.
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
global const ELEMENT_DESCRIPTIONS = Dict(
"Poi1" => "1 node discrete point element",
"Seg2" => "2 node linear segment/line element",
"Seg3" => "3 node quadratic segment/line element",
"Tri3" => "3 node linear triangle element",
"Tri6" => "6 node quadratic triangle element",
"Tri7" => "7 node quadratic triangle element (has middle node)",
"Quad4" => "4 node linear quadrangle element",
"Quad8" => "8 node quadratic quadrangle element (Serendip)",
"Quad9" => "9 node quadratic quadrangle element",
"Tet4" => "4 node linear tetrahedral element",
"Tet10" => "10 node quadratic tetrahedral element",
"Pyr5" => "5 node linear pyramid element",
"Wedge6" => "6 node linear prismatic element (wedge)",
"Wedge15" => "15 node quadratic prismatic element (wedge)",
"Hex8" => "8 node linear hexahedral element",
"Hex20" => "20 node biquadratic hexahedral element",
"Hex27" => "27 node quadratic hexahedral element")
using FEMBasis
global const ELEMENT_SIZES = Dict(
"Poi1" => (0, 1),
"Seg2" => (1, 2),
"Seg3" => (1, 3),
"Tri3" => (2, 3),
"Tri6" => (2, 6),
"Tri7" => (2, 7),
"Quad4" => (2, 4),
"Quad8" => (2, 8),
"Quad9" => (2, 9),
"Tet4" => (3, 4),
"Tet10" => (3, 10),
"Pyr5" => (3,5),
"Wedge6" => (3, 6),
"Wedge15" => (3, 15),
"Hex8" => (3, 8),
"Hex20" => (3, 20),
"Hex27" => (3, 27))
""" Return description line of element. """
function description{T}(element::Element{T})
element_type = last(split("$T", '.'))
return get(ELEMENT_DESCRIPTIONS, element_type, "Unknown element description")
end
""" Return size of element, i.e. tuple (n, m) where n is dimension of element
(0, 1, 2, 3) and m is number of nodes. """
function size{T}(element::Element{T})
element_type = last(split("$T", '.'))
return ELEMENT_SIZES[element_type]
end
""" Return length of element, i.e. number of nodes. """
function length{T}(element::Element{T})
return size(element)[end]
end
### 0d element
type Poi1 <: AbstractElement
# "Poi1" => (0, 1),
"1 node discrete point element",
type Poi1 <: AbstractBasis
end
function get_basis(element::Element{Poi1}, ip, time)
@@ -83,541 +28,32 @@ function get_integration_points(element::Poi1, order::Int64)
return [ (1.0, [] ) ]
end
function get_reference_coordinates(::Type{Poi1})
function size(::Type{Poi1})
return (0, 1)
end
function length(::Type{Poi1})
return 1
end
function FEMBasis.get_reference_element_coordinates(::Type{Poi1})
Vector{Float64}[[0.0]]
end
### 1d elements
type Seg2 <: AbstractElement
end
function get_reference_coordinates(::Type{Seg2})
Vector{Float64}[
[-1.0], # N1
[ 1.0]] # N2
end
function get_interpolation_polynomial(::Type{Seg2}, xi)
[1.0 xi[1]]
end
function get_interpolation_polynomial(::Type{Seg2}, xi, ::Type{Val{:partial_derivatives}})
[0.0 1.0]
end
#
type Seg3 <: AbstractElement
end
function get_reference_coordinates(::Type{Seg3})
Vector{Float64}[
[-1.0], # N1
[ 1.0], # N2
[ 0.0]] # N3
end
function get_interpolation_polynomial(::Type{Seg3}, xi)
[1.0 xi[1] xi[1]^2]
end
function get_interpolation_polynomial(::Type{Seg3}, xi, ::Type{Val{:partial_derivatives}})
[0.0 1.0 2.0*xi[1]]
end
### 2d elements
type Tri3 <: AbstractElement
end
function get_reference_coordinates(::Type{Tri3})
Vector{Float64}[
[0.0, 0.0], # N1
[1.0, 0.0], # N2
[0.0, 1.0]] # N3
end
function get_interpolation_polynomial(::Type{Tri3}, xi)
[
1 xi[1] xi[2]
]
end
function get_interpolation_polynomial(::Type{Tri3}, xi, ::Type{Val{:partial_derivatives}})
[
0.0 1.0 0.0
0.0 0.0 1.0
]
end
#
type Tri6 <: AbstractElement
end
function get_reference_coordinates(::Type{Tri6})
Vector{Float64}[
[0.0, 0.0], # N1
[1.0, 0.0], # N2
[0.0, 1.0], # N3
[0.5, 0.0], # N4
[0.5, 0.5], # N5
[0.0, 0.5]] # N6
end
function get_interpolation_polynomial(::Type{Tri6}, xi)
[
1 xi[1] xi[2] xi[1]^2 xi[1]*xi[2] xi[2]^2
]
end
function get_interpolation_polynomial(::Type{Tri6}, xi, ::Type{Val{:partial_derivatives}})
[
0 1 0 2*xi[1] xi[2] 0
0 0 1 0 xi[1] 2*xi[2]
]
end
#
type Tri7 <: AbstractElement
end
function get_reference_coordinates(::Type{Tri7})
Vector{Float64}[
[0.0, 0.0], # N1
[1.0, 0.0], # N2
[0.0, 1.0], # N3
[0.5, 0.0], # N4
[0.5, 0.5], # N5
[0.0, 0.5], # N6
[1/3, 1/3]] # N7
end
function get_interpolation_polynomial(::Type{Tri7}, xi)
[
1 xi[1] xi[2] xi[1]^2 xi[1]*xi[2] xi[2]^2 xi[1]^2*xi[2]^2
]
end
function get_interpolation_polynomial(::Type{Tri7}, xi, ::Type{Val{:partial_derivatives}})
[
0 1 0 2*xi[1] xi[2] 0 2*xi[1]*xi[2]^2
0 0 1 0 xi[1] 2*xi[2] 2*xi[1]^2*xi[2]
]
end
#
type Quad4 <: AbstractElement
end
function get_reference_coordinates(::Type{Quad4})
Vector{Float64}[
[-1.0, -1.0], # N1
[ 1.0, -1.0], # N2
[ 1.0, 1.0], # N3
[-1.0, 1.0]] # N4
end
function get_interpolation_polynomial(::Type{Quad4}, xi)
[
1.0 xi[1] xi[2] xi[1]*xi[2]
]
end
function get_interpolation_polynomial(::Type{Quad4}, xi, ::Type{Val{:partial_derivatives}})
[
0 1 0 xi[2]
0 0 1 xi[1]
]
end
#
type Quad8 <: AbstractElement
end
function get_reference_coordinates(::Type{Quad8})
Vector{Float64}[
[-1.0, -1.0], # N1
[ 1.0, -1.0], # N2
[ 1.0, 1.0], # N3
[-1.0, 1.0], # N4
[ 0.0, -1.0], # N5
[ 1.0, 0.0], # N6
[ 0.0, 1.0], # N7
[-1.0, 0.0]] # N8
end
function get_interpolation_polynomial(::Type{Quad8}, xi)
[
1 xi[2] xi[1] xi[2]^2 xi[1]*xi[2] xi[1]^2 xi[1]*xi[2]^2 xi[1]^2*xi[2]
]
end
function get_interpolation_polynomial(::Type{Quad8}, xi, ::Type{Val{:partial_derivatives}})
[
0 0 1 0 xi[2] 2*xi[1] xi[2]^2 2*xi[1]*xi[2]
0 1 0 2*xi[2] xi[1] 0 2*xi[1]*xi[2] xi[1]^2
]
end
#
type Quad9 <: AbstractElement
end
function get_reference_coordinates(::Type{Quad9})
Vector{Float64}[
[-1.0, -1.0], # N1
[ 1.0, -1.0], # N2
[ 1.0, 1.0], # N3
[-1.0, 1.0], # N4
[ 0.0, -1.0], # N5
[ 1.0, 0.0], # N6
[ 0.0, 1.0], # N7
[-1.0, 0.0], # N8
[ 0.0, 0.0]] # N9
end
function get_interpolation_polynomial(::Type{Quad9}, xi)
[
1 xi[2] xi[1] xi[2]^2 xi[1]*xi[2] xi[1]^2 xi[1]*xi[2]^2 xi[1]^2*xi[2] xi[1]^2*xi[2]^2
]
end
function get_interpolation_polynomial(::Type{Quad9}, xi, ::Type{Val{:partial_derivatives}})
[
0 0 1 0 xi[2] 2*xi[1] xi[2]^2 2*xi[1]*xi[2] 2*xi[1]*xi[2]^2
0 1 0 2*xi[2] xi[1] 0 2*xi[1]*xi[2] xi[1]^2 2*xi[1]^2*xi[2]
]
end
### 3d elements
type Tet4 <: AbstractElement
function get_basis{B}(element::Element{B}, ip, time)
T = typeof(first(ip))
N = zeros(T, 1, length(B))
eval_basis!(B, N, tuple(ip...))
return N
end
function get_reference_coordinates(::Type{Tet4})
Vector{Float64}[
[0.0, 0.0, 0.0], # N1
[1.0, 0.0, 0.0], # N2
[0.0, 1.0, 0.0], # N3
[0.0, 0.0, 1.0]] # N4
function get_dbasis{B}(element::Element{B}, ip, time)
T = typeof(first(ip))
dN = zeros(T, size(B)...)
eval_dbasis!(B, dN, tuple(ip...))
return dN
end
function get_interpolation_polynomial(::Type{Tet4}, xi)
[
1.0 xi[1] xi[2] xi[3]
]
end
function get_interpolation_polynomial(::Type{Tet4}, xi, ::Type{Val{:partial_derivatives}})
[
0.0 1.0 0.0 0.0
0.0 0.0 1.0 0.0
0.0 0.0 0.0 1.0
]
end
#
type Tet10 <: AbstractElement
end
function get_reference_coordinates(::Type{Tet10})
Vector{Float64}[
[0.0, 0.0, 0.0], # N1
[1.0, 0.0, 0.0], # N2
[0.0, 1.0, 0.0], # N3
[0.0, 0.0, 1.0], # N4
[0.5, 0.0, 0.0], # N5
[0.5, 0.5, 0.0], # N6
[0.0, 0.5, 0.0], # N7
[0.0, 0.0, 0.5], # N8
[0.5, 0.0, 0.5], # N9
[0.0, 0.5, 0.5]] # N10
end
function get_interpolation_polynomial(::Type{Tet10}, xi)
[
1.0 xi[3] xi[2] xi[1] xi[3]^2 xi[2]*xi[3] xi[2]^2 xi[1]*xi[3] xi[1]*xi[2] xi[1]^2
]
end
function get_interpolation_polynomial(::Type{Tet10}, xi, ::Type{Val{:partial_derivatives}})
[
0 0 0 1 0 0 0 xi[3] xi[2] 2*xi[1]
0 0 1 0 0 xi[3] 2*xi[2] 0 xi[1] 0
0 1 0 0 2*xi[3] xi[2] 0 xi[1] 0 0
]
end
#
type Pyr5 <: AbstractElement
end
function get_reference_coordinates(::Type{Pyr5})
Vector{Float64}[
[-1.0,-1.0,-1.0], # N1
[ 1.0,-1.0,-1.0], # N2
[ 1.0, 1.0,-1.0], # N3
[-1.0, 1.0,-1.0], # N4
[ 0.0, 0.0, 1.0]] # N5
end
function get_interpolation_polynomial(::Type{Pyr5}, xi)
[
1.0/8.0*(1.0-1.0*xi[1])*(1.0-1.0*xi[2])*(1.0-1.0*xi[3])
1.0/8.0*(1.0+1.0*xi[1])*(1.0-1.0*xi[2])*(1.0-1.0*xi[3])
1.0/8.0*(1.0+1.0*xi[1])*(1.0+1.0*xi[2])*(1.0-1.0*xi[3])
1.0/8.0*(1.0-1.0*xi[1])*(1.0+1.0*xi[2])*(1.0-1.0*xi[3])
1.0/2.0*(1.0+xi[3])
]'
end
function get_interpolation_polynomial(::Type{Pyr5}, xi, ::Type{Val{:partial_derivatives}})
[
-0.125*(1.0-xi[2])*(1.0-xi[3]) 0.125*(1.0-xi[2])*(1.0-xi[3]) 0.125*(1.0+xi[2])*(1.0-xi[3]) -0.125*(1.0+xi[2])*(1.0-xi[3]) 0.0
-0.125*(1.0-xi[1])*(1.0-xi[3]) -0.125*(1.0+xi[1])*(1.0-xi[3]) 0.125*(1.0+xi[1])*(1.0-xi[3]) 0.125*(1.0-xi[1])*(1.0-xi[3]) 0.0
-0.125*(1.0-xi[1])*(1.0-xi[2]) -0.125*(1.0+xi[1])*(1.0-xi[2]) -0.125*(1.0+xi[1])*(1.0+xi[2]) -0.125*(1.0-xi[1])*(1.0+xi[2]) 0.5
]
end
#
type Wedge6 <: AbstractElement
end
function get_reference_coordinates(::Type{Wedge6})
Vector{Float64}[
[0.0, 0.0, -1.0], # N1
[1.0, 0.0, -1.0], # N2
[0.0, 1.0, -1.0], # N3
[0.0, 0.0, 1.0], # N4
[1.0, 0.0, 1.0], # N5
[0.0, 1.0, 1.0]] # N6
end
function get_interpolation_polynomial(::Type{Wedge6}, x)
[
1 x[1] x[2] x[3] x[1]*x[3] x[2]*x[3]
]
end
function get_interpolation_polynomial(::Type{Wedge6}, x, ::Type{Val{:partial_derivatives}})
[
0 1 0 0 x[3] 0
0 0 1 0 0 x[3]
0 0 0 1 x[1] x[2]
]
end
#
type Wedge15 <: AbstractElement
end
function get_reference_coordinates(::Type{Wedge15})
Vector{Float64}[
[0.0, 0.0, -1.0], # N1
[1.0, 0.0, -1.0], # N2
[0.0, 1.0, -1.0], # N3
[0.0, 0.0, 1.0], # N4
[1.0, 0.0, 1.0], # N5
[0.0, 1.0, 1.0], # N6
[0.5, 0.0, -1.0], # N7
[0.5, 0.5, -1.0], # N8
[0.0, 0.5, -1.0], # N9
[0.5, 0.0, 1.0], # N10
[0.5, 0.5, 1.0], # N11
[0.0, 0.5, 1.0], # N12
[0.0, 0.0, 0.0], # N13
[1.0, 0.0, 0.0], # N14
[0.0, 1.0, 0.0]] # N15
end
function get_interpolation_polynomial(::Type{Wedge15}, x)
[
1 x[1] x[1]^2 x[2] x[1]*x[2] x[2]^2 x[3] x[1]*x[3] x[1]^2*x[3] x[2]*x[3] x[1]*x[2]*x[3] x[2]^2*x[3] x[3]^2 x[1]*x[3]^2 x[2]*x[3]^2
]
end
function get_interpolation_polynomial(::Type{Wedge15}, x, ::Type{Val{:partial_derivatives}})
[
0 1 2*x[1] 0 x[2] 0 0 x[3] 2*x[1]*x[3] 0 x[2]*x[3] 0 0 x[3]^2 0
0 0 0 1 x[1] 2*x[2] 0 0 0 x[3] x[1]*x[3] 2*x[2]*x[3] 0 0 x[3]^2
0 0 0 0 0 0 1 x[1] x[1]^2 x[2] x[1]*x[2] x[2]^2 2*x[3] 2*x[1]*x[3] 2*x[2]*x[3]
]
end
#
type Hex8 <: AbstractElement
end
function get_reference_coordinates(::Type{Hex8})
Vector{Float64}[
[-1.0, -1.0, -1.0], # N1
[ 1.0, -1.0, -1.0], # N2
[ 1.0, 1.0, -1.0], # N3
[-1.0, 1.0, -1.0], # N4
[-1.0, -1.0, 1.0], # N5
[ 1.0, -1.0, 1.0], # N6
[ 1.0, 1.0, 1.0], # N7
[-1.0, 1.0, 1.0]] # N8
end
function get_interpolation_polynomial(::Type{Hex8}, xi)
[
1 xi[3] xi[2] xi[1] xi[2]*xi[3] xi[1]*xi[3] xi[1]*xi[2] xi[1]*xi[2]*xi[3]
]
end
function get_interpolation_polynomial(::Type{Hex8}, xi, ::Type{Val{:partial_derivatives}})
[
0 0 0 1 0 xi[3] xi[2] xi[2]*xi[3]
0 0 1 0 xi[3] 0 xi[1] xi[1]*xi[3]
0 1 0 0 xi[2] xi[1] 0 xi[1]*xi[2]
]
end
#
type Hex20 <: AbstractElement
end
function get_reference_coordinates(::Type{Hex20})
Vector{Float64}[
[-1.0, -1.0, -1.0], # N1
[ 1.0, -1.0, -1.0], # N2
[ 1.0, 1.0, -1.0], # N3
[-1.0, 1.0, -1.0], # N4
[-1.0, -1.0, 1.0], # N5
[ 1.0, -1.0, 1.0], # N6
[ 1.0, 1.0, 1.0], # N7
[-1.0, 1.0, 1.0], # N8
[ 0.0, -1.0, -1.0], # N9
[ 1.0, 0.0, -1.0], # N10
[ 0.0, 1.0, -1.0], # N11
[-1.0, 0.0, -1.0], # N12
[-1.0, -1.0, 0.0], # N13
[ 1.0, -1.0, 0.0], # N14
[ 1.0, 1.0, 0.0], # N15
[-1.0, 1.0, 0.0], # N16
[ 0.0, -1.0, 1.0], # N17
[ 1.0, 0.0, 1.0], # N18
[ 0.0, 1.0, 1.0], # N19
[-1.0, 0.0, 1.0]] # N20
end
function get_interpolation_polynomial(::Type{Hex20}, xi)
[
1 xi[3] xi[2] xi[1] xi[2]*xi[3] xi[1]*xi[3] xi[1]*xi[2] xi[1]*xi[2]*xi[3] xi[3]^2 xi[2]^2 xi[1]^2 xi[2]*xi[3]^2 xi[2]^2*xi[3] xi[1]*xi[3]^2 xi[1]*xi[2]^2 xi[1]^2*xi[3] xi[1]^2*xi[2] xi[1]*xi[2]*xi[3]^2 xi[1]*xi[2]^2*xi[3] xi[1]^2*xi[2]*xi[3]
]
end
function get_interpolation_polynomial(::Type{Hex20}, xi, ::Type{Val{:partial_derivatives}})
[
0 0 0 1 0 xi[3] xi[2] xi[2]*xi[3] 0 0 2*xi[1] 0 0 xi[3]^2 xi[2]^2 2*xi[1]*xi[3] 2*xi[1]*xi[2] xi[2]*xi[3]^2 xi[2]^2*xi[3] 2*xi[1]*xi[2]*xi[3]
0 0 1 0 xi[3] 0 xi[1] xi[1]*xi[3] 0 2*xi[2] 0 xi[3]^2 2*xi[2]*xi[3] 0 2*xi[1]*xi[2] 0 xi[1]^2 xi[1]*xi[3]^2 2*xi[1]*xi[2]*xi[3] xi[1]^2*xi[3]
0 1 0 0 xi[2] xi[1] 0 xi[1]*xi[2] 2*xi[3] 0 0 2*xi[2]*xi[3] xi[2]^2 2*xi[1]*xi[3] 0 xi[1]^2 0 2*xi[1]*xi[2]*xi[3] xi[1]*xi[2]^2 xi[1]^2*xi[2]
]
end
###
type Hex27 <: AbstractElement
end
function get_reference_coordinates(::Type{Hex27})
Vector{Float64}[
[-1.0, -1.0, -1.0], # N1
[ 1.0, -1.0, -1.0], # N2
[ 1.0, 1.0, -1.0], # N3
[-1.0, 1.0, -1.0], # N4
[-1.0, -1.0, 1.0], # N5
[ 1.0, -1.0, 1.0], # N6
[ 1.0, 1.0, 1.0], # N7
[-1.0, 1.0, 1.0], # N8
[ 0.0, -1.0, -1.0], # N9
[ 1.0, 0.0, -1.0], # N10
[ 0.0, 1.0, -1.0], # N11
[-1.0, 0.0, -1.0], # N12
[-1.0, -1.0, 0.0], # N13
[ 1.0, -1.0, 0.0], # N14
[ 1.0, 1.0, 0.0], # N15
[-1.0, 1.0, 0.0], # N16
[ 0.0, -1.0, 1.0], # N17
[ 1.0, 0.0, 1.0], # N18
[ 0.0, 1.0, 1.0], # N19
[-1.0, 0.0, 1.0], # N20
[ 0.0, 0.0, -1.0], # N21
[ 0.0, -1.0, 0.0], # N22
[ 1.0, 0.0, 0.0], # N23
[ 0.0, 1.0, 0.0], # N24
[-1.0, 0.0, 0.0], # N25
[ 0.0, 0.0, 1.0], # N26
[ 0.0, 0.0, 0.0]] # N27
end
function get_interpolation_polynomial(::Type{Hex27}, xi)
[
1 xi[3] xi[2] xi[1] xi[2]*xi[3] xi[1]*xi[3] xi[1]*xi[2] xi[1]*xi[2]*xi[3] xi[3]^2 xi[2]^2 xi[1]^2 xi[2]*xi[3]^2 xi[2]^2*xi[3] xi[1]*xi[3]^2 xi[1]*xi[2]^2 xi[1]^2*xi[3] xi[1]^2*xi[2] xi[2]^2*xi[3]^2 xi[1]*xi[2]*xi[3]^2 xi[1]*xi[2]^2*xi[3] xi[1]^2*xi[3]^2 xi[1]^2*xi[2]*xi[3] xi[1]^2*xi[2]^2 xi[1]*xi[2]^2*xi[3]^2 xi[1]^2*xi[2]*xi[3]^2 xi[1]^2*xi[2]^2*xi[3] xi[1]^2*xi[2]^2*xi[3]^2
]
end
function get_interpolation_polynomial(::Type{Hex27}, xi, ::Type{Val{:partial_derivatives}})
[
0 0 0 1 0 xi[3] xi[2] xi[2]*xi[3] 0 0 2*xi[1] 0 0 xi[3]^2 xi[2]^2 2*xi[1]*xi[3] 2*xi[1]*xi[2] 0 xi[2]*xi[3]^2 xi[2]^2*xi[3] 2*xi[1]*xi[3]^2 2*xi[1]*xi[2]*xi[3] 2*xi[1]*xi[2]^2 xi[2]^2*xi[3]^2 2*xi[1]*xi[2]*xi[3]^2 2*xi[1]*xi[2]^2*xi[3] 2*xi[1]*xi[2]^2*xi[3]^2
0 0 1 0 xi[3] 0 xi[1] xi[1]*xi[3] 0 2*xi[2] 0 xi[3]^2 2*xi[2]*xi[3] 0 2*xi[1]*xi[2] 0 xi[1]^2 2*xi[2]*xi[3]^2 xi[1]*xi[3]^2 2*xi[1]*xi[2]*xi[3] 0 xi[1]^2*xi[3] 2*xi[1]^2*xi[2] 2*xi[1]*xi[2]*xi[3]^2 xi[1]^2*xi[3]^2 2*xi[1]^2*xi[2]*xi[3] 2*xi[1]^2*xi[2]*xi[3]^2
0 1 0 0 xi[2] xi[1] 0 xi[1]*xi[2] 2*xi[3] 0 0 2*xi[2]*xi[3] xi[2]^2 2*xi[1]*xi[3] 0 xi[1]^2 0 2*xi[2]^2*xi[3] 2*xi[1]*xi[2]*xi[3] xi[1]*xi[2]^2 2*xi[1]^2*xi[3] xi[1]^2*xi[2] 0 2*xi[1]*xi[2]^2*xi[3] 2*xi[1]^2*xi[2]*xi[3] xi[1]^2*xi[2]^2 2*xi[1]^2*xi[2]^2*xi[3]
]
end
###
macro create_basis(T)
quote
T = $T
global get_basis, get_dbasis, length, size
X = get_reference_coordinates(T)
nbasis = length(X)
A = zeros(nbasis, nbasis)
for i=1:nbasis
A[i,:] = get_interpolation_polynomial(T, X[i])
end
invA = inv(A)
function get_basis(element::Element{$T}, ip, time)
return get_interpolation_polynomial($T, ip)*invA
end
function get_dbasis(element::Element{$T}, ip, time)
return get_interpolation_polynomial($T, ip, Val{:partial_derivatives})*invA
end
end
end
@create_basis Seg2
@create_basis Seg3
@create_basis Tri3
@create_basis Tri6
@create_basis Tri7
@create_basis Quad4
@create_basis Quad8
@create_basis Quad9
@create_basis Tet4
@create_basis Tet10
@create_basis Pyr5
@create_basis Wedge6
@create_basis Wedge15
@create_basis Hex8
@create_basis Hex20
@create_basis Hex27
function inside(::Union{Type{Seg2}, Type{Seg3}, Type{Quad4}, Type{Quad8},
Type{Quad9}, Type{Pyr5}, Type{Hex8}, Type{Hex20},
Type{Hex27}}, xi)
@@ -628,7 +64,7 @@ function inside(::Union{Type{Tri3}, Type{Tri6}, Type{Tri7}, Type{Tet4}, Type{Tet
return all(xi .>= 0.0) && (sum(xi) <= 1.0)
end
function get_reference_coordinates{E}(element::Element{E})
get_reference_coordinates(E)
function get_reference_coordinates{B}(element::Element{B})
return get_reference_element_coordinates(B)
end
-149
View File
@@ -1,149 +0,0 @@
# 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
+1 -1
View File
@@ -416,7 +416,7 @@ function (field::CCTV)(xi::Vector, time::Number)
return field.data(time)
end
function (field::CVTV)(xi::Vector, time::Number)
function (field::CVTV)(xi, time)
return field.data(xi, time)
end
+3 -3
View File
@@ -122,7 +122,7 @@ function assemble!(problem::Problem{Contact}, slave_element::Element{Tri3}, time
Q3 = create_rotation_matrix(slave_element, time)
# project slave nodes to auxiliary plane (x0, Q)
xi = mean(get_reference_coordinates(slave_element))
xi = get_mean_xi(slave_element)
N = vec(get_basis(slave_element, xi, time))
x0 = N*X1
n0 = N*n1
@@ -280,7 +280,7 @@ function assemble!(problem::Problem{Contact}, slave_element::Element{Tri6}, time
#la = sub_slave_element("lambda", time)
# create auxiliary plane
xi = mean(get_reference_coordinates(sub_slave_element))
xi = get_mean_xi(sub_slave_element)
N = vec(get_basis(sub_slave_element, xi, time))
x0 = N*X1
n0 = N*n1
@@ -356,7 +356,7 @@ function assemble!(problem::Problem{Contact}, slave_element::Element{Tri6}, time
n1 = sub_slave_element("normal", time)
# create auxiliary plane
xi = mean(get_reference_coordinates(sub_slave_element))
xi = get_mean_xi(sub_slave_element)
N = vec(get_basis(sub_slave_element, xi, time))
x0 = N*X1
n0 = N*n1
+1 -1
View File
@@ -56,7 +56,7 @@ function assemble!(problem::Problem{Dirichlet}, time::Float64=0.0;
for i=1:field_dim
haskey(element, field_name*" $i") || continue
ldofs = gdofs[i:field_dim:end]
xis = get_reference_coordinates(typeof(element.properties))
xis = get_reference_coordinates(element)
vals = Float64[]
for xi in xis
g = element(field_name*" $i", xi, time)
+1 -1
View File
@@ -146,7 +146,7 @@ function diagnose_interface(problem::Problem{Mortar}, time::Float64)
n1 = Field([normals[j] for j in slave_element_nodes])
# project slave nodes to auxiliary plane (x0, Q)
xi = mean(get_reference_coordinates(slave_element))
xi = get_mean_xi(slave_element)
N = vec(get_basis(slave_element, xi, time))
x0 = N*X1
n0 = N*n1
+17 -6
View File
@@ -103,11 +103,11 @@ function approx_in{T}(q::T, P::Vector{T}; rtol=1.0e-4, atol=0.0)
return false
end
function get_polygon_clip(xs, xm, n)
function get_polygon_clip{T}(xs::Vector{T}, xm::Vector{T}, n::T)
# objective: search does line xm1 - xm2 clip xs
nm = length(xm)
ns = length(xs)
P = Vector[]
P = T[]
# 1. test is master point inside slave, if yes, add to clip
for i=1:nm
@@ -330,6 +330,17 @@ function split_quadratic_elements(elements::Vector, time::Float64)
return new_elements
end
function get_mean_xi(element::Element)
xi = zeros(2)
coords = get_reference_coordinates(element)
for (xi1,xi2) in coords
xi[1] += xi1
xi[2] += xi2
end
xi /= length(coords)
return xi
end
""" Assemble linear surface element to problem.
Dual basis is constructed such that partially integrated slave segments are taken into account in a proper way.
@@ -357,7 +368,7 @@ function assemble!{E<:Union{Tri3, Quad4}}(problem::Problem{Mortar}, slave_elemen
n1 = slave_element("normal", time)
# project slave nodes to auxiliary plane (x0, Q)
xi = mean(get_reference_coordinates(slave_element))
xi = get_mean_xi(slave_element)
first_slave_element && debug("midpoint xi = $xi")
N = vec(get_basis(slave_element, xi, time))
x0 = N*X1
@@ -465,7 +476,7 @@ function assemble!{E<:Union{Tri3, Quad4}}(problem::Problem{Mortar}, slave_elemen
all_cells = get_cells(P, C0)
for cell in all_cells
virtual_element = Element(Tri3, Int[])
update!(virtual_element, "geometry", cell)
virtual_element.fields["geometry"] = DVTI(cell)
# 5. loop integration point of integration cell
for ip in get_integration_points(virtual_element, 3)
@@ -579,7 +590,7 @@ function assemble!{E<:Union{Tri6}}(problem::Problem{Mortar}, slave_element::Elem
n1 = sub_slave_element("normal", time)
# create auxiliary plane
xi = mean(get_reference_coordinates(sub_slave_element))
xi = get_mean_xi(sub_slave_element)
first_slave_element && debug("midpoint xi = $xi")
N = vec(get_basis(sub_slave_element, xi, time))
x0 = N*X1
@@ -662,7 +673,7 @@ function assemble!{E<:Union{Tri6}}(problem::Problem{Mortar}, slave_element::Elem
n1 = sub_slave_element("normal", time)
# create auxiliary plane
xi = mean(get_reference_coordinates(sub_slave_element))
xi = get_mean_xi(sub_slave_element)
first_slave_element && debug("midpoint xi = $xi")
N = vec(get_basis(sub_slave_element, xi, time))
x0 = N*X1
+12
View File
@@ -33,6 +33,18 @@ function (point::Point)(field_name, time=0.0)
point.fields[field_name](time).data
end
function start(point::Point)
return start(point.coords)
end
function done(point::Point, i)
return done(point.coords, i)
end
function next(point::Point, i)
return next(point.coords, i)
end
function update!{T}(point::Point, field_name, val::Pair{Float64, T})
if haskey(point, field_name)
update!(point[field_name], val)