mirror of
https://github.com/JuliaFEM/JuliaFEM.jl.git
synced 2026-08-18 11:20:12 +00:00
Merge branch 'master' of git://github.com/JuliaFEM/JuliaFEM.jl into HEAD
This commit is contained in:
File diff suppressed because one or more lines are too long
+1
-1
@@ -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
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user