mirror of
https://github.com/JuliaFEM/JuliaFEM.jl.git
synced 2026-09-24 19:19:54 +00:00
multiple dirichlet boundary conditions for vector valued functions. direct solver design.
This commit is contained in:
+48
-6
@@ -1,18 +1,60 @@
|
||||
|
||||
# This file is a part of JuliaFEM.
|
||||
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
|
||||
|
||||
module TestAutoDiffWeakForm
|
||||
module TestDirichletBoundaryCondition
|
||||
|
||||
using JuliaFEM.Test
|
||||
using JuliaFEM
|
||||
using JuliaFEM: Seg2, DirichletProblem
|
||||
using JuliaFEM: Seg2, DirichletProblem, Assembly, assemble!
|
||||
|
||||
function test_dirichlet_problem()
|
||||
element = Seg2([3, 4])
|
||||
function test_dirichlet_problem_1_dim()
|
||||
element = Seg2([1, 2])
|
||||
element["geometry"] = Vector[[1.0, 1.0], [0.0, 1.0]]
|
||||
problem = DirichletProblem(1)
|
||||
element["temperature"] = 0.0
|
||||
problem = DirichletProblem("temperature", 1)
|
||||
push!(problem, element)
|
||||
assembly = Assembly()
|
||||
assemble!(assembly, problem)
|
||||
A = full(assembly.stiffness_matrix)
|
||||
b = full(assembly.force_vector)
|
||||
@test isapprox(A, 1/6*[2 1; 1 2])
|
||||
@test isapprox(b, [0.0, 0.0])
|
||||
end
|
||||
|
||||
function test_dirichlet_problem_2_dim()
|
||||
element = Seg2([1, 2])
|
||||
element["geometry"] = Vector[[1.0, 1.0], [0.0, 1.0]]
|
||||
element["displacement"] = 0.0
|
||||
problem = DirichletProblem("displacement", 2)
|
||||
push!(problem, element)
|
||||
assembly = Assembly()
|
||||
assemble!(assembly, problem)
|
||||
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]
|
||||
@test isapprox(A, A_expected)
|
||||
@test isapprox(b, [0.0, 0.0, 0.0, 0.0])
|
||||
end
|
||||
|
||||
function test_dirichlet_problem_2_dim_single_dof_fixed()
|
||||
element = Seg2([1, 2])
|
||||
element["geometry"] = Vector[[1.0, 1.0], [0.0, 1.0]]
|
||||
element["displacement 2"] = 0.0
|
||||
problem = DirichletProblem("displacement", 2)
|
||||
push!(problem, element)
|
||||
assembly = Assembly()
|
||||
assemble!(assembly, problem)
|
||||
A = full(assembly.stiffness_matrix)
|
||||
b = full(assembly.force_vector)
|
||||
info(b)
|
||||
info("A = \n$A")
|
||||
A_expected = 1/6*[
|
||||
0 0 0 0
|
||||
0 2 0 1
|
||||
0 0 0 0
|
||||
0 1 0 2]
|
||||
@test isapprox(A, A_expected)
|
||||
@test isapprox(b, [0.0, 0.0, 0.0, 0.0])
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
+13
-12
@@ -25,27 +25,28 @@ function test_elasticity_volume_load()
|
||||
end
|
||||
|
||||
function test_elasticity_surface_load()
|
||||
N = Vector[[0.0, 0.0], [10.0, 0.0], [10.0, 1.0], [0.0, 1.0]]
|
||||
N = Vector[[0.0, 0.0], [1.0, 0.0], [0.0, 1.0], [1.0, 1.0]]
|
||||
|
||||
element1 = Quad4([1, 2, 3, 4])
|
||||
element1["geometry"] = Vector[N[1], N[2], N[3], N[4]]
|
||||
element1["youngs modulus"] = 500.0
|
||||
element1["poissons ratio"] = 0.3
|
||||
element1 = Quad4([1, 2, 4, 3])
|
||||
element1["geometry"] = Vector[N[1], N[2], N[4], N[3]]
|
||||
element1["youngs modulus"] = 900.0
|
||||
element1["poissons ratio"] = 0.25
|
||||
element2 = Seg2([3, 4])
|
||||
element2["geometry"] = Vector[N[3], N[4]]
|
||||
element2["displacement traction force"] = Vector[[0.0, -10.0], [0.0, -10.0]]
|
||||
element2["displacement traction force"] = Vector[[0.0, -100.0], [0.0, -100.0]]
|
||||
|
||||
free_dofs = [3, 4, 5, 6]
|
||||
#free_dofs = [3, 5, 6, 8]
|
||||
free_dofs = [3, 6, 7, 8]
|
||||
problem = PlaneStressElasticityProblem()
|
||||
push!(problem, element1)
|
||||
push!(problem, element2)
|
||||
solve!(problem, free_dofs, 1.0; max_iterations=10)
|
||||
disp = get_basis(element1)("displacement", [1.0, 1.0], 1.0)[2]
|
||||
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.
|
||||
@test isapprox(disp, -9.33106637611714)
|
||||
@test isapprox(disp, [3.17431158889468E-02, -1.38591518927826E-01])
|
||||
end
|
||||
|
||||
#test_elasticity_volume_load()
|
||||
|
||||
end
|
||||
|
||||
+38
-82
@@ -5,7 +5,7 @@ module ElementTests
|
||||
|
||||
using JuliaFEM.Test
|
||||
|
||||
using JuliaFEM: Element, Basis, Field, FieldSet, FunctionSpace, test_element
|
||||
using JuliaFEM: Element, Field, FieldSet, test_element
|
||||
|
||||
""" Prototype element
|
||||
|
||||
@@ -13,11 +13,11 @@ This should always pass test_element if everything is ok.
|
||||
"""
|
||||
type MockElement <: Element
|
||||
connectivity :: Vector{Int}
|
||||
basis :: Basis
|
||||
basis :: Field
|
||||
fields :: FieldSet
|
||||
end
|
||||
|
||||
function MockElement(connectivity)
|
||||
function MockElement(connectivity, fields...)
|
||||
|
||||
h(xi) = 1/4*[
|
||||
(1-xi[1])*(1-xi[2])
|
||||
@@ -29,95 +29,51 @@ function MockElement(connectivity)
|
||||
-(1-xi[2]) (1-xi[2]) (1+xi[2]) -(1+xi[2])
|
||||
-(1-xi[1]) -(1+xi[1]) (1+xi[1]) (1-xi[1])]
|
||||
|
||||
basis = Basis(h, dh)
|
||||
MockElement(connectivity, basis, Dict())
|
||||
MockElement(connectivity, Field(h, dh), FieldSet(fields...))
|
||||
end
|
||||
|
||||
Base.size(element::Type{MockElement}) = (2, 4)
|
||||
|
||||
"""test test_element against mock element"""
|
||||
function test_mockelement()
|
||||
""" Return test element with some fields. """
|
||||
function get_element()
|
||||
el = MockElement([1, 2, 3, 4])
|
||||
el["geometry"] = Vector{Float64}[[0.0,0.0], [1.0,0.0], [1.0,1.0], [0.0,1.0]]
|
||||
el["temperature"] = (
|
||||
0.0 => [0.0, 0.0, 0.0, 0.0],
|
||||
1.0 => [1.0, 2.0, 3.0, 4.0])
|
||||
el["displacement"] = (
|
||||
0.0 => Vector{Float64}[[0.0,0.0], [0.0, 0.0], [0.0,0.0], [0.0,0.0]],
|
||||
1.0 => Vector{Float64}[[0.0,0.0], [1.0,-1.0], [2.0,3.0], [0.0,0.0]])
|
||||
return el
|
||||
end
|
||||
|
||||
function test_mock_element()
|
||||
test_element(MockElement)
|
||||
end
|
||||
|
||||
""" test adding fieldsets and fields to element"""
|
||||
function test_add_fields_to_element()
|
||||
el = MockElement([1, 2, 3, 4])
|
||||
#geometry = Field([0.0, 0.0, 0.0, 0.0])
|
||||
el["geometry"] = Field([0.0, 0.0, 0.0, 0.0])
|
||||
@test el["geometry"][1].time == 0.0
|
||||
@test last(el["geometry"]) == [0.0, 0.0, 0.0, 0.0]
|
||||
el["geometry"] = Field(Vector[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 1.0]])
|
||||
@test last(el["geometry"])[3] == [1.0, 1.0]
|
||||
el["geometry"] = Vector[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 1.0]]
|
||||
@test last(el["geometry"])[3] == [1.0, 1.0]
|
||||
el["geometry"] = [0.0 0.0; 1.0 0.0; 1.0 1.0; 0.0 1.0]'
|
||||
@test last(el["geometry"])[3] == [1.0, 1.0]
|
||||
el["geometry"] = (0.0, [0.0, 0.0, 0.0, 0.0]), (1.0, [1.0, 1.0, 1.0, 1.0])
|
||||
field = el["geometry"]
|
||||
@test length(field) == 2 # two time steps
|
||||
el["boundary flux"] = (0.0, 0.0), (1.0, 6.0)
|
||||
el = get_element()
|
||||
info(el.fields)
|
||||
end
|
||||
|
||||
function test_add_fields_to_element_2()
|
||||
el = MockElement([1, 2, 3, 4])
|
||||
el["data"] = (0.0 => [1, 2], 1.0 => [2, 3])
|
||||
@test length(el["data"]) == 2
|
||||
@test el["data"][1].time == 0.0
|
||||
@test el["data"][2].time == 1.0
|
||||
@test last(el["data"][1]) == [1, 2]
|
||||
@test last(el["data"][2]) == [2, 3]
|
||||
function test_interpolate()
|
||||
el = get_element()
|
||||
@test isapprox(el("geometry", [0.0, 0.0]), [0.5, 0.5])
|
||||
@test isapprox(el("geometry", [0.0, 0.0], 0.0), [0.5, 0.5])
|
||||
@test isapprox(el([0.0, 0.0]), [0.25 0.25 0.25 0.25])
|
||||
@test isapprox(el([0.0, 0.0], Val{:grad}), [-0.5 0.5 0.5 -0.5; -0.5 -0.5 0.5 0.5])
|
||||
gradT = el("temperature", [0.0, 0.0], 1.0, Val{:grad})
|
||||
info("gradT = $gradT")
|
||||
X = [0.5, 0.5]
|
||||
gradT_expected = [1-2*X[2] 3-2*X[1]]
|
||||
info("gradT(expected) = $gradT_expected")
|
||||
@test isapprox(gradT, gradT_expected)
|
||||
|
||||
@test isapprox(el("temperature", [0.0, 0.0], 0.5), 1/2*gradT_expected)
|
||||
|
||||
gradT = el("temperature", [0.0, 0.0], 0.5, Val{:grad})
|
||||
info("gradT = $gradT")
|
||||
@test isapprox(gradT, 1/2*gradT_expected)
|
||||
end
|
||||
|
||||
function test_add_data_to_element_using_push()
|
||||
el = MockElement([1, 2, 3, 4])
|
||||
el["data"] = [0, 0, 0, 0]
|
||||
|
||||
push!(el["data"], [1, 2, 3, 4])
|
||||
@test length(el["data"]) == 1
|
||||
@test length(el["data"][1]) == 2
|
||||
@test el["data"][1].time == 0.0
|
||||
|
||||
push!(el["data"], 1.0 => [2, 3, 4, 5]) # creates new timestep at t=1.0
|
||||
push!(el["data"], [3, 4, 5, 6]) # adds new increment data to last timestep
|
||||
@test length(el["data"]) == 2
|
||||
@test length(el["data"][2]) == 2
|
||||
@test el["data"][2].time == 1.0
|
||||
|
||||
end
|
||||
|
||||
#=
|
||||
facts("interpolation of fields in some function space") do
|
||||
|
||||
el = MockElement([1, 2, 3, 4])
|
||||
fieldset1 = FieldSet("geometry", [Field(0.0, Vector[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 1.0]])])
|
||||
fieldset2 = FieldSet("constant scalar field", [Field(0.0, 1.0)])
|
||||
fieldset3 = FieldSet("scalar field", [Field(0.0, [1.0, 2.0, 3.0, 4.0])])
|
||||
fieldset4 = FieldSet("vector field 1", [Field(0.0, Vector[[1.0], [2.0], [3.0], [4.0]])])
|
||||
fieldset5 = FieldSet("vector field 2", [Field(0.0, Vector[[1.0, 5.0], [2.0, 6.0], [3.0, 7.0], [4.0, 8.0]])])
|
||||
fieldset6 = FieldSet("vector field 3", [Field(0.0, Vector[[1.0, 5.0, 9.0], [2.0, 6.0, 10.0], [3.0, 7.0, 11.0], [4.0, 8.0, 12.0]])])
|
||||
fieldset7 = FieldSet("tensor field 1", [Field(0.0, Matrix[[1.0 5.0; 9.0 13.0], [2.0 6.0; 10.0 14.0], [3.0 7.0; 11.0 15.0], [4.0 8.0; 12.0 16.0]])])
|
||||
|
||||
element["geometry"] = fieldset1
|
||||
element["constant scalar field"] = fieldset2
|
||||
element["scalar field"] = fieldset3
|
||||
element["vector field 1"] = fieldset4
|
||||
element["vector field 2"] = fieldset5
|
||||
element["vector field 3"] = fieldset6
|
||||
element["tensor field 1"] = fieldset7
|
||||
|
||||
xi = [0.0, 0.0]
|
||||
t = 0.0
|
||||
u = FunctionSpace(element)
|
||||
v = FunctionSpace(element)
|
||||
|
||||
@fact v("constant scalar field", xi, t) --> 1.0
|
||||
@fact v("scalar field", xi, t) --> 1/4*(1+2+3+4)
|
||||
@fact v("vector field 1", xi, t) --> [1/4*(1+2+3+4)]
|
||||
@fact v("vector field 2", xi, t) --> 1/4*[1+2+3+4, 5+6+7+8]
|
||||
@fact v("vector field 3", xi, t) --> 1/4*[1+2+3+4, 5+6+7+8, 9+10+11+12]
|
||||
@fact v("tensor field 1", xi, t) --> 1/4*[1+2+3+4 5+6+7+8; 9+10+11+12 13+14+15+16]
|
||||
end
|
||||
=#
|
||||
|
||||
end
|
||||
|
||||
+57
-4
@@ -6,7 +6,7 @@ module SolverTests
|
||||
using JuliaFEM.Test
|
||||
using JuliaFEM
|
||||
|
||||
using JuliaFEM: DirichletProblem, Seg2, PlaneHeatProblem, Quad4, SimpleSolver, get_element, get_basis, MortarElement, MortarProblem, DirectSolver, PlaneStressElasticityProblem
|
||||
using JuliaFEM: DirichletProblem, Seg2, PlaneHeatProblem, Quad4, SimpleSolver, get_element, get_basis, MortarElement, MortarProblem, PlaneStressElasticityProblem, solve!, DirectSolver
|
||||
|
||||
""" Define Problem 1:
|
||||
|
||||
@@ -38,7 +38,8 @@ end
|
||||
function get_boundaryproblem()
|
||||
el3 = Seg2([3, 4])
|
||||
el3["geometry"] = Vector[[1.0, 1.0], [0.0, 1.0]]
|
||||
problem2 = DirichletProblem(1)
|
||||
el3["temperature"] = 0.0
|
||||
problem2 = DirichletProblem("temperature", 1)
|
||||
push!(problem2, el3)
|
||||
return problem2
|
||||
end
|
||||
@@ -67,7 +68,7 @@ function test_simplesolver()
|
||||
@test isapprox(T, 100.0)
|
||||
end
|
||||
|
||||
function test_direct_solver()
|
||||
function atest_direct_solver()
|
||||
|
||||
N = Dict{Int, Vector}(
|
||||
1 => [0.0, 0.0],
|
||||
@@ -87,7 +88,7 @@ function test_direct_solver()
|
||||
|
||||
# volume elements
|
||||
e1 = Quad4([1, 2, 5, 4])
|
||||
e1["geometry"] = Vector[N[1], N[2], N[3], N[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])
|
||||
@@ -178,4 +179,56 @@ function test_direct_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]]
|
||||
|
||||
#free_dofs = [3, 5, 6, 8]
|
||||
free_dofs = [3, 6, 7, 8]
|
||||
problem = PlaneStressElasticityProblem()
|
||||
push!(problem, e1)
|
||||
push!(problem, b1)
|
||||
|
||||
# manually solve problem 1
|
||||
#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)
|
||||
push!(problem2, dy)
|
||||
|
||||
solver = DirectSolver()
|
||||
push!(solver, problem)
|
||||
push!(solver, problem2)
|
||||
|
||||
# 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
|
||||
|
||||
# test_solver_multiple_dirichlet_bc()
|
||||
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user