Merge branch 'master' of git://github.com/JuliaFEM/JuliaFEM.jl into HEAD

This commit is contained in:
Olli Väinölä
2015-12-11 09:57:26 +02:00
9 changed files with 184 additions and 27 deletions
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -14,7 +14,7 @@ function assemble!(assembly::Assembly, problem::BoundaryProblem{DirichletProblem
field_name = problem.parent_field_name
gdofs = get_gdofs(element, field_dim)
for ip in get_integration_points(element)
for ip in get_integration_points(element, Val{2})
w = ip.weight * det(element, ip, time)
N = element(ip, time)
A = w*N'*N
+8 -7
View File
@@ -78,14 +78,15 @@ end
function get_integration_points(::TriangularElements, ::Type{Val{5}})
# http://math2.uncc.edu/~shaodeng/TEACHING/math5172/Lectures/Lect_15.PDF
# FIXME: something wrong here with weights ..?
[
IntegrationPoint([0.33333333333333, 0.33333333333333], 0.22500000000000),
IntegrationPoint([0.47014206410511, 0.47014206410511], 0.13239415278851),
IntegrationPoint([0.47014206410511, 0.05971587178977], 0.13239415278851),
IntegrationPoint([0.05971587178977, 0.47014206410511], 0.13239415278851),
IntegrationPoint([0.10128650732346, 0.10128650732346], 0.12593918054483),
IntegrationPoint([0.10128650732346, 0.79742698535309], 0.12593918054483),
IntegrationPoint([0.79742698535309, 0.10128650732346], 0.12593918054483)
IntegrationPoint([0.33333333333333, 0.33333333333333], 0.5*0.22500000000000),
IntegrationPoint([0.47014206410511, 0.47014206410511], 0.5*0.13239415278851),
IntegrationPoint([0.47014206410511, 0.05971587178977], 0.5*0.13239415278851),
IntegrationPoint([0.05971587178977, 0.47014206410511], 0.5*0.13239415278851),
IntegrationPoint([0.10128650732346, 0.10128650732346], 0.5*0.12593918054483),
IntegrationPoint([0.10128650732346, 0.79742698535309], 0.5*0.12593918054483),
IntegrationPoint([0.79742698535309, 0.10128650732346], 0.5*0.12593918054483)
]
end
+101 -3
View File
@@ -364,6 +364,30 @@ function get_points_inside_triangle(Y::Matrix, X::Matrix)
end
""" Return unique objects with some given tolerance. This is used in next function
because traditional unique() command returns row vectors as non-unique if they
differs only a "little".
"""
function uniquetol(P, dim::Int; args...)
@assert dim == 2
items = Vector{Float64}[P[:,i] for i=1:size(P,dim)]
new_items = Vector{Float64}[]
for item in items
has_found = false
for new_item in new_items
if isapprox(item, new_item; args...)
has_found = true
break
end
end
if !has_found
push!(new_items, item)
end
end
return reshape([new_items...;], length(new_items[]), length(new_items))
end
"""
Make polygon clipping of shapes S and M.
@@ -400,13 +424,13 @@ function clip_polygon(S::Matrix, M::Matrix)
P2 = get_points_inside_triangle(M, S)
P3 = get_points_inside_triangle(S, M)
P = hcat(P1, P2, P3)
P = uniquetol(P, 2)
meanval = mean(P, 2)
tmp = P .- meanval
angles = atan2(tmp[2,:], tmp[1,:])
angles = reshape(angles, length(angles))
order = sortperm(angles)
P = copy(unique(P[:, order], 2))
return P, neighbours
return P[:, order], neighbours
end
@@ -569,7 +593,9 @@ end
# Mortar assembly
function assemble!(assembly::Assembly, problem::BoundaryProblem{MortarProblem}, slave_element::Element, time::Number)
typealias MortarElements2D Union{Seg2, Seg3}
function assemble!{E<:MortarElements2D}(assembly::Assembly, problem::BoundaryProblem{MortarProblem}, slave_element::Element{E}, time::Real)
# get dimension and name of PARENT field
field_dim = problem.parent_field_dim
@@ -612,3 +638,75 @@ function assemble!(assembly::Assembly, problem::BoundaryProblem{MortarProblem},
end
end
end
typealias MortarElements3D Union{Tri3}
function assemble!{E<:MortarElements3D}(assembly::Assembly, problem::BoundaryProblem{MortarProblem}, slave_element::Element{E}, time::Real)
field_dim = problem.parent_field_dim
field_name = problem.parent_field_name
slave_dofs = get_gdofs(slave_element, field_dim)
# info("Slave dofs: $slave_dofs")
# info("Field dim: $field_dim")
# create auxiliary plane and project slave nodes to it
# x0 = origo, Q = local basis
x0, Q = create_auxiliary_plane(slave_element, time)
S = Vector{Float64}[]
for p in slave_element("geometry", time)
push!(S, project_point_to_auxiliary_plane(p, x0, Q))
end
S = reshape([S...;], 2, 3)
integration_points = get_integration_points(E, Val{5})
for master_element in slave_element["master elements"]
master_dofs = get_gdofs(master_element, field_dim)
# project master nodes to auxiliary plane and create polygon clipping
M = Vector{Float64}[]
for p in master_element("geometry", time)
push!(M, project_point_to_auxiliary_plane(p, x0, Q))
end
M = reshape([M...;], 2, 3)
P, neighbours = clip_polygon(S, M)
C = calculate_polygon_centerpoint(P)
npts = size(P, 2) # number of vertices in polygon
# S = zeros(3, 3)
# M = zeros(3, 3)
for i=1:npts # loop vertices and create temporary integrate cells
xvec = [C[1], P[1, i], P[1, mod(i, npts)+1]]
yvec = [C[2], P[2, i], P[2, mod(i, npts)+1]]
X = hcat(xvec, yvec)'
geom = Field(Vector{Float64}[X[:,j] for j=1:size(X,2)])
for ip in integration_points
# calculate determiant of jacobian
dN = get_dbasis(E, ip.xi)
J = sum([kron(dN[:,j], geom[j]') for j=1:length(geom)])
w = ip.weight*det(J)
# gauss point in auxiliary plane
N = get_basis(E, ip.xi)
x = vec(N*geom)
# find projection of gauss point to master and slave elements
theta1 = project_point_from_plane_to_surface(x, x0, Q, slave_element, time)
theta2 = project_point_from_plane_to_surface(x, x0, Q, master_element, time)
# evaluate shape functions values in gauss point and add contribution to matrices
N1 = slave_element(theta1[2:3], time)
N2 = master_element(theta2[2:3], time)
S = w*N1'*N1
M = w*N1'*N2
for k=1:field_dim
sd = slave_dofs[k:field_dim:end]
md = master_dofs[k:field_dim:end]
add!(assembly.stiffness_matrix, sd, sd, S)
add!(assembly.stiffness_matrix, sd, md, -M)
# info("sd = $sd")
# info("md = $md")
end
end
end
# info("S = \n$S")
# info("M = \n$M")
end
end
View File
+3 -1
View File
@@ -51,6 +51,8 @@ function test_solver_multiple_dirichlet_bc()
push!(problem3, dy)
solver = DirectSolver()
solver.dump_matrices = true
solver.name = "test_solver_multiple_dirichlet_bc"
push!(solver, problem)
push!(solver, problem2)
push!(solver, problem3)
@@ -63,7 +65,7 @@ function test_solver_multiple_dirichlet_bc()
@test isapprox(disp, [3.17431158889468E-02, -1.38591518927826E-01])
end
#test_solver_multiple_dirichlet_bc()
test_solver_multiple_dirichlet_bc()
function test_direct_cholesky_with_non_homogeneous_dirichlet_conditions()
+12 -1
View File
@@ -4,7 +4,7 @@
module TestDirichletBoundaryCondition
using JuliaFEM.Test
using JuliaFEM.Core: Seg2, DirichletProblem, Assembly, assemble
using JuliaFEM.Core: Tri3, Seg2, DirichletProblem, Assembly, assemble
function test_dirichlet_problem_1_dim()
element = Seg2([1, 2])
@@ -53,4 +53,15 @@ function test_dirichlet_problem_2_dim_single_dof_fixed()
@test isapprox(b, [0.0, 0.0, 0.0, 0.0])
end
function test_dirichlet_surface_tri3()
elem = Tri3([1, 2, 3])
elem["geometry"] = Vector{Float64}[[0.0, 0.0], [1.0, 0.0], [0.0, 1.0]]
elem["temperature"] = 0.0
prob = DirichletProblem("temperature", 1)
push!(prob, elem)
ass = assemble(prob, 0.0)
k = full(ass.stiffness_matrix)
@test isapprox(k, 1/24*[2 1 1; 1 2 1; 1 1 2])
end
end
+2
View File
@@ -36,6 +36,8 @@ function test_one_element() # always start test function with name test_
A = full(assembly.stiffness_matrix)
b = full(assembly.force_vector)
info("stiffness matrix = \n$(round(A, 3))")
@test isapprox(A, [
4.0 -1.0 -2.0 -1.0
-1.0 4.0 -1.0 -2.0
+37 -2
View File
@@ -15,7 +15,8 @@ using JuliaFEM.Core: project_from_slave_to_master, project_from_master_to_slave
using JuliaFEM.Core: create_auxiliary_plane, project_point_to_auxiliary_plane,
get_edge_intersections, get_points_inside_triangle,
clip_polygon, calculate_polygon_centerpoint,
project_point_from_plane_to_surface
project_point_from_plane_to_surface, assemble
function get_test_2d_model()
# this is hand calculated and given as an example in my thesis
@@ -68,6 +69,7 @@ function test_calc_flat_2d_projection_slave_to_master()
@test X2 == [3/4, 1.0]
end
function test_calc_flat_2d_projection_master_to_slave()
slaves, masters = get_test_2d_model()
slave1, slave2 = slaves
@@ -80,6 +82,7 @@ function test_calc_flat_2d_projection_master_to_slave()
end
#test_calc_flat_2d_projection_master_to_slave()
function test_calc_flat_2d_projection_rotated()
master1 = Seg2([3, 4])
master1["geometry"] = Vector{Float64}[[0.0, 1.0], [0.0, 0.0]]
@@ -102,6 +105,7 @@ function test_calc_flat_2d_projection_rotated()
end
function test_create_flat_2d_assembly()
slaves, masters = get_test_2d_model()
slave1, slave2 = slaves
@@ -149,6 +153,7 @@ function test_create_flat_2d_assembly()
end
#test_create_flat_2d_assembly()
function test_2d_mortar_multiple_bodies_multiple_dirichlet_bc()
N = Vector[
[0.0, 0.0], [1.0, 0.0],
@@ -351,6 +356,7 @@ function test_2d_mortar_three_bodies_shared_nodes()
end
#test_2d_mortar_three_bodies_shared_nodes()
function test_auxiliary_plane_transforms()
nodes = Vector{Float64}[
[0.0, 0.0, 0.0],
@@ -380,7 +386,7 @@ function test_auxiliary_plane_transforms()
info("projected point = $X")
@test isapprox(X, Float64[1.0/3.0+0.1, 1.0/3.0+0.1, 0.0])
end
test_auxiliary_plane_transforms()
#test_auxiliary_plane_transforms()
function test_get_edge_intersections()
@@ -460,4 +466,33 @@ end
#test_calculate_polygon_centerpoint()
function test_assemble_3d_problem()
nodes = Vector{Float64}[
[0.0, 0.0, 0.0],
[1.0, 0.0, 0.0],
[0.0, 1.0, 0.0],
[0.0, 0.0, 0.1],
[1.0, 0.0, 0.1],
[0.0, 1.0, 0.1]]
mel = Tri3([4, 5, 6])
mel["geometry"] = Vector{Float64}[nodes[4], nodes[5], nodes[6]]
sel = Tri3([1, 2, 3])
sel["geometry"] = Vector{Float64}[nodes[1], nodes[2], nodes[3]]
R = [0.0 1.0 0.0
0.0 0.0 1.0
1.0 0.0 0.0]
sel["nodal ntsys"] = Matrix{Float64}[R, R, R]
sel["master elements"] = Element[mel]
prob = MortarProblem("temperature", 1)
push!(prob, sel)
stiffness_matrix = full(assemble(prob, 0.0).stiffness_matrix)
info("stiffness matrix for this problem:\n$stiffness_matrix")
M = D = 1/24*[2 1 1; 1 2 1; 1 1 2]
B = [D -M] # slave dofs are first in this.
info("expected matrix for this problem:\n$B")
@test isapprox(stiffness_matrix, B)
end
#test_assemble_3d_problem()
end