Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# CHANGES

## v.1.10.0

### Changed
- `SolverConfiguration` has no `LP` property any more: everything is available via the `linsolver`.
- `initialize_linear_solver` is slightly changed and called much later in `solve`.

## v.1.9.1

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "ExtendableFEM"
uuid = "a722555e-65e0-4074-a036-ca7ce79a4aed"
version = "1.9.1"
version = "1.10.0"
authors = ["Christian Merdon <merdon@wias-berlin.de>", "Patrick Jaap <patrick.jaap@wias-berlin.de>"]

[deps]
Expand Down
9 changes: 1 addition & 8 deletions src/solver_config.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ mutable struct SolverConfiguration{AT <: AbstractMatrix, bT, xT}
tempsol::xT ## temporary solution
res::xT
freedofs::Vector{Int} ## stores indices of free dofs
LP::LinearProblem
statistics::Dict{Symbol, Any}
linsolver::Any
unknown_ids_in_sol::Array{Int, 1}
Expand Down Expand Up @@ -221,11 +220,5 @@ function SolverConfiguration(Problem::ProblemDescription, unknowns::Array{Unknow
x_temp = x
end

## construct linear problem
if length(freedofs) > 0
LP = LinearProblem(A.entries.cscmatrix[freedofs, freedofs], b.entries[freedofs])
else
LP = LinearProblem(A.entries.cscmatrix, b.entries)
end
return SolverConfiguration{typeof(A), typeof(b), typeof(x)}(Problem, A, b, x, x_temp, res, freedofs, LP, default_statistics(TvM, TiM), nothing, unknown_ids_in_sol, unknowns, copy(unknowns), offsets, parameters)
return SolverConfiguration{typeof(A), typeof(b), typeof(x)}(Problem, A, b, x, x_temp, res, freedofs, default_statistics(TvM, TiM), nothing, unknown_ids_in_sol, unknowns, copy(unknowns), offsets, parameters)
end
63 changes: 34 additions & 29 deletions src/solvers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ end

Initialize the linear solver for the given system.
"""
function init_linear_solver!(SC, A, timer, method_linear, precon_linear)
function init_linear_solver!(SC, A, b, timer)

# TODO use the timer
time_assembly = 0.0
Expand All @@ -98,11 +98,14 @@ function init_linear_solver!(SC, A, timer, method_linear, precon_linear)
stats = @timed begin
abstol = SC.parameters[:abstol]
reltol = SC.parameters[:reltol]
LP = SC.LP
method_linear = SC.parameters[:method_linear]
precon_linear = SC.parameters[:precon_linear]

LP = LinearProblem(A, b)
if precon_linear !== nothing
SC.linsolver = init(LP, method_linear; Pl = precon_linear(A.entries.cscmatrix), abstol = abstol, reltol = reltol)
SC.linsolver = init(LP, method_linear; Pl = precon_linear(A), abstol, reltol)
else
SC.linsolver = init(LP, method_linear; abstol = abstol, reltol = reltol)
SC.linsolver = init(LP, method_linear; abstol, reltol)
end
end
time_assembly += stats.time
Expand Down Expand Up @@ -242,11 +245,10 @@ Solves the linear system and updates the solution vector. This includes:
- Computing the residual
- Updating the solution with optional damping
"""
function solve_linear_system!(A, b, sol, soltemp, residual, linsolve, unknowns, freedofs, damping, PD, SC, stats, is_linear, timer, kwargs...)
function solve_linear_system!(A, b, sol, soltemp, residual, unknowns, freedofs, damping, PD, SC, stats, is_linear, timer, kwargs...)

@timeit timer "linear solver" begin


# does the linsolve object need a (new) matrix?
linsolve_needs_matrix = !SC.parameters[:constant_matrix] || !SC.parameters[:initialized]

Expand All @@ -272,9 +274,9 @@ function solve_linear_system!(A, b, sol, soltemp, residual, linsolve, unknowns,

if length(PD.restrictions) == 0
if linsolve_needs_matrix
linsolve.A = A_unrestricted
linsolve_A = A_unrestricted
end
linsolve.b = b_unrestricted
linsolve_b = b_unrestricted
else
# add possible Lagrange restrictions
restriction_matrices = [length(freedofs) > 0 ? view(restriction_matrix(re), freedofs, :) : restriction_matrix(re) for re in PD.restrictions ]
Expand Down Expand Up @@ -342,11 +344,7 @@ function solve_linear_system!(A, b, sol, soltemp, residual, linsolve, unknowns,
end

b_block = BlockVector(zeros(Tv, total_size), block_sizes)

b_block[Block(1)] = b_unrestricted
u_unrestricted = @views linsolve.u[1:block_sizes[1]]
u_block = BlockVector(zeros(Tv, total_size), block_sizes)
u_block[Block(1)] = u_unrestricted

for i in eachindex(restriction_matrices)
if linsolve_needs_matrix
Expand All @@ -358,8 +356,7 @@ function solve_linear_system!(A, b, sol, soltemp, residual, linsolve, unknowns,
end

# convert to dense vectors
linsolve.b = Vector(b_block)
linsolve.u = Vector(u_block)
linsolve_b = Vector(b_block)

if linsolve_needs_matrix

Expand All @@ -379,12 +376,28 @@ function solve_linear_system!(A, b, sol, soltemp, residual, linsolve, unknowns,
# write each block directly in the resulting matrix
A_flat[range_row, range_col] = A_block[Block(i, j)]
end
linsolve.A = A_flat
linsolve_A = A_flat
end
end
end

SC.parameters[:initialized] = true

if SC.parameters[:initialized]
# set/update the linear system
SC.linsolver.b = linsolve_b
if linsolve_needs_matrix
SC.linsolver.A = linsolve_A
end
else
# init solver if not done before
@timeit timer "linear solver" begin
init_linear_solver!(SC, linsolve_A, linsolve_b, timer)
end
SC.parameters[:initialized] = true
end

# now the linear solver is definitely ready
linsolve = SC.linsolver

# Solve linear system
push!(stats[:matrix_nnz], nnz(linsolve.A))
Expand Down Expand Up @@ -725,11 +738,6 @@ function CommonSolve.solve(PD::ProblemDescription, FES::Union{<:FESpace, Vector{
@info ".... isposdef = $(isposdef(A.entries.cscmatrix))"
end

## init solver
@timeit timer "linear solver" begin
init_linear_solver!(SC, A, timer, method_linear, precon_linear)
end

## compute nonlinear residual
@timeit timer "assembly" @timeit timer "residual vector" begin
nlres = compute_nonlinear_residual!(residual, A, b, sol, unknowns, PD, SC, freedofs)
Expand All @@ -744,11 +752,8 @@ function CommonSolve.solve(PD::ProblemDescription, FES::Union{<:FESpace, Vector{
break
end

linsolve = SC.linsolver


linres = solve_linear_system!(
A, b, sol, soltemp, residual, linsolve, unknowns,
A, b, sol, soltemp, residual, unknowns,
freedofs, damping, PD, SC, stats, is_linear, timer
)

Expand Down Expand Up @@ -874,11 +879,11 @@ function iterate_until_stationarity(
# Initialize linear solver if needed
solve_init_time, solve_init_allocs = init_linear_solver!(
SC,
A,
TimerOutput(),
SC.parameters[:method_linear],
SC.parameters[:precon_linear]
A.entries.cscmatrix,
b.entries,
TimerOutput()
)

time_solve_init += solve_init_time
allocs_solve_init += solve_init_allocs

Expand Down
Loading