mirror of
https://github.com/JuliaFEM/JuliaFEM.jl.git
synced 2026-09-18 09:41:31 +00:00
Merge branch 'master' of https://github.com/JuliaFEM/JuliaFEM.jl
This commit is contained in:
@@ -4,10 +4,20 @@ module JuliaFEM
|
||||
|
||||
VERSION < v"0.4-" && using Docile
|
||||
using Lexicon
|
||||
using Logging
|
||||
@Logging.configure(level=DEBUG)
|
||||
|
||||
Logging.info("loading types")
|
||||
include("types.jl") # type definitions
|
||||
Logging.info("loading elements")
|
||||
include("elements.jl") # elements
|
||||
include("math.jl") # basic mathematical operations
|
||||
|
||||
include("elasticity_solver.jl")
|
||||
include("xdmf.jl")
|
||||
include("abaqus_reader.jl")
|
||||
include("interfaces.jl")
|
||||
|
||||
export set_coordinates, get_coordinates, set_material
|
||||
|
||||
end # module
|
||||
|
||||
+9
-17
@@ -1,17 +1,12 @@
|
||||
# This file is a part of JuliaFEM.
|
||||
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
|
||||
|
||||
module abaqus_reader
|
||||
eldims = Dict(
|
||||
"C3D10" => 10,
|
||||
"C3D4" => 4)
|
||||
|
||||
using Logging
|
||||
@Logging.configure(level=DEBUG)
|
||||
|
||||
VERSION < v"0.4-" && using Docile
|
||||
|
||||
eldims = Dict({"C3D10" => 10})
|
||||
global handlers = Dict()
|
||||
|
||||
|
||||
"""
|
||||
Register new handler for parser
|
||||
"""
|
||||
@@ -29,13 +24,12 @@ end
|
||||
function parse_header(header_line)
|
||||
args = map(s -> strip(s), split(header_line, ","))
|
||||
args[1] = strip(args[1], '*')
|
||||
d = Dict({"section" => args[1]})
|
||||
options = Dict()
|
||||
d = Dict("section" => args[1], "options" => Dict())
|
||||
options = d["options"]
|
||||
for k in args[2:end]
|
||||
args2 = split(k, "=")
|
||||
options[args2[1]] = args2[2]
|
||||
end
|
||||
d["options"] = options
|
||||
return d
|
||||
end
|
||||
|
||||
@@ -56,7 +50,7 @@ function parse_element_section(model, header, data)
|
||||
end
|
||||
eldim = eldims[eltype]
|
||||
m = matchall(r"[0-9]+", data)
|
||||
m = map(integer, m)
|
||||
m = map((s) -> parse(Int, s), m)
|
||||
elements = create_or_get(model, "elements")
|
||||
m = reshape(m, eldim+1, round(Int, length(m)/(eldim+1)))
|
||||
nel = size(m)[2]
|
||||
@@ -80,7 +74,7 @@ function parse_nodeset_section(model, header, data)
|
||||
nset_name = header["options"]["NSET"]
|
||||
Logging.debug("Creating node set $nset_name")
|
||||
m = matchall(r"[0-9]+", data)
|
||||
node_ids = map(integer, m)
|
||||
node_ids = map((s) -> parse(Int, s), m)
|
||||
nsets = create_or_get(model, "nsets")
|
||||
nsets[nset_name] = Int64[]
|
||||
for j in node_ids
|
||||
@@ -110,10 +104,10 @@ function parse_abaqus(fid)
|
||||
end
|
||||
|
||||
for line in eachline(fid)
|
||||
if beginswith(line, "**")
|
||||
if startswith(line, "**")
|
||||
continue
|
||||
end
|
||||
if beginswith(line, "*")
|
||||
if startswith(line, "*")
|
||||
process_section(section)
|
||||
header = parse_header(line)
|
||||
Logging.debug("Found ", header["section"], " section")
|
||||
@@ -131,5 +125,3 @@ add_handler("NODE", parse_node_section)
|
||||
add_handler("ELEMENT", parse_element_section)
|
||||
add_handler("NSET", parse_nodeset_section)
|
||||
|
||||
end
|
||||
|
||||
|
||||
+85
-82
@@ -3,6 +3,8 @@
|
||||
|
||||
module elasticity_solver
|
||||
|
||||
using ForwardDiff
|
||||
|
||||
using Logging
|
||||
@Logging.configure(level=INFO)
|
||||
|
||||
@@ -12,103 +14,104 @@ VERSION < v"0.4-" && using Docile
|
||||
# directly if needed or using general interface combining data model and
|
||||
# solver.
|
||||
|
||||
|
||||
"""
|
||||
Interpolate field variable using basis functions f for point ip.
|
||||
This function tries to be as general as possible and allows interpolating
|
||||
lot of different fields.
|
||||
This is dummy function. Testing doctests and documentation.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
field :: Array{Number, dim}
|
||||
Field variable
|
||||
basis :: Function
|
||||
Basis functions
|
||||
ip :: Array{Number, 1}
|
||||
Point to interpolate
|
||||
x : Array{Float64, 1}
|
||||
|
||||
Returns
|
||||
-------
|
||||
Array{float64, 1}
|
||||
x + 1
|
||||
|
||||
Notes
|
||||
-----
|
||||
This is dummy function
|
||||
|
||||
Raises
|
||||
------
|
||||
Exception
|
||||
if things are not going right
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> a = [1.0, 2.0, 3.0]
|
||||
>>> dummy(a)
|
||||
[2.0, 3.0, 4.0]
|
||||
"""
|
||||
function interpolate{T<:Real}(field::Array{T,1}, basis::Function, ip)
|
||||
result = dot(field, basis(ip))
|
||||
return result
|
||||
end
|
||||
function interpolate{T<:Real}(field::Array{T,2}, basis::Function, ip)
|
||||
m, n = size(field)
|
||||
bip = basis(ip)
|
||||
tmp = size(bip)
|
||||
if length(tmp) == 1
|
||||
ndim = 1
|
||||
nnodes = tmp[1]
|
||||
else
|
||||
ndim, nnodes = size(bip)
|
||||
end
|
||||
if ndim == 1
|
||||
if n == nnodes
|
||||
result = field * bip
|
||||
elseif m == nnodes
|
||||
result = field' * bip
|
||||
end
|
||||
else
|
||||
if n == nnodes
|
||||
result = bip' * field
|
||||
elseif m == nnodes
|
||||
result = bip' * field'
|
||||
end
|
||||
end
|
||||
if length(result) == 1
|
||||
result = result[1]
|
||||
end
|
||||
return result
|
||||
function dummy(a)
|
||||
# not doing anything useful.
|
||||
return a+1
|
||||
end
|
||||
|
||||
|
||||
|
||||
"""
|
||||
Calculate local tangent stiffness matrix and residual force vector R = T - F
|
||||
Calculate local tangent stiffness matrix and residual force vector
|
||||
R = T - F for elasticity problem.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
X : Element coordinates
|
||||
u : Displacement field
|
||||
R : Residual force vector
|
||||
K : Tangent stiffness matrix
|
||||
basis : Basis functions
|
||||
dbasis : Derivative of basis functions
|
||||
lambda : Material parameter
|
||||
mu : Material parameter
|
||||
ipoints : integration points
|
||||
iweights : integration weights
|
||||
|
||||
Returns
|
||||
-------
|
||||
None
|
||||
|
||||
Notes
|
||||
-----
|
||||
If material parameters are given in list, they are interpolated to gauss
|
||||
points using shape functions.
|
||||
"""
|
||||
function calc_local_matrices!(X, u, R, Kt, N, dNdchi, lambda_, mu_, ipoints, iweights)
|
||||
dim, nnodes = size(X)
|
||||
I = eye(dim)
|
||||
R[:,:] = 0.0
|
||||
Kt[:,:] = 0.0
|
||||
function calc_local_matrices!(X, u, R, K, basis, dbasis, lambda_, mu_, ipoints, iweights)
|
||||
dim, nnodes = size(X)
|
||||
I = eye(dim)
|
||||
R[:,:] = 0.0
|
||||
|
||||
dF = zeros(dim, dim)
|
||||
#dF = zeros(dim, dim)
|
||||
|
||||
for m = 1:length(iweights)
|
||||
w = iweights[m]
|
||||
chi = ipoints[m, :]
|
||||
# interpolate material parameters from element node fields
|
||||
#lambda = (lambda_*N(chi))[1]
|
||||
#mu = (mu_*N(chi))[1]
|
||||
# Jt = X*dNdchi(chi)
|
||||
#@debug("Jt:\n",Jt)
|
||||
lambda = interpolate(lambda_, N, chi)
|
||||
mu = interpolate(mu_, N, chi)
|
||||
Jt = interpolate(X, dNdchi, chi)
|
||||
detJ = det(Jt)
|
||||
deltaN = inv(Jt)*dNdchi(chi)'
|
||||
delta_u = u*deltaN'
|
||||
F = I + delta_u # Deformation gradient
|
||||
E = 1/2*(delta_u' + delta_u + delta_u'*delta_u) # Green-Lagrange strain tensor
|
||||
S = lambda*trace(E)*I + 2*mu*E # PK2 stress tensor
|
||||
P = F*S # PK1 stress tensor
|
||||
R[:,:] += w*P*deltaN*detJ
|
||||
function calc_R!(u, R)
|
||||
for m = 1:length(iweights)
|
||||
w = iweights[m]
|
||||
xi = ipoints[m, :]
|
||||
# calculate material parameters
|
||||
lambda = typeof(lambda_) == Float64 ? lambda_ : dot(lambda_, basis(xi))
|
||||
mu = typeof(mu_) == Float64 ? mu_ : dot(mu_, basis(xi))
|
||||
Jt = X*dbasis(xi)
|
||||
detJ = det(Jt)
|
||||
dbasisdX = dbasis(xi)*inv(Jt)
|
||||
|
||||
for p = 1:nnodes
|
||||
for i = 1:dim
|
||||
dF[:,:] = 0.0
|
||||
dF[i,:] = deltaN[:,p]
|
||||
dE = 1/2*(F'*dF + dF'*F)
|
||||
dS = lambda*trace(dE)*I + 2*mu*dE
|
||||
dP = dF*S + F*dS
|
||||
for q = 1:nnodes
|
||||
for j = 1:dim
|
||||
Kt[dim*(p-1)+i,dim*(q-1)+j] += w*(dP[j,:]*deltaN[:,q])[1]*detJ
|
||||
end
|
||||
end
|
||||
end
|
||||
gradu = u*dbasisdX
|
||||
F = I + gradu # Deformation gradient
|
||||
E = 1/2*(gradu' + gradu + gradu'*gradu) # Green-Lagrange strain tensor
|
||||
S = lambda*trace(E)*I + 2*mu*E # PK2 stress tensor
|
||||
P = F*S # PK1 stress tensor
|
||||
|
||||
R[:,:] += w*P*dbasisdX'*detJ
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# herlper for tangent stiffness matrix
|
||||
function R!(u, R)
|
||||
R[:] = 0
|
||||
calc_R!(reshape(u, dim, nnodes), reshape(R, dim, nnodes))
|
||||
#calc_Wext!(reshape(u, 2, 4), reshape(R, 2, 4))
|
||||
end
|
||||
Jacobian = ForwardDiff.forwarddiff_jacobian(R!, Float64, fadtype=:dual, n=dim*nnodes, m=dim*nnodes)
|
||||
|
||||
K[:, :] = Jacobian(reshape(u, dim*nnodes))
|
||||
R!(reshape(u, dim*nnodes), reshape(R, dim*nnodes))
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
+235
@@ -0,0 +1,235 @@
|
||||
# This file is a part of JuliaFEM.
|
||||
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
|
||||
|
||||
abstract Element
|
||||
|
||||
"""
|
||||
Get jacobian of element evaluated at point xi
|
||||
"""
|
||||
function get_jacobian(el::Element, xi)
|
||||
dbasisdxi(xi) = get_dbasisdxi(el, xi)
|
||||
X = get_coordinates(el)
|
||||
J = interpolate(X, dbasisdxi, xi)'
|
||||
return J
|
||||
end
|
||||
|
||||
"""
|
||||
Evaluate partial derivatives of basis function w.r.t
|
||||
material description X, i.e. dbasis/dX
|
||||
"""
|
||||
function get_dbasisdX(el::Element, xi)
|
||||
dbasisdxi = get_dbasisdxi(el, xi)
|
||||
J = get_jacobian(el, xi)
|
||||
dbasisdxi*inv(J)
|
||||
end
|
||||
|
||||
"""
|
||||
Return coordinates of element in array of size dim x nnodes
|
||||
"""
|
||||
function get_coordinates(el::Element)
|
||||
el.coordinates
|
||||
end
|
||||
|
||||
"""
|
||||
Set coordinates for element
|
||||
"""
|
||||
function set_coordinates(el::Element, coordinates)
|
||||
el.coordinates = coordinates
|
||||
end
|
||||
|
||||
"""
|
||||
Get element id
|
||||
"""
|
||||
function get_element_id(el::Element)
|
||||
el.id
|
||||
end
|
||||
|
||||
|
||||
|
||||
### Lagrange family ###
|
||||
|
||||
abstract CG <: Element # Lagrange element family
|
||||
|
||||
"""
|
||||
Create new Lagrange element
|
||||
|
||||
FIXME: this is not working
|
||||
|
||||
LoadError: error compiling anonymous: type definition not allowed inside a local scope
|
||||
|
||||
It's the for loop which is causing problems. See
|
||||
https://github.com/JuliaLang/julia/issues/10555
|
||||
|
||||
"""
|
||||
function create_lagrange_element(element_name, X, P, dP)
|
||||
|
||||
@eval begin
|
||||
|
||||
nnodes, dim = size(X)
|
||||
A = zeros(nnodes, nnodes)
|
||||
for i=1:nnodes
|
||||
A[i,:] = P(X[i,:])
|
||||
end
|
||||
invA = inv(A)'
|
||||
|
||||
type $element_name
|
||||
element_id :: Int
|
||||
node_ids :: Array{Int, 1}
|
||||
coordinates :: Array{Float64, 2}
|
||||
fields :: Dict{ASCIIString, Any}
|
||||
end
|
||||
|
||||
function $element_name(element_id, node_ids)
|
||||
coordinates = zeros(dim, nnodes)
|
||||
fields = Dict{ASCIIString, Any}()
|
||||
$element_name(element_id, node_ids, coordinates, fields)
|
||||
end
|
||||
|
||||
function $element_name(element_id, node_ids, coordinates)
|
||||
fields = Dict{ASCIIString, Any}()
|
||||
$element_name(element_id, node_ids, coordinates, fields)
|
||||
end
|
||||
|
||||
function get_basis(el::$element_name, xi)
|
||||
invA*P(xi)
|
||||
end
|
||||
|
||||
function get_dbasisdxi(el::$element_name, xi)
|
||||
invA*dP(xi)
|
||||
end
|
||||
|
||||
$element_name
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# 0d Lagrange elements
|
||||
|
||||
"""
|
||||
1 node point element
|
||||
"""
|
||||
type Point1 <: CG
|
||||
element_id :: Int
|
||||
node_ids :: Array{Int, 1}
|
||||
coordinates :: Array{Float64, 2}
|
||||
fields :: Dict{ASCIIString, Any}
|
||||
end
|
||||
|
||||
# 1d Lagrange elements
|
||||
|
||||
"""
|
||||
2 node linear line element
|
||||
"""
|
||||
type Seg2 <: CG
|
||||
element_id :: Int
|
||||
node_ids :: Array{Int, 1}
|
||||
coordinates :: Array{Float64, 2}
|
||||
fields :: Dict{ASCIIString, Any}
|
||||
end
|
||||
|
||||
# X = [-1.0 1.0]'
|
||||
# P = (xi) -> [1.0 xi[1]]'
|
||||
# dP = (xi) -> [0.0 1.0]'
|
||||
# create_lagrange_element(:Seg2, X, P, dP)
|
||||
|
||||
"""
|
||||
3 node quadratic line element
|
||||
"""
|
||||
type Seg2 <: CG
|
||||
element_id :: Int
|
||||
node_ids :: Array{Int, 1}
|
||||
coordinates :: Array{Float64, 2}
|
||||
fields :: Dict{ASCIIString, Any}
|
||||
end
|
||||
#X = [-1.0 1.0 0.0]'
|
||||
#P = (xi) -> [1.0 xi[1] xi[1]^2]'
|
||||
#dP = (xi) -> [0.0 1.0 2*xi[1]]'
|
||||
#create_lagrange_element(:Seg3, X, P, dP)
|
||||
|
||||
# 2d Lagrange elements
|
||||
|
||||
"""
|
||||
4 node bilinear quadrangle element
|
||||
"""
|
||||
type Quad4 <: CG
|
||||
element_id :: Int
|
||||
node_ids :: Array{Int, 1}
|
||||
coordinates :: Array{Float64, 2}
|
||||
fields :: Dict{ASCIIString, Any}
|
||||
end
|
||||
function get_basis(el::Quad4, xi)
|
||||
[(1-xi[1])*(1-xi[2])/4
|
||||
(1+xi[1])*(1-xi[2])/4
|
||||
(1+xi[1])*(1+xi[2])/4
|
||||
(1-xi[1])*(1+xi[2])/4]
|
||||
end
|
||||
function get_dbasisdxi(el::Quad4, xi)
|
||||
[-(1-xi[2])/4.0 -(1-xi[1])/4.0
|
||||
(1-xi[2])/4.0 -(1+xi[1])/4.0
|
||||
(1+xi[2])/4.0 (1+xi[1])/4.0
|
||||
-(1+xi[2])/4.0 (1-xi[1])/4.0]
|
||||
end
|
||||
#X = [
|
||||
# -1.0 -1.0
|
||||
# 1.0 -1.0
|
||||
# 1.0 1.0
|
||||
# -1.0 1.0]
|
||||
#P = (xi) -> [
|
||||
# 1.0
|
||||
# xi[1]
|
||||
# xi[2]
|
||||
# xi[1]*xi[2]]
|
||||
#dP = (xi) -> [
|
||||
# 0.0 0.0
|
||||
# 1.0 0.0
|
||||
# 0.0 1.0
|
||||
# xi[2] xi[1]]
|
||||
#create_lagrange_element(:Quad4, X, P, dP)
|
||||
|
||||
# 3d Lagrange elements
|
||||
|
||||
"""
|
||||
10 node quadratic tethahedron
|
||||
"""
|
||||
type Tet10 <: CG
|
||||
element_id :: Int
|
||||
node_ids :: Array{Int, 1}
|
||||
coordinates :: Array{Float64, 2}
|
||||
fields :: Dict{ASCIIString, Any}
|
||||
end
|
||||
# X = [
|
||||
# 0.0 0.0 0.0
|
||||
# 1.0 0.0 0.0
|
||||
# 0.0 1.0 0.0
|
||||
# 0.0 0.0 1.0
|
||||
# 0.5 0.0 0.0
|
||||
# 0.5 0.5 0.0
|
||||
# 0.0 0.5 0.0
|
||||
# 0.0 0.0 0.5
|
||||
# 0.5 0.0 0.5
|
||||
# 0.0 0.5 0.5]
|
||||
# P(xi) = [
|
||||
# 1
|
||||
# xi[1]
|
||||
# xi[2]
|
||||
# xi[3]
|
||||
# xi[1]^2
|
||||
# xi[2]^2
|
||||
# xi[3]^2
|
||||
# xi[1]*xi[2]
|
||||
# xi[2]*xi[3]
|
||||
# xi[3]*xi[1]]
|
||||
# dP(xi) = [
|
||||
# 0 0 0
|
||||
# 1 0 0
|
||||
# 0 1 0
|
||||
# 0 0 1
|
||||
# 2*xi[1] 0 0
|
||||
# 0 2*xi[2] 0
|
||||
# 0 0 2*xi[3]
|
||||
# xi[2] xi[1] 0
|
||||
# 0 xi[3] xi[2]
|
||||
# xi[3] 0 xi[1]
|
||||
# ]
|
||||
#create_lagrange_element(:Tet10, X, P, dP)
|
||||
+186
@@ -0,0 +1,186 @@
|
||||
# This file is a part of JuliaFEM.
|
||||
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
|
||||
|
||||
"""
|
||||
This module contains math stuff, including interpolation, integration, linearization, ...
|
||||
"""
|
||||
|
||||
using ForwardDiff
|
||||
|
||||
export interpolate, integrate, linearize
|
||||
|
||||
"""
|
||||
Interpolate field variable using basis functions f for point ip.
|
||||
This function tries to be as general as possible and allows interpolating
|
||||
lot of different fields.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
field :: Array{Number, dim}
|
||||
Field variable
|
||||
basis :: Function
|
||||
Basis functions
|
||||
ip :: Array{Number, 1}
|
||||
Point to interpolate
|
||||
"""
|
||||
function interpolate(field::Float64, basis::Function, ip::Array{Float64,1})
|
||||
# dummy function, unable to interpolate scalar value!
|
||||
return field
|
||||
end
|
||||
function interpolate{T<:Real}(field::Array{T,1}, basis::Function, ip)
|
||||
result = dot(field, basis(ip))
|
||||
return result
|
||||
end
|
||||
function interpolate{T<:Real}(field::Array{T,2}, basis::Function, ip)
|
||||
m, n = size(field)
|
||||
bip = basis(ip)
|
||||
tmp = size(bip)
|
||||
if length(tmp) == 1
|
||||
ndim = 1
|
||||
nnodes = tmp[1]
|
||||
else
|
||||
ndim, nnodes = size(bip)
|
||||
end
|
||||
if ndim == 1
|
||||
if n == nnodes
|
||||
result = field * bip
|
||||
elseif m == nnodes
|
||||
result = field' * bip
|
||||
end
|
||||
else
|
||||
if n == nnodes
|
||||
result = bip' * field
|
||||
elseif m == nnodes
|
||||
result = bip' * field'
|
||||
end
|
||||
end
|
||||
if length(result) == 1
|
||||
result = result[1]
|
||||
end
|
||||
return result
|
||||
end
|
||||
function interpolate(e::Element, field::ASCIIString, x::Array{Float64,1}; derivative=false)
|
||||
basis = derivative ? get_dbasisdxi(e) : get_basis(e)
|
||||
return interpolate(e.attributes[field], basis, x)
|
||||
end
|
||||
|
||||
|
||||
|
||||
"""
|
||||
Linearize function f w.r.t some given field, i.e. calculate dR/du
|
||||
|
||||
Parameters
|
||||
----------
|
||||
f::Function
|
||||
(possibly) nonlinear function to linearize
|
||||
field::ASCIIString
|
||||
field variable
|
||||
|
||||
Returns
|
||||
-------
|
||||
Array{Float64, 2}
|
||||
jacobian / "tangent stiffness matrix"
|
||||
|
||||
"""
|
||||
function linearize(f::Function, el::Element, field::ASCIIString)
|
||||
dim, nnodes = size(el.attributes[field])
|
||||
function helper!(x, y)
|
||||
orig = copy(el.attributes[field])
|
||||
el.attributes[field] = reshape(x, dim, nnodes)
|
||||
y[:] = f(el)
|
||||
el.attributes[field] = copy(orig)
|
||||
end
|
||||
jac = ForwardDiff.forwarddiff_jacobian(helper!, Float64, fadtype=:dual, n=dim*nnodes, m=dim*nnodes)
|
||||
return jac(el.attributes[field][:])
|
||||
end
|
||||
|
||||
"""
|
||||
This version returns another function which can be then evaluated against field
|
||||
"""
|
||||
function linearize(f::Function, field::ASCIIString)
|
||||
function jacobian(el::Element, args...)
|
||||
dim, nnodes = size(el.attributes[field])
|
||||
function helper!(x, y)
|
||||
orig = copy(el.attributes[field])
|
||||
el.attributes[field] = reshape(x, dim, nnodes)
|
||||
y[:] = f(el, args...)
|
||||
el.attributes[field] = copy(orig)
|
||||
end
|
||||
jac = ForwardDiff.forwarddiff_jacobian(helper!, Float64, fadtype=:dual, n=dim*nnodes, m=dim*nnodes)
|
||||
return jac(el.attributes[field][:])
|
||||
end
|
||||
return jacobian
|
||||
end
|
||||
|
||||
"""
|
||||
In-place version, no additional garbage collection.
|
||||
"""
|
||||
function linearize!(f::Function, el::Element, field::ASCIIString, target::ASCIIString)
|
||||
el.attributes[target][:] = 0.0
|
||||
dim, nnodes = size(el.attributes[field])
|
||||
function helper!(x, y)
|
||||
orig = copy(el.attributes[field])
|
||||
el.attributes[field] = reshape(x, dim, nnodes)
|
||||
y[:] = f(el)
|
||||
el.attributes[field] = copy(orig)
|
||||
end
|
||||
jac! = ForwardDiff.forwarddiff_jacobian!(helper!, Float64, fadtype=:dual, n=dim*nnodes, m=dim*nnodes)
|
||||
jac!(el.attributes[field][:], el.attributes[target])
|
||||
end
|
||||
|
||||
|
||||
|
||||
"""
|
||||
Integrate f over element using Gaussian quadrature rules.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
el::Element
|
||||
well defined element
|
||||
f::Function
|
||||
Function to integrate
|
||||
"""
|
||||
function integrate(f::Function, el::Element)
|
||||
target = []
|
||||
for ip in el.integration_points
|
||||
J = interpolate(el, "coordinates", ip.xi; derivative=true)
|
||||
push!(target, ip.weight*f(el, ip)*det(J))
|
||||
end
|
||||
return sum(target)
|
||||
end
|
||||
#function integrate(f::Function, integration_points::Array{IntegrationPoint, 1}, Xargs...)
|
||||
# target = []
|
||||
# for ip in integration_points
|
||||
# J = interpolate(el, "coordinates", ip.xi; derivative=true)
|
||||
# push!(target, ip.weight*f(ip, args...)*det(J))
|
||||
# end
|
||||
# return sum(target)
|
||||
#end
|
||||
|
||||
"""
|
||||
This version returns a function which must be operated with element e
|
||||
"""
|
||||
function integrate(f::Function)
|
||||
function integrate(el::Element)
|
||||
target = []
|
||||
for ip in el.integration_points
|
||||
J = interpolate(el, "coordinates", ip.xi; derivative=true)
|
||||
push!(target, ip.weight*f(el, ip)*det(J))
|
||||
end
|
||||
return sum(target)
|
||||
end
|
||||
return integrate
|
||||
end
|
||||
|
||||
"""
|
||||
This version saves results inplace to target, garbage collection free
|
||||
"""
|
||||
function integrate!(f::Function, el::Element, target)
|
||||
# set target to zero
|
||||
el.attributes[target][:] = 0.0
|
||||
for ip in el.integration_points
|
||||
J = interpolate(el, "coordinates", ip.xi; derivative=true)
|
||||
el.attributes[target][:,:] += ip.weight*f(el, ip)*det(J)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
# This file is a part of JuliaFEM.
|
||||
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
|
||||
|
||||
export IntegrationPoint, Element, Assembly, FunctionSpace
|
||||
|
||||
"""
|
||||
Integration point
|
||||
|
||||
xi :: Array{Float64, 1}
|
||||
(dimensionless) coordinates of integration point
|
||||
weight :: Float64
|
||||
Integration weight
|
||||
attributes :: Dict{ASCIIString, Any}
|
||||
This is used to save internal variables of IP needed e.g. for incremental
|
||||
material models.
|
||||
"""
|
||||
type IntegrationPoint
|
||||
xi :: Array{Float64, 1}
|
||||
weight :: Float64
|
||||
attributes :: Dict{ASCIIString, Any}
|
||||
end
|
||||
|
||||
type FunctionSpace
|
||||
basis :: Function
|
||||
dbasis :: Function
|
||||
end
|
||||
|
||||
abstract Element
|
||||
|
||||
#type Element
|
||||
# id :: Int
|
||||
# node_ids :: Array{Int, 1}
|
||||
# shape_functions :: FunctionSpace
|
||||
# integration_points :: Array{IntegrationPoint, 1}
|
||||
# attributes :: Dict{ASCIIString, Any}
|
||||
#end
|
||||
|
||||
|
||||
type Assembly
|
||||
# LHS
|
||||
I :: Array{Int64, 1}
|
||||
J :: Array{Int64, 1}
|
||||
A :: Array{Float64, 1}
|
||||
# RHS
|
||||
i :: Array{Int64, 1}
|
||||
b :: Array{Float64, 1}
|
||||
# global dofs for each element
|
||||
gdofs :: Dict{Int64, Array{Int64, 1}}
|
||||
end
|
||||
Assembly() = Assembly(Int64[], Int64[], Float64[], Int64[], Float64[], Dict{Int64,Array{Int64,1}}())
|
||||
Assembly(gdofs::Dict{Int64,Array{Int64,1}}) = Assembly(Int64[], Int64[], Float64[], Int64[], Float64[], gdofs)
|
||||
|
||||
+51
-22
@@ -1,17 +1,8 @@
|
||||
# This file is a part of JuliaFEM.
|
||||
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
|
||||
|
||||
module xdmf
|
||||
|
||||
using Logging
|
||||
@Logging.configure(level=INFO)
|
||||
|
||||
using LightXML
|
||||
|
||||
VERSION < v"0.4-" && using Docile
|
||||
|
||||
# i add docstrings later
|
||||
|
||||
# element codes: http://www.paraview.org/pipermail/paraview/2013-July/028859.html
|
||||
# > from ./VTK/ThirdParty/xdmf2/vtkxdmf2/libsrc/XdmfTopology.h
|
||||
# >
|
||||
@@ -84,29 +75,68 @@ function xdmf_new_grid(temporal_collection; time=0)
|
||||
return grid
|
||||
end
|
||||
|
||||
#function xdmf_new_mesh(grid, X, elmap)
|
||||
# geometry = new_child(grid, "Geometry")
|
||||
# set_attribute(geometry, "Type", "XYZ")
|
||||
# dataitem = new_child(geometry, "DataItem")
|
||||
# set_attribute(dataitem, "DataType", "Float")
|
||||
# set_attribute(dataitem, "Dimensions", length(X))
|
||||
# set_attribute(dataitem, "Format", "XML")
|
||||
# set_attribute(dataitem, "Precision", "4")
|
||||
# add_text(dataitem, join(X, " "))
|
||||
# topology = new_child(grid, "Topology")
|
||||
# set_attribute(topology, "Dimensions", "1")
|
||||
# set_attribute(topology, "Type", "Mixed")
|
||||
# dataitem = new_child(topology, "DataItem")
|
||||
# set_attribute(dataitem, "DataType", "Int")
|
||||
# set_attribute(dataitem, "Dimensions", length(elmap))
|
||||
# set_attribute(dataitem, "Format", "XML")
|
||||
# set_attribute(dataitem, "Precision", 4)
|
||||
# elmap2 = copy(elmap)
|
||||
# elmap2[2:end,:] -= 1
|
||||
# add_text(dataitem, join(elmap2, " "))
|
||||
#end
|
||||
|
||||
function xdmf_new_mesh(grid, X, elmap)
|
||||
dim, nnodes = size(X)
|
||||
geometry = new_child(grid, "Geometry")
|
||||
set_attribute(geometry, "Type", "XYZ")
|
||||
dataitem = new_child(geometry, "DataItem")
|
||||
set_attribute(dataitem, "DataType", "Float")
|
||||
set_attribute(dataitem, "Dimensions", length(X))
|
||||
set_attribute(dataitem, "Dimensions", "$nnodes $dim")
|
||||
set_attribute(dataitem, "Format", "XML")
|
||||
set_attribute(dataitem, "Precision", "4")
|
||||
add_text(dataitem, join(X, " "))
|
||||
set_attribute(dataitem, "Precision", 8)
|
||||
#add_text(dataitem, join(X, " "))
|
||||
s = "\n"
|
||||
|
||||
for i=1:nnodes
|
||||
s *= "\t\t" * join(X[:,i], " ") * "\n"
|
||||
end
|
||||
s *= " "
|
||||
add_text(dataitem, s)
|
||||
|
||||
topology = new_child(grid, "Topology")
|
||||
set_attribute(topology, "Dimensions", "1")
|
||||
set_attribute(topology, "Type", "Mixed")
|
||||
dataitem = new_child(topology, "DataItem")
|
||||
set_attribute(dataitem, "DataType", "Int")
|
||||
set_attribute(dataitem, "Dimensions", length(elmap))
|
||||
set_attribute(dataitem, "Format", "XML")
|
||||
set_attribute(dataitem, "Precision", 4)
|
||||
elmap2 = copy(elmap)
|
||||
elmap2[2:end,:] -= 1
|
||||
add_text(dataitem, join(elmap2, " "))
|
||||
dim, nelements = size(elmap2)
|
||||
|
||||
topology = new_child(grid, "Topology")
|
||||
#set_attribute(topology, "Dimensions", "1")
|
||||
set_attribute(topology, "TopologyType", "Mixed")
|
||||
set_attribute(topology, "NumberOfElements", nelements)
|
||||
dataitem = new_child(topology, "DataItem")
|
||||
set_attribute(dataitem, "DataType", "Int")
|
||||
set_attribute(dataitem, "Dimensions", "$nelements $dim")
|
||||
set_attribute(dataitem, "Format", "XML")
|
||||
set_attribute(dataitem, "Precision", 8)
|
||||
s = "\n"
|
||||
for i=1:nelements
|
||||
s *= "\t\t" * join(elmap2[:,i], " ") * "\n"
|
||||
end
|
||||
add_text(dataitem, s)
|
||||
#add_text(dataitem, join(elmap2, " "))
|
||||
end
|
||||
|
||||
|
||||
function xdmf_new_field(grid, name, source, data)
|
||||
loc = Dict("elements" => "Cell",
|
||||
"nodes" => "Node")
|
||||
@@ -149,4 +179,3 @@ function xdmf_save_model(xdoc, filename)
|
||||
save_file(xdoc, filename)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user