2015-10-09 23:45:28 +03:00
|
|
|
|
# This file is a part of JuliaFEM.
|
|
|
|
|
|
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
|
|
|
|
|
|
|
|
|
|
|
|
# Heat problems
|
|
|
|
|
|
|
2015-10-28 04:29:14 +02:00
|
|
|
|
""" Heat equations.
|
|
|
|
|
|
|
|
|
|
|
|
Formulation
|
|
|
|
|
|
-----------
|
|
|
|
|
|
|
|
|
|
|
|
Field equation is:
|
|
|
|
|
|
|
|
|
|
|
|
ρc∂u/∂t = ∇⋅(k∇u) + f
|
|
|
|
|
|
|
|
|
|
|
|
Weak form is: find u∈U such that ∀v in V
|
|
|
|
|
|
|
|
|
|
|
|
∫k∇u∇v dx = ∫fv dx + ∫gv ds,
|
|
|
|
|
|
|
|
|
|
|
|
where
|
|
|
|
|
|
|
2016-06-17 02:10:17 +03:00
|
|
|
|
k = temperature thermal conductivity defined on volume elements
|
|
|
|
|
|
f = temperature load defined on volume elements
|
|
|
|
|
|
g = temperature flux defined on boundary elements
|
2015-10-28 04:29:14 +02:00
|
|
|
|
|
2016-07-01 02:55:56 +03:00
|
|
|
|
Parameters
|
|
|
|
|
|
----------
|
|
|
|
|
|
temperature thermal conductivity
|
|
|
|
|
|
temperature load
|
|
|
|
|
|
temperature flux
|
|
|
|
|
|
|
|
|
|
|
|
thermal conductivity
|
|
|
|
|
|
heat source
|
|
|
|
|
|
heat flux
|
|
|
|
|
|
heat transfer coefficient
|
|
|
|
|
|
external temperature
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Formulations
|
|
|
|
|
|
------------
|
|
|
|
|
|
1D, 2D, 3D
|
|
|
|
|
|
|
2015-10-28 04:29:14 +02:00
|
|
|
|
References
|
|
|
|
|
|
----------
|
|
|
|
|
|
https://en.wikipedia.org/wiki/Heat_equation
|
2016-07-01 02:55:56 +03:00
|
|
|
|
https://en.wikipedia.org/wiki/Heat_capacity
|
|
|
|
|
|
https://en.wikipedia.org/wiki/Thermal_conduction
|
|
|
|
|
|
https://en.wikipedia.org/wiki/Thermal_conductivity
|
|
|
|
|
|
https://en.wikipedia.org/wiki/Thermal_diffusivity
|
|
|
|
|
|
https://en.wikipedia.org/wiki/Volumetric_heat_capacity
|
2015-10-28 04:29:14 +02:00
|
|
|
|
"""
|
2016-06-17 02:10:17 +03:00
|
|
|
|
type Heat <: FieldProblem
|
2016-07-01 02:55:56 +03:00
|
|
|
|
formulation :: ASCIIString
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function Heat()
|
|
|
|
|
|
return Heat("3D")
|
2016-06-17 02:10:17 +03:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function get_unknown_field_name(problem::Problem{Heat})
|
|
|
|
|
|
return "temperature"
|
|
|
|
|
|
end
|
|
|
|
|
|
|
2016-07-01 02:55:56 +03:00
|
|
|
|
function assemble!(assembly::Assembly, problem::Problem{Heat}, element::Element, time=0.0)
|
|
|
|
|
|
formulation = Val{Symbol(problem.properties.formulation)}
|
|
|
|
|
|
assemble!(assembly, problem, element, time, formulation)
|
2016-06-17 02:10:17 +03:00
|
|
|
|
end
|
|
|
|
|
|
|
2016-07-01 02:55:56 +03:00
|
|
|
|
# 3d heat problems
|
|
|
|
|
|
|
|
|
|
|
|
function assemble!{E}(assembly::Assembly, problem::Problem{Heat}, element::Element{E}, time, ::Type{Val{Symbol("3D")}})
|
|
|
|
|
|
info("Unknown element type $E for 3d heat problem!")
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
typealias Heat3DVolumeElements Union{Tet4, Tet10, Hex8}
|
|
|
|
|
|
typealias Heat3DSurfaceElements Union{Tri3, Tri6, Quad4}
|
|
|
|
|
|
|
|
|
|
|
|
function assemble!{E<:Heat3DVolumeElements}(assembly::Assembly, problem::Problem{Heat}, element::Element{E}, time, ::Type{Val{Symbol("3D")}})
|
|
|
|
|
|
gdofs = get_gdofs(problem, element)
|
|
|
|
|
|
field_name = get_unknown_field_name(problem)
|
|
|
|
|
|
nnodes = length(element)
|
|
|
|
|
|
K = zeros(nnodes, nnodes)
|
|
|
|
|
|
fq = zeros(nnodes)
|
|
|
|
|
|
for ip in get_integration_points(element)
|
|
|
|
|
|
detJ = element(ip, time, Val{:detJ})
|
|
|
|
|
|
w = ip.weight*detJ
|
|
|
|
|
|
N = element(ip, time)
|
|
|
|
|
|
if haskey(element, "$field_name thermal conductivity")
|
|
|
|
|
|
dN = element(ip, time, Val{:Grad})
|
|
|
|
|
|
k = element("$field_name thermal conductivity", ip, time)
|
|
|
|
|
|
K += w*k*dN'*dN
|
|
|
|
|
|
end
|
|
|
|
|
|
if haskey(element, "$field_name load")
|
|
|
|
|
|
f = element("$field_name load", ip, time)
|
|
|
|
|
|
fq += w*N'*f
|
|
|
|
|
|
end
|
|
|
|
|
|
end
|
|
|
|
|
|
T = vec(element[field_name](time))
|
|
|
|
|
|
fq -= K*T
|
|
|
|
|
|
add!(assembly.K, gdofs, gdofs, K)
|
|
|
|
|
|
add!(assembly.f, gdofs, fq)
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function assemble!{E<:Heat3DSurfaceElements}(assembly::Assembly, problem::Problem{Heat}, element::Element{E}, time, ::Type{Val{Symbol("3D")}})
|
|
|
|
|
|
gdofs = get_gdofs(problem, element)
|
|
|
|
|
|
field_name = get_unknown_field_name(problem)
|
|
|
|
|
|
nnodes = length(element)
|
|
|
|
|
|
K = zeros(nnodes, nnodes)
|
|
|
|
|
|
fq = zeros(nnodes)
|
|
|
|
|
|
for ip in get_integration_points(element)
|
|
|
|
|
|
detJ = element(ip, time, Val{:detJ})
|
|
|
|
|
|
w = ip.weight*detJ
|
|
|
|
|
|
N = element(ip, time)
|
|
|
|
|
|
if haskey(element, "$field_name flux")
|
|
|
|
|
|
q = element("$field_name flux", ip, time)
|
|
|
|
|
|
fq += w*N'*q
|
|
|
|
|
|
end
|
|
|
|
|
|
if haskey(element, "$field_name heat transfer coefficient")
|
|
|
|
|
|
h = element("$field_name heat transfer coefficient", ip, time)
|
|
|
|
|
|
Tu = element("$field_name external temperature", ip, time)
|
|
|
|
|
|
K += w*h*N'*N
|
|
|
|
|
|
fq += w*N'*h*Tu
|
|
|
|
|
|
end
|
|
|
|
|
|
end
|
|
|
|
|
|
T = vec(element[field_name](time))
|
|
|
|
|
|
fq -= K*T
|
|
|
|
|
|
add!(assembly.K, gdofs, gdofs, K)
|
|
|
|
|
|
add!(assembly.f, gdofs, fq)
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
# 2d heat problems
|
|
|
|
|
|
|
|
|
|
|
|
function assemble!{E}(assembly::Assembly, problem::Problem{Heat}, element::Element{E}, time, ::Type{Val{Symbol("2D")}})
|
|
|
|
|
|
info("Unknown element type $E for 2d heat problem!")
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
typealias Heat2DVolumeElements Union{Tri3, Tri6, Quad4}
|
|
|
|
|
|
typealias Heat2DSurfaceElements Union{Seg2, Seg3}
|
|
|
|
|
|
|
|
|
|
|
|
function assemble!{E<:Heat2DVolumeElements}(assembly::Assembly, problem::Problem{Heat}, element::Element{E}, time, ::Type{Val{Symbol("2D")}})
|
2016-06-08 23:42:36 +03:00
|
|
|
|
gdofs = get_gdofs(problem, element)
|
2016-06-19 20:01:37 +03:00
|
|
|
|
field_name = get_unknown_field_name(problem)
|
|
|
|
|
|
nnodes = length(element)
|
|
|
|
|
|
K = zeros(nnodes, nnodes)
|
|
|
|
|
|
fq = zeros(nnodes)
|
2015-11-27 10:10:00 +02:00
|
|
|
|
for ip in get_integration_points(element)
|
2016-06-08 23:42:36 +03:00
|
|
|
|
detJ = element(ip, time, Val{:detJ})
|
|
|
|
|
|
w = ip.weight*detJ
|
2015-11-27 10:10:00 +02:00
|
|
|
|
N = element(ip, time)
|
2016-06-19 20:01:37 +03:00
|
|
|
|
if haskey(element, "$field_name thermal conductivity")
|
2016-06-08 23:42:36 +03:00
|
|
|
|
dN = element(ip, time, Val{:Grad})
|
2016-06-19 20:01:37 +03:00
|
|
|
|
k = element("$field_name thermal conductivity", ip, time)
|
|
|
|
|
|
K += w*k*dN'*dN
|
2015-10-28 04:29:14 +02:00
|
|
|
|
end
|
2016-06-19 20:01:37 +03:00
|
|
|
|
if haskey(element, "$field_name load")
|
|
|
|
|
|
f = element("$field_name load", ip, time)
|
|
|
|
|
|
fq += w*N'*f
|
2015-10-28 04:29:14 +02:00
|
|
|
|
end
|
2016-07-01 02:55:56 +03:00
|
|
|
|
end
|
|
|
|
|
|
T = vec(element[field_name](time))
|
|
|
|
|
|
fq -= K*T
|
|
|
|
|
|
add!(assembly.K, gdofs, gdofs, K)
|
|
|
|
|
|
add!(assembly.f, gdofs, fq)
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function assemble!{E<:Heat2DSurfaceElements}(assembly::Assembly, problem::Problem{Heat}, element::Element{E}, time, ::Type{Val{Symbol("2D")}})
|
|
|
|
|
|
gdofs = get_gdofs(problem, element)
|
|
|
|
|
|
field_name = get_unknown_field_name(problem)
|
|
|
|
|
|
nnodes = length(element)
|
|
|
|
|
|
K = zeros(nnodes, nnodes)
|
|
|
|
|
|
fq = zeros(nnodes)
|
|
|
|
|
|
for ip in get_integration_points(element)
|
|
|
|
|
|
detJ = element(ip, time, Val{:detJ})
|
|
|
|
|
|
w = ip.weight*detJ
|
|
|
|
|
|
N = element(ip, time)
|
2016-06-19 20:01:37 +03:00
|
|
|
|
if haskey(element, "$field_name flux")
|
|
|
|
|
|
g = element("$field_name flux", ip, time)
|
|
|
|
|
|
fq += w*N'*g
|
2015-10-28 04:29:14 +02:00
|
|
|
|
end
|
|
|
|
|
|
end
|
2016-06-19 20:01:37 +03:00
|
|
|
|
T = vec(element[field_name](time))
|
|
|
|
|
|
fq -= K*T
|
|
|
|
|
|
add!(assembly.K, gdofs, gdofs, K)
|
|
|
|
|
|
add!(assembly.f, gdofs, fq)
|
2015-10-28 04:29:14 +02:00
|
|
|
|
end
|
|
|
|
|
|
|