rewrite assembly, see #69. a lot of tests probably fail but the most important ones pass

This commit is contained in:
Jukka Aho
2015-11-12 21:54:46 +02:00
parent c6fe18c15c
commit 6ae28fc689
12 changed files with 317 additions and 370 deletions
+67 -84
View File
@@ -6,25 +6,27 @@ module ElementTests
using JuliaFEM.Test
using JuliaFEM
using JuliaFEM: Equation, Quad4, IntegrationPoint, initialize_local_assembly,
get_element, get_basis, grad, calculate_local_assembly!,
PlaneHeatProblem, Seg2, HeatEquation, Problem, solve!
using JuliaFEM: Equation, Quad4, IntegrationPoint, Assembly, assemble!,
get_element, get_basis, grad, get_unknown_field_name,
PlaneHeatProblem, Seg2, Problem, solve!,
get_default_integration_points, Equation
abstract MyEquation <: Equation
""" Diffusive heat transfer for 4-node bilinear element, with a nonlinear source term. """
type DC2D4NL <: Equation
element :: Quad4
integration_points :: Array{IntegrationPoint, 1}
function JuliaFEM.get_unknown_field_name(equation::MyEquation)
return "temperature"
end
function DC2D4NL(element::Quad4, initial_temperature=zeros(4))
integration_points = [
IntegrationPoint(1.0/sqrt(3.0)*[-1, -1], 1.0),
IntegrationPoint(1.0/sqrt(3.0)*[ 1, -1], 1.0),
IntegrationPoint(1.0/sqrt(3.0)*[ 1, 1], 1.0),
IntegrationPoint(1.0/sqrt(3.0)*[-1, 1], 1.0)]
""" Diffusive heat transfer for 4-node bilinear element, with a nonlinear source term. """
type DC2D4NL <: MyEquation
element :: Quad4
integration_points :: Vector{IntegrationPoint}
end
function DC2D4NL(element::Quad4)
integration_points = get_default_integration_points(element)
if !haskey(element, "temperature")
element["temperature"] = initial_temperature
element["temperature"] = zeros(4)
end
DC2D4NL(element, integration_points)
end
@@ -34,17 +36,15 @@ function Base.size(equation::DC2D4NL)
end
""" Nonlinear flux term. """
type DC2D2NL <: Equation
type DC2D2NL <: MyEquation
element :: Seg2
integration_points :: Array{IntegrationPoint, 1}
integration_points :: Vector{IntegrationPoint}
end
function DC2D2NL(element::Seg2, initial_temperature=zeros(2))
#integration_points = [
# IntegrationPoint([0.0], 2.0)]
function DC2D2NL(element::Seg2)
integration_points = JuliaFEM.line5()
if !haskey(element, "temperature")
element["temperature"] = initial_temperature
element["temperature"] = zeros(2)
end
DC2D2NL(element, integration_points)
end
@@ -63,34 +63,23 @@ function JuliaFEM.get_potential_energy(equation::DC2D4NL, ip, time; variation=no
c = basis("temperature nonlinearity coefficient", ip, time)
gradT = grad(basis)("temperature", ip, time, variation)
Wint = (k + c*T) * 1/2*vecdot(gradT, gradT)
#Wint = k*1/2*vecdot(gradT, gradT)
Wext = f*T
#Wext = 0.0
return Wint - Wext
end
function JuliaFEM.has_potential_energy(eq::DC2D4NL)
return true
end
function JuliaFEM.get_potential_energy(equation::DC2D2NL, ip, time; variation=nothing)
element = get_element(equation)
basis = get_basis(element)
T = basis("temperature", ip, time, variation)[1]
Wint = 0.0
sig = 5.7e-8
eps = basis("emissivity", ip, time)[1]
T_ext = basis("temperature external", ip, time)[1]
q0 = eps*sig*((T_ext+273.15)^4 - (T+273.15)^4)
coeff = basis("temperature coefficient", ip, time)[1]
q0 = coeff*(T_ext^4 - T^4)
Wint = 0.0
Wext = q0*T
W = Wint - Wext
return W
end
function JuliaFEM.has_potential_energy(eq::DC2D2NL)
return true
end
function test_potential_energy_method()
# create model -- start
@@ -99,36 +88,37 @@ function test_potential_energy_method()
element["temperature thermal conductivity"] = 6.0
element["temperature load"] = [0.0, 0.0, 0.0, 0.0]
element["temperature nodal load"] = [3.0, 3.0, 0.0, 0.0]
element["temperature nonlinearity coefficient"] = [6.0, 6.0, 6.0, 6.0]
element["temperature nonlinearity coefficient"] = 6.0
equation = DC2D4NL(element)
# create model -- end
la = initialize_local_assembly() # create workspace for local matrices
ass = Assembly()
info("unknown field name: $(get_unknown_field_name(equation))")
T = zeros(4) # create workspace for solution vector
dT = zeros(4) #
fd = [1, 2] # free dofs
tic()
# start loops, in principle solve ∂r(u)/∂uΔu = -r(u) and update.
for i=1:10
calculate_local_assembly!(la, equation, "temperature") # calculate local matrices
dT[fd] = la.stiffness_matrix[fd,fd] \ la.force_vector[fd]
empty!(ass)
assemble!(ass, equation) # calculate local matrices
dT[fd] = full(ass.stiffness_matrix)[fd,fd] \ full(ass.force_vector)[fd]
T += dT
push!(element["temperature"], T) # add new increment to model
info("T = $T")
@printf("increment %2d, |du| = %8.5f\n", i, norm(dT))
err = last(element["temperature"])[1] - 2/3
isapprox(err, 0.0) && break
end
toc()
err = last(element["temperature"])[1] - 2/3
info("error: $err")
@test isapprox(err, 0.0)
end
type TestProblem <: Problem
unknown_field_name :: ASCIIString
unknown_field_dimension :: Int
equations :: Array{Equation, 1}
equations :: Vector{Equation}
element_mapping :: Dict{DataType, DataType}
end
@@ -143,55 +133,48 @@ function test_potential_energy_method_2()
# create model -- start
N = Vector[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 1.0]]
element = Quad4([1, 2, 3, 4])
element["geometry"] = Vector[N[1], N[2], N[3], N[4]]
element["temperature thermal conductivity"] = 6.0
element["temperature load"] = [0.0, 0.0, 0.0, 0.0]
element["temperature nonlinearity coefficient"] = [0.0, 0.0, 0.0, 0.0]
#equation1 = DC2D4NL(element, initial_temperature=ones(4))
equation1 = DC2D4NL(element)
element1 = Quad4([1, 2, 3, 4])
element1["geometry"] = Vector[N[1], N[2], N[3], N[4]]
element1["temperature thermal conductivity"] = 6.0
element1["temperature load"] = [0.0, 0.0, 0.0, 0.0]
element1["temperature nonlinearity coefficient"] = [0.0, 0.0, 0.0, 0.0]
element1["temperature"] = ones(4)
boundary_element = Seg2([1, 2])
boundary_element["geometry"] = Vector[N[1], N[2]]
boundary_element["emissivity"] = 0.5
boundary_element["temperature external"] = 10.0
#equation2 = DC2D2NL(boundary_element, initial_temperature=ones(4))
equation2 = DC2D2NL(boundary_element)
element2 = Seg2([1, 2])
element2["geometry"] = Vector[N[1], N[2]]
element2["temperature coefficient"] = 3.0e-8 # ~ 5.7e-8 * 0.5
element2["temperature external"] = 100.0
element2["temperature"] = ones(2)
# create model -- end
equation1 = DC2D4NL(element1)
equation2 = DC2D2NL(element2)
ass = Assembly()
info("unknown field name: $(get_unknown_field_name(equation1))")
element["temperature"] = ones(4)
boundary_element["temperature"] = ones(2)
equations = [equation1, equation2]
la = initialize_local_assembly() # create workspace for local matrices
T = zeros(4) # create workspace for solution vector
dT = zeros(4) #
fd = [1, 2] # free dofs
info("equation 1")
calculate_local_assembly!(la, equation1, "temperature")
info("stiffness matrix: $(la.stiffness_matrix)")
# info("force vector: $(la.force_vector)")
info("equation 2")
calculate_local_assembly!(la, equation2, "temperature")
# info("stiffness matrix: $(la.stiffness_matrix)")
info("force vector: $(la.force_vector)")
# start loops, in principle solve ∂r(u)/∂uΔu = -r(u) and update.
for i=1:10
empty!(ass)
assemble!(ass, equation1)
assemble!(ass, equation2)
dT[fd] = full(ass.stiffness_matrix)[fd,fd] \ full(ass.force_vector)[fd]
T += dT
push!(element1["temperature"], T)
push!(element2["temperature"], T[fd])
@printf("increment %2d, |du| = %8.5f\n", i, norm(dT))
err = last(element1["temperature"])[1] - 0.5
isapprox(err, 0.0) && break
end
info("Creating problem")
#problem = PlaneHeatProblem("temperature", 1, equations, Dict())
problem = TestProblem(equations)
free_dofs = [1, 2]
tic()
solve!(problem, free_dofs; max_iterations=10)
toc()
temp = get_basis(boundary_element)("temperature", [0.0])[1]
info("temperature = $temp")
#err = last(element["temperature"])[1] - 2/3
#info("error: $err")
# 0.3888756709834147 tulee jostakin syysta...
# tai -0.39411350336960116
info(boundary_element["temperature"])
@test isapprox(temp, 2.93509690572300E+00) # tested using Code Aster
err = last(element1["temperature"])[1] - 0.5
info("error: $err")
@test isapprox(err, 0.0)
# @test isapprox(temp, 2.93509690572300E+00) # tested using Code Aster
end
end