mirror of
https://github.com/JuliaFEM/JuliaFEM.jl.git
synced 2026-08-30 08:02:50 +00:00
small bug fixes
This commit is contained in:
+5
-5
@@ -188,10 +188,10 @@ end
|
||||
|
||||
""" Return dual basis transformation matrix Ae. """
|
||||
function get_dualbasis(element::Element, time::Real)
|
||||
if length(element.dualbasis) == 0
|
||||
if length(element.A) == 0
|
||||
nnodes = size(element, 2)
|
||||
D = zeros(nnodes, nnodes)
|
||||
M = zeros(nnodes, nnodes)
|
||||
De = zeros(nnodes, nnodes)
|
||||
Me = zeros(nnodes, nnodes)
|
||||
for ip in get_integration_points(element, Val{3})
|
||||
w = ip.weight
|
||||
J = get_jacobian(element, ip, time)
|
||||
@@ -207,8 +207,8 @@ function get_dualbasis(element::Element, time::Real)
|
||||
De += w*diagm(vec(N))
|
||||
Me += w*N'*N
|
||||
end
|
||||
element.D = D
|
||||
element.M = M
|
||||
element.D = De
|
||||
element.M = Me
|
||||
element.A = De*inv(Me)
|
||||
end
|
||||
return element.D, element.M, element.A
|
||||
|
||||
@@ -271,6 +271,7 @@ end
|
||||
""" Find nodes corresponding to dofs. """
|
||||
function find_nodes_by_dofs(problem::Problem, dofs)
|
||||
dim = get_unknown_field_dimension(problem)
|
||||
return find_nodes_by_dofs(dim, dofs)
|
||||
end
|
||||
function find_nodes_by_dofs(dim, dofs)
|
||||
nodes = Int64[]
|
||||
|
||||
+7
-5
@@ -1,7 +1,8 @@
|
||||
# This file is a part of JuliaFEM.
|
||||
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
|
||||
|
||||
subscript(i) = map(repr(i)) do c
|
||||
function subscript(i)
|
||||
map(repr(i)) do c
|
||||
c == '1' ? '\u2081' :
|
||||
c == '2' ? '\u2082' :
|
||||
c == '3' ? '\u2083' :
|
||||
@@ -12,8 +13,9 @@ subscript(i) = map(repr(i)) do c
|
||||
c == '8' ? '\u2088' :
|
||||
c == '9' ? '\u2089' :
|
||||
c == '0' ? '\u2080' :
|
||||
error("Unexpected Chatacter")
|
||||
error("Unexpected character")
|
||||
end
|
||||
end
|
||||
|
||||
function pretty_print_constraint_equation(a, b, g; char1="u", char2="λ")
|
||||
s = ""
|
||||
@@ -95,17 +97,17 @@ function handle_overconstraint_error!(problem, nodes, all_dofs, C1_, C1, C2_, C2
|
||||
"""
|
||||
function action1(node_id, dofs)
|
||||
dofs_ = get_related_dofs(intersect(dofs, all_dofs))
|
||||
# this will fail with dofs > 2 for some yet unknown reason
|
||||
length(dofs_) > 2 && return dofs_, false
|
||||
|
||||
any(has_lagrange_coefficients(dofs_)) && return dofs_, false
|
||||
C = full([C2[dofs_, :]; C2_[dofs_, :]])
|
||||
d = full([g[dofs_]; g_[dofs_]])
|
||||
# this will fail with dofs > 2 for some yet unknown reason
|
||||
length(dofs_) > 2 && return dofs_, false
|
||||
info("rank = $(rank(C)), dofs = $(length(dofs_))")
|
||||
rank(C) != length(dofs_) && return dofs_, false
|
||||
C2_[dofs_,:] = C2[dofs_,:] = 0
|
||||
g_[dofs_,:] = g[dofs_,:] = 0
|
||||
x = C \ d
|
||||
x[abs(x) .< 1.0e-12] = 0
|
||||
C2[dofs_, dofs_] = eye(length(dofs_))
|
||||
g[dofs_] = x
|
||||
return dofs_, true
|
||||
|
||||
+59
-38
@@ -138,11 +138,12 @@ end
|
||||
# Tuple{Symbol,Any,Any} or Function
|
||||
|
||||
type Solver
|
||||
name :: ASCIIString
|
||||
time :: Real
|
||||
iteration :: Int
|
||||
name :: ASCIIString # some descriptive name for problem
|
||||
time :: Real # current time
|
||||
iteration :: Int # iteration counter
|
||||
ndofs :: Int # total dimension of global stiffness matrix, i.e., dim*nnodes
|
||||
problems :: Vector{Problem}
|
||||
is_linear_system :: Bool
|
||||
is_linear_system :: Bool # setting this to true makes assumption of one step convergence
|
||||
nonlinear_system_max_iterations :: Int64
|
||||
nonlinear_system_convergence_tolerance :: Float64
|
||||
linear_system_solver :: Symbol
|
||||
@@ -150,11 +151,12 @@ end
|
||||
|
||||
function Solver(name::ASCIIString="default solver", time::Real=0.0)
|
||||
return Solver(
|
||||
name, # name
|
||||
time, # time
|
||||
0, # iteration counter
|
||||
name,
|
||||
time,
|
||||
0, # iteration #
|
||||
0, # ndofs
|
||||
[], # array of problems
|
||||
false, # is this a linear system which can be solved in a single iteration?
|
||||
false, # is_linear_system
|
||||
10, # max nonlinear iterations
|
||||
5.0e-5, # nonlinear iteration convergence tolerance
|
||||
:DirectLinearSolver # linear system solution method
|
||||
@@ -210,6 +212,7 @@ function get_mortar_problems(solver::Solver)
|
||||
filter(is_mortar_problem, solver.problems)
|
||||
end
|
||||
|
||||
|
||||
"""Return one combined field assembly for a set of field problems.
|
||||
|
||||
Parameters
|
||||
@@ -218,7 +221,7 @@ solver :: Solver
|
||||
|
||||
Returns
|
||||
-------
|
||||
K, f :: SparseMatrixCOO
|
||||
K, f :: SparseMatrixCSC
|
||||
|
||||
Notes
|
||||
-----
|
||||
@@ -227,42 +230,65 @@ problems must have unique node ids.
|
||||
|
||||
"""
|
||||
function get_field_assembly(solver::Solver)
|
||||
return get_field_assembly(get_field_problems(solver))
|
||||
end
|
||||
function get_field_assembly(problems::Vector{Problem})
|
||||
problems = get_field_problems(solver)
|
||||
K = SparseMatrixCOO()
|
||||
f = SparseMatrixCOO()
|
||||
for problem in problems
|
||||
append!(K, problem.assembly.K)
|
||||
append!(f, problem.assembly.f)
|
||||
end
|
||||
K = sparse(K)
|
||||
solver.ndofs = size(K, 1)
|
||||
f = sparse(f, solver.ndofs, 1)
|
||||
return K, f
|
||||
end
|
||||
|
||||
|
||||
""" Return one combined boundary assembly for a set of boundary problems.
|
||||
|
||||
Returns
|
||||
-------
|
||||
C1, C2, D, g :: SparseMatrixCOO
|
||||
C1, C2, D, g :: SparseMatrixCSC
|
||||
|
||||
Notes
|
||||
-----
|
||||
When some dof is constrained by multiple boundary problems an algorithm is
|
||||
launched what tries to do it's best to solve issue. It's far from perfect
|
||||
but is able to handle some basic situations occurring in corner nodes and
|
||||
crosspoints.
|
||||
|
||||
"""
|
||||
function get_boundary_assembly(solver::Solver)
|
||||
return get_boundary_assembly(get_boundary_problems(solver))
|
||||
end
|
||||
function get_boundary_assembly(problems::Vector{Problem})
|
||||
C1 = SparseMatrixCOO()
|
||||
C2 = SparseMatrixCOO()
|
||||
D = SparseMatrixCOO()
|
||||
g = SparseMatrixCOO()
|
||||
for problem in problems
|
||||
append!(C1, problem.assembly.C1)
|
||||
append!(C2, problem.assembly.C2)
|
||||
append!(D, problem.assembly.D)
|
||||
append!(g, problem.assembly.g)
|
||||
ndofs = solver.ndofs
|
||||
@assert ndofs != 0
|
||||
C1 = spzeros(ndofs, ndofs)
|
||||
C2 = spzeros(ndofs, ndofs)
|
||||
D = spzeros(ndofs, ndofs)
|
||||
g = spzeros(ndofs, 1)
|
||||
for problem in get_boundary_problems(solver)
|
||||
assembly = problem.assembly
|
||||
C1_ = sparse(assembly.C1, ndofs, ndofs)
|
||||
C2_ = sparse(assembly.C2, ndofs, ndofs)
|
||||
D_ = sparse(assembly.D, ndofs, ndofs)
|
||||
g_ = sparse(assembly.g, ndofs, 1)
|
||||
already_constrained = get_nonzero_rows(C2)
|
||||
new_constraints = get_nonzero_rows(C2_)
|
||||
overconstrained_dofs = intersect(already_constrained, new_constraints)
|
||||
if length(overconstrained_dofs) != 0
|
||||
overconstrained_dofs = sort(overconstrained_dofs)
|
||||
overconstrained_nodes = find_nodes_by_dofs(problem, overconstrained_dofs)
|
||||
handle_overconstraint_error!(problem, overconstrained_nodes,
|
||||
overconstrained_dofs, C1, C1_, C2, C2_, D, D_, g, g_)
|
||||
end
|
||||
C1 += C1_
|
||||
C2 += C2_
|
||||
D += D_
|
||||
g += g_
|
||||
end
|
||||
return C1, C2, D, g
|
||||
end
|
||||
|
||||
|
||||
""" Solve linear system using LU factorization (UMFPACK).
|
||||
"""
|
||||
function solve_linear_system(solver::Solver, ::Type{Val{:DirectLinearSolver}})
|
||||
@@ -271,31 +297,26 @@ function solve_linear_system(solver::Solver, ::Type{Val{:DirectLinearSolver}})
|
||||
|
||||
# assemble field problems
|
||||
K, f = get_field_assembly(solver)
|
||||
K = sparse(K)
|
||||
dim = size(K, 1)
|
||||
f = sparse(f, dim, 1)
|
||||
|
||||
# assemble boundary problems
|
||||
C1, C2, D, g = get_boundary_assembly(solver)
|
||||
C1 = sparse(C1, dim, dim)
|
||||
C2 = sparse(C2, dim, dim)
|
||||
D = sparse(D, dim, dim)
|
||||
g = sparse(g, dim, 1)
|
||||
|
||||
# construct global system Ax=b and solve using lu factorization
|
||||
A = [K C1'; C2 D]
|
||||
b = [f; g]
|
||||
nz1 = sort(unique(rowvals(A)))
|
||||
nz2 = sort(unique(rowvals(A')))
|
||||
x = zeros(length(b))
|
||||
x[nz1] = lufact(A[nz1,nz2]) \ full(b[nz1])
|
||||
|
||||
u = x[1:dim]
|
||||
la = x[dim+1:end]
|
||||
nz = get_nonzero_rows(A)
|
||||
x = zeros(length(b))
|
||||
x[nz] = lufact(A[nz,nz]) \ full(b[nz])
|
||||
|
||||
ndofs = solver.ndofs
|
||||
u = x[1:ndofs]
|
||||
la = x[ndofs+1:end]
|
||||
info("UMFPACK: solved in ", time()-t0, " seconds. norm = ", norm(u))
|
||||
return u, la
|
||||
end
|
||||
|
||||
|
||||
""" Check convergence of problems.
|
||||
|
||||
Notes
|
||||
|
||||
+1
-1
@@ -135,7 +135,7 @@ Returns
|
||||
|
||||
Ordered list of row indices.
|
||||
"""
|
||||
function get_nonzero_rows(A::SparseMatrixCOO)
|
||||
function get_nonzero_rows(A::SparseMatrixCSC)
|
||||
# FIXME: This is probably a very inefficient way to do this.
|
||||
return sort(unique(rowvals(A)))
|
||||
end
|
||||
|
||||
@@ -17,5 +17,11 @@ end
|
||||
dim = 3
|
||||
nodes = find_nodes_by_dofs(dim, dofs)
|
||||
@test nodes == [1, 3]
|
||||
|
||||
dofs = [2, 12]
|
||||
dim = 2
|
||||
nodes = find_nodes_by_dofs(dim,dofs)
|
||||
@test nodes == [1, 6]
|
||||
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user