removed Equation type from code

This commit is contained in:
Jukka Aho
2015-11-27 10:10:00 +02:00
parent f5afcf2057
commit ef667e8f34
23 changed files with 730 additions and 1817 deletions
+132
View File
@@ -0,0 +1,132 @@
# This file is a part of JuliaFEM.
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
module DirectSolverTests
using JuliaFEM.Test
using JuliaFEM
using JuliaFEM: Seg2, Quad4
using JuliaFEM: PlaneStressElasticityProblem, DirichletProblem
using JuliaFEM: DirectSolver
function test_solver_multiple_dirichlet_bc()
N = Vector[[0.0, 0.0], [1.0, 0.0], [0.0, 1.0], [1.0, 1.0]]
e1 = Quad4([1, 2, 4, 3])
e1["geometry"] = Vector[N[1], N[2], N[4], N[3]]
e1["youngs modulus"] = 900.0
e1["poissons ratio"] = 0.25
b1 = Seg2([3, 4])
b1["geometry"] = Vector[N[3], N[4]]
b1["displacement traction force"] = Vector[[0.0, -100.0], [0.0, -100.0]]
problem = PlaneStressElasticityProblem()
push!(problem, e1)
push!(problem, b1)
# manually solve problem 1
# free_dofs = [3, 5, 6, 8]
# free_dofs = [3, 6, 7, 8]
#solve!(problem, free_dofs, 0.0; max_iterations=10)
#disp = e1("displacement", [1.0, 1.0], 0.0)
#info("displacement at tip: $disp")
#@test isapprox(disp, [3.17431158889468E-02, -1.38591518927826E-01])
# boundary elements for dirichlet dx=0
dx = Seg2([1, 3])
dx["geometry"] = Vector[N[1], N[3]]
dx["displacement 1"] = 0.0
# boundary elements for dirichlet dy=0
dy = Seg2([1, 2])
dy["geometry"] = Vector[N[1], N[2]]
dy["displacement 2"] = 0.0
problem2 = DirichletProblem("displacement", 2)
push!(problem2, dx)
problem3 = DirichletProblem("displacement", 2)
push!(problem3, dy)
solver = DirectSolver()
push!(solver, problem)
push!(solver, problem2)
push!(solver, problem3)
# launch solver
norm = solver(0.0)
disp = e1("displacement", [1.0, 1.0], 0.0)
info("displacement at tip: $disp")
@test isapprox(disp, [3.17431158889468E-02, -1.38591518927826E-01])
end
function test_solver_multiple_bodies_multiple_dirichlet_bc()
N = Vector[
[0.0, 0.0], [1.0, 0.0],
[0.0, 1.0], [1.0, 1.0],
[0.0, 2.0], [1.0, 2.0]]
e1 = Quad4([1, 2, 4, 3])
e1["geometry"] = Vector[N[1], N[2], N[4], N[3]]
e2 = Quad4([3, 4, 6, 5])
e2["geometry"] = Vector[N[3], N[4], N[6], N[5]]
for el in [e1, e2]
el["youngs modulus"] = 900.0
el["poissons ratio"] = 0.25
end
b1 = Seg2([5, 6])
b1["geometry"] = Vector[N[5], N[6]]
b1["displacement traction force"] = Vector[[0.0, -100.0], [0.0, -100.0]]
body1 = PlaneStressElasticityProblem()
push!(body1, e1)
body2 = PlaneStressElasticityProblem()
push!(body2, e2)
push!(body2, b1)
# boundary elements for dirichlet dx=0
dx1 = Seg2([1, 3])
dx1["geometry"] = Vector[N[1], N[3]]
dx2 = Seg2([3, 5])
dx2["geometry"] = Vector[N[3], N[5]]
for dx in [dx1, dx2]
dx["displacement 1"] = 0.0
end
boundary1 = DirichletProblem("displacement", 2)
push!(boundary1, dx1)
push!(boundary1, dx2)
# boundary elements for dirichlet dy=0
dy1 = Seg2([1, 2])
dy1["geometry"] = Vector[N[1], N[2]]
dy1["displacement 2"] = 0.0
boundary2 = DirichletProblem("displacement", 2)
push!(boundary2, dy1)
solver = DirectSolver()
push!(solver, body1)
push!(solver, body2)
push!(solver, boundary1)
push!(solver, boundary2)
# launch solver
norm = solver(0.0)
disp = e2("displacement", [1.0, 1.0], 0.0)
info("displacement at tip: $disp")
# code aster verification, two_elements.comm
@test isapprox(disp, [3.17431158889468E-02, -2.77183037855653E-01])
end
# test_solver_multiple_bodies_multiple_dirichlet_bc()
end
+4 -7
View File
@@ -5,7 +5,7 @@ module TestDirichletBoundaryCondition
using JuliaFEM.Test
using JuliaFEM
using JuliaFEM: Seg2, DirichletProblem, Assembly, assemble!
using JuliaFEM: Seg2, DirichletProblem, Assembly, assemble
function test_dirichlet_problem_1_dim()
element = Seg2([1, 2])
@@ -13,8 +13,7 @@ function test_dirichlet_problem_1_dim()
element["temperature"] = 0.0
problem = DirichletProblem("temperature", 1)
push!(problem, element)
assembly = Assembly()
assemble!(assembly, problem)
assembly = assemble(problem, 0.0)
A = full(assembly.stiffness_matrix)
b = full(assembly.force_vector)
@test isapprox(A, 1/6*[2 1; 1 2])
@@ -27,8 +26,7 @@ function test_dirichlet_problem_2_dim()
element["displacement"] = 0.0
problem = DirichletProblem("displacement", 2)
push!(problem, element)
assembly = Assembly()
assemble!(assembly, problem)
assembly = assemble(problem, 0.0)
A = full(assembly.stiffness_matrix)
b = full(assembly.force_vector)
A_expected = 1/6*[2 0 1 0; 0 2 0 1; 1 0 2 0; 0 1 0 2]
@@ -42,8 +40,7 @@ function test_dirichlet_problem_2_dim_single_dof_fixed()
element["displacement 2"] = 0.0
problem = DirichletProblem("displacement", 2)
push!(problem, element)
assembly = Assembly()
assemble!(assembly, problem)
assembly = assemble(problem, 0.0)
A = full(assembly.stiffness_matrix)
b = full(assembly.force_vector)
info(b)
+8 -7
View File
@@ -4,9 +4,7 @@
module ElasticityTests
using JuliaFEM.Test
using JuliaFEM: Seg2, Quad4, Field, FieldSet, CPS4,
get_basis, solve!,
PlaneStressElasticityProblem
using JuliaFEM: Seg2, Quad4, PlaneStressElasticityProblem, solve!
function test_elasticity_volume_load()
element = Quad4([1, 2, 3, 4])
@@ -14,11 +12,13 @@ function test_elasticity_volume_load()
element["youngs modulus"] = 500.0
element["poissons ratio"] = 0.3
element["displacement load"] = Vector[[0.0, -10.0], [0.0, -10.0], [0.0, -10.0], [0.0, -10.0]]
free_dofs = [3, 4, 5, 6]
element["displacement"] = (0.0 => Vector{Float64}[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]])
problem = PlaneStressElasticityProblem()
push!(problem, element)
free_dofs = [3, 4, 5, 6]
solve!(problem, free_dofs, 0.0; max_iterations=10)
disp = get_basis(element)("displacement", [1.0, 1.0], 0.0)
disp = element("displacement", [1.0, 1.0], 0.0)
info("displacement at tip: $disp")
# verified using Code Aster.
@test isapprox(disp[2], -8.77303119819776)
@@ -31,9 +31,12 @@ function test_elasticity_surface_load()
element1["geometry"] = Vector[N[1], N[2], N[4], N[3]]
element1["youngs modulus"] = 900.0
element1["poissons ratio"] = 0.25
element1["displacement"] = (0.0 => Vector{Float64}[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]])
element2 = Seg2([3, 4])
element2["geometry"] = Vector[N[3], N[4]]
element2["displacement traction force"] = Vector[[0.0, -100.0], [0.0, -100.0]]
element2["displacement"] = (0.0 => Vector{Float64}[[0.0, 0.0], [0.0, 0.0]])
#free_dofs = [3, 5, 6, 8]
free_dofs = [3, 6, 7, 8]
@@ -41,8 +44,6 @@ function test_elasticity_surface_load()
push!(problem, element1)
push!(problem, element2)
solve!(problem, free_dofs, 0.0; max_iterations=10)
#disp = get_basis(element1)("displacement", [1.0, 1.0], 1.0)[2]
info(last(element1["displacement"]))
disp = element1("displacement", [1.0, 1.0], 0.0)
info("displacement at tip: $disp")
# verified using Code Aster.
+10 -12
View File
@@ -7,8 +7,7 @@ module HeatTests # always wrap tests to module ending with "Tests"
using JuliaFEM.Test # always use JuliaFEM.Test, not Base.Test
using JuliaFEM: HeatEquation
using JuliaFEM: Seg2, Quad4, DC2D4, DC2D2, Assembly, assemble!
using JuliaFEM: Seg2, Quad4, HeatProblem, assemble
function test_one_element() # always start test function with name test_
@@ -26,11 +25,13 @@ function test_one_element() # always start test function with name test_
# linear ramp from 0 to 6 in time 0 to 1
boundary_element["temperature flux"] = (0.0 => 0.0, 1.0 => 6.0)
problem = HeatProblem()
push!(problem, element)
push!(problem, boundary_element)
# Set constant source f=12 with k=6. Accurate solution is
# T=1 on free boundary, u(x,y) = -1/6*(1/2*f*x^2 - f*x)
equation = convert(HeatEquation, element)
assembly = Assembly()
assemble!(assembly, equation)
assembly = assemble(problem, 0.0)
fdofs = [1, 2]
A = full(assembly.stiffness_matrix)
b = full(assembly.force_vector)
@@ -38,18 +39,15 @@ function test_one_element() # always start test function with name test_
# Set constant flux g=6 on boundary. Accurate solution is
# u(x,y) = x which equals T=1 on boundary.
boundary_equation = convert(HeatEquation, boundary_element)
empty!(assembly)
time = 1.0
assemble!(assembly, equation, time)
assemble!(assembly, boundary_equation, time)
# at time t=1.0 all loads should be on.
assembly = assemble(problem, 1.0)
A = full(assembly.stiffness_matrix)
b = full(assembly.force_vector)
T = A[fdofs, fdofs] \ b[fdofs]
info("T = $T")
@test isapprox(T, [2.0, 2.0]) # always use @test to test things.
@test isapprox(T, [2.0, 2.0])
end
end
+31 -69
View File
@@ -3,73 +3,43 @@
module ElementTests
using JuliaFEM
using JuliaFEM.Test
using JuliaFEM
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
using JuliaFEM: AbstractProblem, Problem
using JuliaFEM: Element, Seg2, Quad4
using JuliaFEM: IntegrationPoint, solve!
abstract MyEquation <: Equation
abstract HeatProblem <: AbstractProblem
function JuliaFEM.get_unknown_field_name(equation::MyEquation)
function HeatProblem(dim::Int=1, elements=[])
return Problem{HeatProblem}(dim, elements)
end
function JuliaFEM.get_unknown_field_name{P<:HeatProblem}(::Type{P})
return "temperature"
end
""" Diffusive heat transfer for 4-node bilinear element, with a nonlinear source term. """
type DC2D4NL <: MyEquation
element :: Quad4
integration_points :: Vector{IntegrationPoint}
function JuliaFEM.get_unknown_field_type{P<:HeatProblem}(::Type{P})
return Float64
end
function Base.size(equation::DC2D4NL)
return (1, 4)
end
""" Nonlinear flux term. """
type DC2D2NL <: MyEquation
element :: Seg2
integration_points :: Vector{IntegrationPoint}
end
function Base.size(equation::DC2D2NL)
return (1, 2)
end
function Base.convert(::Type{MyEquation}, element::Quad4)
integration_points = get_default_integration_points(element)
haskey(element, "temperature") || (element["temperature"] = 0.0 => zeros(4))
DC2D4NL(element, integration_points)
end
function Base.convert(::Type{MyEquation}, element::Seg2)
integration_points = JuliaFEM.line5()
haskey(element, "temperature") || (element["temperature"] = 0.0 => zeros(2))
DC2D2NL(element, integration_points)
end
""" Calculate a potential Π = Wint - Wext of system. """
function JuliaFEM.get_potential_energy(equation::DC2D4NL, ip, time; variation=nothing)
element = get_element(equation)
basis = get_basis(element)
k = basis("temperature thermal conductivity", ip, time)
f = basis("temperature load", ip, time)
T = basis("temperature", ip, time, variation)
c = basis("temperature nonlinearity coefficient", ip, time)
gradT = grad(basis)("temperature", ip, time, variation)
function JuliaFEM.get_potential_energy(problem::Problem{HeatProblem}, element::Element{Quad4}, ip::IntegrationPoint, time::Number; variation=nothing)
k = element("temperature thermal conductivity", ip, time)
f = element("temperature load", ip, time)
T = element("temperature", ip, time, variation)
c = element("temperature nonlinearity coefficient", ip, time)
gradT = element("temperature", ip, time, Val{:grad}, variation)
Wint = (k + c*T) * 1/2*vecdot(gradT, gradT)
Wext = f*T
return Wint - Wext
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]
T_ext = basis("temperature external", ip, time)[1]
coeff = basis("temperature coefficient", ip, time)[1]
function JuliaFEM.get_potential_energy(problem::Problem{HeatProblem}, element::Element{Seg2}, ip::IntegrationPoint, time::Number; variation=nothing)
T = element("temperature", ip, time, variation)[1]
T_ext = element("temperature external", ip, time)[1]
coeff = element("temperature coefficient", ip, time)[1]
q0 = coeff*(T_ext^4 - T^4)
Wint = 0.0
Wext = q0*T
@@ -86,28 +56,19 @@ function test_potential_energy_method()
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
equation = convert(MyEquation, element)
element["temperature"] = (0.0 => zeros(Float64, 4))
problem = HeatProblem()
push!(problem, element)
# create model -- end
solve!(equation, [1, 2], 0.0)
basis = get_basis(element)
temp = basis("temperature", [0.0, -1.0], 0.0)
solve!(problem, [1, 2], 0.0)
temp = element("temperature", [0.0, -1.0], 0.0)
err = temp - 2/3
info("error: $err")
@test isapprox(err, 0.0)
end
type TestProblem <: Problem
unknown_field_name :: ASCIIString
unknown_field_dimension :: Int
equations :: Vector{MyEquation}
end
function TestProblem(equations=[])
TestProblem("temperature", 1, equations)
end
function test_potential_energy_method_2()
# create model -- start
@@ -117,20 +78,21 @@ function test_potential_energy_method_2()
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"] = (0.0 => zeros(Float64, 4))
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"] = (0.0 => zeros(Float64, 2))
# create model -- end
problem = TestProblem()
problem = HeatProblem()
push!(problem, element1)
push!(problem, element2)
solve!(problem, [1, 2], 0.0)
basis = get_basis(element1)
temp = basis("temperature", [0.0, -1.0], 0.0)
temp = element1("temperature", [0.0, -1.0], 0.0)
err = temp - 0.5
info("error: $err")
@test isapprox(err, 0.0, atol=1.0e-6)
+17 -267
View File
@@ -6,14 +6,11 @@ module SolverTests
using JuliaFEM.Test
using JuliaFEM
using JuliaFEM: DirichletProblem, Seg2, PlaneHeatProblem, Quad4, SimpleSolver, get_element, get_basis, MortarElement, MortarProblem, PlaneStressElasticityProblem, solve!, DirectSolver
using JuliaFEM: Seg2, Quad4
using JuliaFEM: DirichletProblem, HeatProblem
using JuliaFEM: LinearSolver
""" Define Problem 1:
- Field function: Laplace equation Δu=0 in Ω={u∈R²|(x,y)∈[0,1]×[0,1]}
- Neumann boundary on Γ₁={0<=x<=1, y=0}, ∂u/∂n=600 on Γ₁
"""
function get_heatproblem()
function test_linearsolver()
el1 = Quad4([1, 2, 3, 4])
el1["geometry"] = Vector[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 1.0]]
el1["temperature thermal conductivity"] = 6.0
@@ -26,278 +23,31 @@ function get_heatproblem()
(1.0 => 600.0)
)
problem1 = PlaneHeatProblem()
push!(problem1, el1)
push!(problem1, el2)
return problem1
end
field_problem = HeatProblem()
push!(field_problem, el1)
push!(field_problem, el2)
""" Define Problem 2:
- Dirichlet boundary Γ₂={0<=x<=1, y=1}, u=0 on Γ₂
"""
function get_boundaryproblem()
el3 = Seg2([3, 4])
el3["geometry"] = Vector[[1.0, 1.0], [0.0, 1.0]]
el3["temperature"] = 0.0
problem2 = DirichletProblem("temperature", 1)
push!(problem2, el3)
return problem2
end
function test_simplesolver()
info("construct heat problem")
problem1 = get_heatproblem()
info("construct boundary problem")
problem2 = get_boundaryproblem()
boundary_problem = DirichletProblem("temperature", 1)
push!(boundary_problem, el3)
# Create a solver for a set of problems
info("create SimpleSolver with problems.")
solver = SimpleSolver()
push!(solver, problem1)
push!(solver, problem2)
info("solve!")
solver = LinearSolver(field_problem, boundary_problem)
# Solve problem at time t=1.0 and update fields
call(solver, 1.0)
solver(1.0)
# Postprocess.
# Interpolate temperature field along boundary of Γ₁ at time t=1.0
xi = [0.0, -1.0]
el2 = get_element(problem1.equations[2])
basis = get_basis(el2)
X = basis("geometry", xi, 1.0)
T = basis("temperature", xi, 1.0)
X = el2("geometry", xi, 1.0)
T = el2("temperature", xi, 1.0)
info("Temperature at point X = $X is T = $T")
@test isapprox(T, 100.0)
end
#test_simplesolver()
function atest_direct_solver()
N = Dict{Int, Vector}(
1 => [0.0, 0.0],
2 => [2.0, 0.0],
3 => [4.0, 0.0],
4 => [0.0, 1.0],
5 => [2.0, 1.0],
6 => [4.0, 1.0],
7 => [0.0, 1.0],
8 => [1.0, 1.0],
9 => [3.0, 1.0],
10 => [4.0, 1.0],
11 => [0.0, 2.0],
12 => [1.0, 2.0],
13 => [3.0, 2.0],
13 => [4.0, 1.0])
# volume elements
e1 = Quad4([1, 2, 5, 4])
e1["geometry"] = Vector[N[1], N[2], N[5], N[4]]
e2 = Quad4([2, 3, 6, 5])
e2["geometry"] = Vector[N[2], N[3], N[6], N[5]]
e3 = Quad4([7, 8, 12, 11])
e3["geometry"] = Vector[N[7], N[8], N[12], N[11]]
e4 = Quad4([8, 9, 13, 12])
e4["geometry"] = Vector[N[8], N[9], N[13], N[12]]
e5 = Quad4([9, 10, 14, 13])
e5["geometry"] = Vector[N[9], N[10], N[14], N[13]]
# boundary elements for boundary load
b1 = Seg2([11, 12])
b1["geometry"] = Vector[N[11], N[12]]
b1["displacement traction force"] = Vector[[0.0, -10.0], [0.0, -10.0]]
b2 = Seg2([12, 13])
b2["geometry"] = Vector[N[12], N[13]]
b2["displacement traction force"] = Vector[[0.0, -10.0], [0.0, -10.0]]
b3 = Seg3([13, 14])
b3["geometry"] = Vector[N[13], N[14]]
b3["displacement traction force"] = Vector[[0.0, -10.0], [0.0, -10.0]]
# boundary elements for dirichlet dy=0
d1 = Seg2([1, 2])
d1["geometry"] = Vector[N[1], N[2]]
d1["displacement 2"] = 0.0
d2 = Seg2([2, 3])
d2["geometry"] = Vector[N[2], N[3]]
d2["displacement 2"] = 0.0
# boundary elements for dirichlet dx=0
d3 = Seg2([1, 4])
d3["geometry"] = Vector[N[1], N[4]]
d3["displacement 1"] = 0.0
d4 = Seg2([4, 11])
d4["geometry"] = Vector[N[4], N[11]]
d4["displacmeent 1"] = 0.0
# mortar elements to tie meshes -- masters
m1 = MSeg2([4, 5])
m1["geometry"] = Vector[N[4], N[5]]
m2 = MSeg2([5, 6])
m2["geometry"] = Vector[N[5], N[6]]
# mortar elements to tie meshes -- slaves
rotation_matrix(phi) = [cos(phi) -sin(phi); sin(phi) cos(phi)]
phi = rotation_matrix(-pi/2)
m3 = MSeg2([7, 8])
m3["geometry"] = Vector[N[7], N[8]]
m3["nodal ntsys"] = Matrix[phi, phi]
m3["master elements"] = MortarElement[m1, m2]
m4 = MSeg2([8, 9])
m4["geometry"] = Vector[N[8], N[9]]
m4["nodal ntsys"] = Matrix[phi, phi]
m4["master elements"] = MortarElement[m1, m2]
m5 = MSeg2([9, 10])
m5["geometry"] = Vector[N[9], N[10]]
m5["nodal ntsys"] = Matrix[phi, phi]
m5["master elements"] = MortarElement[m1, m2]
problem1 = PlaneStressElasticityProblem()
push!(problem1, e1)
push!(problem1, e2)
push!(problem1, e3)
push!(problem1, e4)
push!(problem1, e5)
push!(problem1, b1)
push!(problem1, b2)
push!(problem1, b3)
problem2 = DirichletProblem()
push!(problem2, d1)
push!(problem2, d2)
push!(problem2, d3)
push!(problem2, d4)
problem3 = MortarProblem()
push!(problem3, m1)
push!(problem3, m2)
push!(problem3, m3)
push!(problem3, m4)
push!(problem3, m5)
solver = DirectSolver()
push!(solver, problem1)
push!(solver, problem2)
push!(solver, problem3)
call(solver)
end
function test_solver_multiple_dirichlet_bc()
N = Vector[[0.0, 0.0], [1.0, 0.0], [0.0, 1.0], [1.0, 1.0]]
e1 = Quad4([1, 2, 4, 3])
e1["geometry"] = Vector[N[1], N[2], N[4], N[3]]
e1["youngs modulus"] = 900.0
e1["poissons ratio"] = 0.25
b1 = Seg2([3, 4])
b1["geometry"] = Vector[N[3], N[4]]
b1["displacement traction force"] = Vector[[0.0, -100.0], [0.0, -100.0]]
problem = PlaneStressElasticityProblem()
push!(problem, e1)
push!(problem, b1)
# manually solve problem 1
# free_dofs = [3, 5, 6, 8]
# free_dofs = [3, 6, 7, 8]
#solve!(problem, free_dofs, 0.0; max_iterations=10)
#disp = e1("displacement", [1.0, 1.0], 0.0)
#info("displacement at tip: $disp")
#@test isapprox(disp, [3.17431158889468E-02, -1.38591518927826E-01])
# boundary elements for dirichlet dx=0
dx = Seg2([1, 3])
dx["geometry"] = Vector[N[1], N[3]]
dx["displacement 1"] = 0.0
# boundary elements for dirichlet dy=0
dy = Seg2([1, 2])
dy["geometry"] = Vector[N[1], N[2]]
dy["displacement 2"] = 0.0
problem2 = DirichletProblem("displacement", 2)
push!(problem2, dx)
problem3 = DirichletProblem("displacement", 2)
push!(problem3, dy)
solver = DirectSolver()
push!(solver, problem)
push!(solver, problem2)
push!(solver, problem3)
# launch solver
norm = solver(0.0)
# info(e1("displacement"))
# info(last(e1["displacement"]))
disp = e1("displacement", [1.0, 1.0], 0.0)
info("displacement at tip: $disp")
@test isapprox(disp, [3.17431158889468E-02, -1.38591518927826E-01])
end
function test_solver_multiple_bodies_multiple_dirichlet_bc()
N = Vector[
[0.0, 0.0], [1.0, 0.0],
[0.0, 1.0], [1.0, 1.0],
[0.0, 2.0], [1.0, 2.0]]
e1 = Quad4([1, 2, 4, 3])
e1["geometry"] = Vector[N[1], N[2], N[4], N[3]]
e2 = Quad4([3, 4, 6, 5])
e2["geometry"] = Vector[N[3], N[4], N[6], N[5]]
for el in [e1, e2]
el["youngs modulus"] = 900.0
el["poissons ratio"] = 0.25
end
b1 = Seg2([5, 6])
b1["geometry"] = Vector[N[5], N[6]]
b1["displacement traction force"] = Vector[[0.0, -100.0], [0.0, -100.0]]
body1 = PlaneStressElasticityProblem()
push!(body1, e1)
body2 = PlaneStressElasticityProblem()
push!(body2, e2)
push!(body2, b1)
# boundary elements for dirichlet dx=0
dx1 = Seg2([1, 3])
dx1["geometry"] = Vector[N[1], N[3]]
dx2 = Seg2([3, 5])
dx2["geometry"] = Vector[N[3], N[5]]
for dx in [dx1, dx2]
dx["displacement 1"] = 0.0
end
boundary1 = DirichletProblem("displacement", 2)
push!(boundary1, dx1)
push!(boundary1, dx2)
# boundary elements for dirichlet dy=0
dy1 = Seg2([1, 2])
dy1["geometry"] = Vector[N[1], N[2]]
dy1["displacement 2"] = 0.0
boundary2 = DirichletProblem("displacement", 2)
push!(boundary2, dy1)
solver = DirectSolver()
push!(solver, body1)
push!(solver, body2)
push!(solver, boundary1)
push!(solver, boundary2)
# launch solver
norm = solver(0.0)
disp = e2("displacement", [1.0, 1.0], 0.0)
info("displacement at tip: $disp")
# code aster verification, two_elements.comm
@test isapprox(disp, [3.17431158889468E-02, -2.77183037855653E-01])
end
# test_solver_multiple_bodies_multiple_dirichlet_bc()
end
+30 -36
View File
@@ -5,57 +5,48 @@ module TestAutoDiffWeakForm
using JuliaFEM.Test
using JuliaFEM
using JuliaFEM: Quad4, Equation, IntegrationPoint, assemble!, Assembly,
solve!, get_field, get_element, get_basis,
grad, get_default_integration_points
""" Plane stress formulation for 4-node bilinear element. """
type CPS4 <: Equation
element :: Quad4
integration_points :: Vector{IntegrationPoint}
using JuliaFEM: Problem, AbstractProblem, CG, Element, IntegrationPoint, Quad4, solve!
abstract PlaneStressElasticityProblem <: AbstractProblem
function PlaneStressElasticityProblem(dim::Int=2, elements=[])
return Problem{PlaneStressElasticityProblem}(dim, elements)
end
function JuliaFEM.get_unknown_field_name(equation::CPS4)
function JuliaFEM.get_unknown_field_name{P<:PlaneStressElasticityProblem}(::Type{P})
return "displacement"
end
function CPS4(element::Quad4)
integration_points = get_default_integration_points(element)
if !haskey(element, "displacement")
element["displacement"] = 0.0 => Vector{Float64}[[0.0,0.0], [0.0,0.0], [0.0,0.0], [0.0,0.0]]
end
CPS4(element, integration_points)
function JuliaFEM.get_unknown_field_type{P<:PlaneStressElasticityProblem}(::Type{P})
return Vector{Float64}
end
function Base.size(eq::CPS4)
return (2, 4)
end
function JuliaFEM.get_residual_vector{EL<:CG}(problem::Problem{PlaneStressElasticityProblem}, element::Element{EL}, ip::IntegrationPoint, time::Number; variation=nothing)
function JuliaFEM.get_residual_vector(equation::CPS4, ip, time; variation=nothing)
element = get_element(equation)
basis = get_basis(element)
dbasis = grad(basis)
basis = element(ip, time)
dbasis = element(ip, time, Val{:grad})
# material parameters
E = basis("youngs modulus", ip, time)
nu = basis("poissons ratio", ip, time)
E = element("youngs modulus", ip, time)
nu = element("poissons ratio", ip, time)
mu = E/(2*(1+nu))
la = E*nu/((1+nu)*(1-2*nu))
la = 2*la*mu/(la + 2*mu) # <- correction for 2d
# elasticity formulation
u = basis("displacement", ip, time, variation)
gradu = dbasis("displacement", ip, time, variation)
u = element("displacement", ip, time, variation)
gradu = element("displacement", ip, time, Val{:grad}, variation)
F = I + gradu
b = basis("displacement volume load", ip, time)
E = 1/2*(F'*F - I)
S = la*trace(E)*I + 2*mu*E
P = F*S
r = F*S*dbasis
b = element("displacement volume load", ip, time)
r -= b*basis
# residual vector
r_int = P*dbasis(ip,time)
r_ext = b*basis(ip,time)
r = r_int - r_ext
return vec(r)
end
@@ -66,15 +57,18 @@ function test_residual_form()
element["youngs modulus"] = 500.0
element["poissons ratio"] = 0.3
element["displacement volume load"] = Vector[[0.0,-10.0], [0.0,-10.0], [0.0,-10.0], [0.0,-10.0]]
equation = CPS4(element)
element["displacement"] = (0.0 => Vector{Float64}[zeros(2) for i=1:length(element)])
problem = PlaneStressElasticityProblem()
push!(problem, element)
# create model -- end
free_dofs = [3, 4, 5, 6]
solve!(equation, free_dofs, 0.0) # launch a newton solver for single element
disp = get_basis(element)("displacement", [1.0, 1.0], 0.0)[2]
println("displacement at tip: $disp")
solve!(problem, free_dofs, 0.0) # launch a newton solver for single element
disp = element("displacement", [1.0, 1.0], 0.0)
info("displacement at tip: $disp")
# verified using Code Aster.
@test isapprox(disp, -8.77303119819776E+00)
@test isapprox(disp[2], -8.77303119819776E+00)
end
end