Skip to content

Commit cbde993

Browse files
authored
Merge pull request #180 from Cthonios/multi-block-fixes
fixes to multi-block stiffness assembly methods and adding tests for …
2 parents d928ca0 + a1073e4 commit cbde993

File tree

9 files changed

+193
-43
lines changed

9 files changed

+193
-43
lines changed

ext/FiniteElementContainersAdaptExt.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ function Adapt.adapt_structure(to, asm::FiniteElementContainers.SparsityPattern)
2828
Is = adapt(to, asm.Is)
2929
Js = adapt(to, asm.Js)
3030
unknown_dofs = adapt(to, asm.unknown_dofs)
31-
block_sizes = adapt(to, asm.block_sizes)
32-
block_offsets = adapt(to, asm.block_offsets)
31+
block_start_indices = adapt(to, asm.block_start_indices)
32+
block_el_level_sizes = adapt(to, asm.block_el_level_sizes)
3333
#
3434
klasttouch = adapt(to, asm.klasttouch)
3535
csrrowptr = adapt(to, asm.csrrowptr)
@@ -41,7 +41,7 @@ function Adapt.adapt_structure(to, asm::FiniteElementContainers.SparsityPattern)
4141
cscnzval = adapt(to, asm.cscnzval)
4242
return FiniteElementContainers.SparsityPattern(
4343
Is, Js,
44-
unknown_dofs, block_sizes, block_offsets,
44+
unknown_dofs, block_start_indices, block_el_level_sizes,
4545
klasttouch, csrrowptr, csrcolval, csrnzval,
4646
csccolptr, cscrowval, cscnzval
4747
)

src/assemblers/Matrix.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -137,11 +137,11 @@ KA.@kernel function _assemble_block_matrix_kernel!(
137137
end
138138
end
139139

140-
block_size = values(pattern.block_sizes)[block_id]
141-
block_offset = values(pattern.block_offsets)[block_id]
142-
start_id = (block_id - 1) * block_size +
143-
(E - 1) * block_offset + 1
144-
end_id = start_id + block_offset - 1
140+
block_start_index = values(pattern.block_start_indices)[block_id]
141+
block_el_level_size = values(pattern.block_el_level_sizes)[block_id]
142+
start_id = block_start_index +
143+
(E - 1) * block_el_level_size
144+
end_id = start_id + block_el_level_size - 1
145145
ids = start_id:end_id
146146
for (i, id) in enumerate(ids)
147147
Atomix.@atomic field[id] += K_el.data[i]

src/assemblers/SparseMatrixAssembler.jl

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,11 @@ function _assemble_element!(
9797
pattern::SparsityPattern, storage, K_el::SMatrix, el_id::Int, block_id::Int
9898
)
9999
# figure out ids needed to update
100-
block_size = values(pattern.block_sizes)[block_id]
101-
block_offset = values(pattern.block_offsets)[block_id]
102-
# get range of ids
103-
start_id = (block_id - 1) * block_size +
104-
(el_id - 1) * block_offset + 1
105-
end_id = start_id + block_offset - 1
100+
block_start_index = values(pattern.block_start_indices)[block_id]
101+
block_el_level_size = values(pattern.block_el_level_sizes)[block_id]
102+
start_id = block_start_index +
103+
(el_id - 1) * block_el_level_size
104+
end_id = start_id + block_el_level_size - 1
106105
ids = start_id:end_id
107106

108107
# get appropriate storage and update values

src/assemblers/SparsityPattern.jl

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ struct SparsityPattern{
1313
Is::I
1414
Js::I
1515
unknown_dofs::I
16-
block_sizes::B
17-
block_offsets::B
16+
block_start_indices::B
17+
block_el_level_sizes::B
1818
# cache arrays
1919
klasttouch::I
2020
csrrowptr::I
@@ -46,23 +46,33 @@ function SparsityPattern(dof::DofManager)
4646

4747
# first get total number of entries in a stupid manner
4848
n_entries = 0
49-
block_sizes = Vector{Int64}(undef, n_blocks)
50-
block_offsets = Vector{Int64}(undef, n_blocks)
49+
block_start_indices = Vector{Int64}(undef, n_blocks)
50+
block_el_level_sizes = Vector{Int64}(undef, n_blocks)
5151

5252
# for (n, conn) in enumerate(values(dof.H1_vars[1].fspace.elem_conns))
53+
start_carry = 1
5354
for (n, conn) in enumerate(values(fspace.elem_conns))
5455
ids = reshape(1:n_total_dofs, ND, NN)
5556
# TODO do we need this operation?
5657
conn = reshape(ids[:, conn], ND * size(conn, 1), size(conn, 2))
5758
n_entries += size(conn, 1)^2 * size(conn, 2)
58-
block_sizes[n] = size(conn, 2)
59-
block_offsets[n] = size(conn, 1)^2
59+
60+
# block_start_indices[n] = size(conn, 2)
61+
# if n == 1
62+
# block_start_indices[n] = 1
63+
# else
64+
# block_start_indices[n] = carry
65+
# end
66+
block_start_indices[n] = start_carry
67+
68+
start_carry = start_carry + size(conn, 1)^2 * size(conn, 2)
69+
block_el_level_sizes[n] = size(conn, 1)^2
6070
end
6171

6272
# convert to NamedTuples so it's easy to index
6373
block_syms = keys(fspace.ref_fes)
64-
block_sizes = NamedTuple{block_syms}(tuple(block_sizes)...)
65-
block_offsets = NamedTuple{block_syms}(tuple(block_offsets)...)
74+
block_start_indices = NamedTuple{block_syms}(tuple(block_start_indices)...)
75+
block_el_level_sizes = NamedTuple{block_syms}(tuple(block_el_level_sizes)...)
6676

6777
# setup pre-allocated arrays based on number of entries found above
6878
Is = Vector{Int64}(undef, n_entries)
@@ -100,7 +110,7 @@ function SparsityPattern(dof::DofManager)
100110
return SparsityPattern(
101111
Is, Js,
102112
unknown_dofs,
103-
block_sizes, block_offsets,
113+
block_start_indices, block_el_level_sizes,
104114
# cache arrays
105115
klasttouch, csrrowptr, csrcolval, csrnzval,
106116
# additional cache arrays

test/poisson/TestPoisson.jl

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using Adapt
2+
using AMDGPU
13
using Exodus
24
using FiniteElementContainers
35
using StaticArrays
@@ -126,3 +128,97 @@ function test_poisson_neumann(
126128
# rm(output_file; force=true)
127129
display(solver.timer)
128130
end
131+
132+
function test_poisson_dirichlet_multi_block_quad4_quad4(
133+
dev, use_condensed,
134+
nsolver, lsolver
135+
)
136+
mesh = UnstructuredMesh(Base.source_dir() * "/poisson/multi_block_mesh_quad4_quad4.g")
137+
V = FunctionSpace(mesh, H1Field, Lagrange)
138+
physics = Poisson()
139+
props = create_properties(physics)
140+
u = ScalarFunction(V, :u)
141+
asm = SparseMatrixAssembler(u; use_condensed=use_condensed)
142+
143+
# setup and update bcs
144+
dbcs = DirichletBC[
145+
DirichletBC(:u, :boundary, bc_func)
146+
]
147+
148+
# setup the parameters
149+
p = create_parameters(mesh, asm, physics, props; dirichlet_bcs=dbcs)
150+
151+
if dev != cpu
152+
p = p |> dev
153+
asm = asm |> dev
154+
end
155+
156+
# setup solver and integrator
157+
solver = nsolver(lsolver(asm))
158+
integrator = QuasiStaticIntegrator(solver)
159+
evolve!(integrator, p)
160+
161+
if dev != cpu
162+
p = p |> cpu
163+
end
164+
165+
U = p.h1_field
166+
167+
pp = PostProcessor(mesh, output_file, u)
168+
write_times(pp, 1, 0.0)
169+
write_field(pp, 1, ("u",), U)
170+
close(pp)
171+
172+
# if !Sys.iswindows()
173+
# @test exodiff(output_file, gold_file)
174+
# end
175+
rm(output_file; force=true)
176+
display(solver.timer)
177+
end
178+
179+
function test_poisson_dirichlet_multi_block_quad4_tri3(
180+
dev, use_condensed,
181+
nsolver, lsolver
182+
)
183+
mesh = UnstructuredMesh(Base.source_dir() * "/poisson/multi_block_mesh_quad4_tri3.g")
184+
V = FunctionSpace(mesh, H1Field, Lagrange)
185+
physics = Poisson()
186+
props = create_properties(physics)
187+
u = ScalarFunction(V, :u)
188+
asm = SparseMatrixAssembler(u; use_condensed=use_condensed)
189+
190+
# setup and update bcs
191+
dbcs = DirichletBC[
192+
DirichletBC(:u, :boundary, bc_func)
193+
]
194+
195+
# setup the parameters
196+
p = create_parameters(mesh, asm, physics, props; dirichlet_bcs=dbcs)
197+
198+
if dev != cpu
199+
p = p |> dev
200+
asm = asm |> dev
201+
end
202+
203+
# setup solver and integrator
204+
solver = nsolver(lsolver(asm))
205+
integrator = QuasiStaticIntegrator(solver)
206+
evolve!(integrator, p)
207+
208+
if dev != cpu
209+
p = p |> cpu
210+
end
211+
212+
U = p.h1_field
213+
214+
pp = PostProcessor(mesh, output_file, u)
215+
write_times(pp, 1, 0.0)
216+
write_field(pp, 1, ("u",), U)
217+
close(pp)
218+
219+
# if !Sys.iswindows()
220+
# @test exodiff(output_file, gold_file)
221+
# end
222+
rm(output_file; force=true)
223+
display(solver.timer)
224+
end
23.3 KB
Binary file not shown.
24.3 KB
Binary file not shown.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
reset
2+
3+
create surface rectangle width 1 height 1 zplane
4+
Surface 1 Move X 0.5 Y 0.5
5+
6+
create surface circle radius 0.25 zplane
7+
Surface 2 Move X 0.5 Y 0.5
8+
9+
subtract body 2 from body 1 keep_tool
10+
11+
imprint body all
12+
merge tol 1e-6
13+
merge all
14+
15+
surface 2 scheme trimesh
16+
surface 2 size 0.05
17+
surface 3 size 0.05
18+
19+
mesh surface 3
20+
mesh surface 2
21+
22+
block 1 add surface 3
23+
block 2 add surface 2
24+
25+
block 1 name "block_1"
26+
block 2 name "block_2"
27+
28+
block 1 element type quad4
29+
block 2 element type tri3
30+
#block 2 element type quad4
31+
32+
nodeset 1 add curve 1 2 3 4
33+
nodeset 1 name "boundary"
34+
sideset 1 add curve 1 2 3 4
35+
sideset 1 name "boundary"
36+
37+
#export genesis "multi_block_mesh_quad4_quad4.g" overwrite
38+
export genesis "multi_block_mesh_quad4_tri3.g" overwrite

test/runtests.jl

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -35,30 +35,37 @@ include("TestPhysics.jl")
3535
include("poisson/TestPoisson.jl")
3636

3737
cg_solver = x -> IterativeLinearSolver(x, :CgSolver)
38-
38+
condensed = [false, true]
39+
lsolvers = [cg_solver, DirectLinearSolver]
3940
# cpu tests
40-
test_poisson_dirichlet(cpu, false, NewtonSolver, DirectLinearSolver)
41-
test_poisson_dirichlet(cpu, true, NewtonSolver, DirectLinearSolver)
42-
test_poisson_dirichlet(cpu, false, NewtonSolver, cg_solver)
43-
test_poisson_dirichlet(cpu, true, NewtonSolver, cg_solver)
44-
test_poisson_neumann(cpu, false, NewtonSolver, DirectLinearSolver)
45-
test_poisson_neumann(cpu, true, NewtonSolver, DirectLinearSolver)
46-
test_poisson_neumann(cpu, false, NewtonSolver, cg_solver)
47-
test_poisson_neumann(cpu, true, NewtonSolver, cg_solver)
48-
49-
if AMDGPU.functional()
50-
test_poisson_dirichlet(rocm, false, NewtonSolver, cg_solver)
51-
test_poisson_dirichlet(rocm, true, NewtonSolver, cg_solver)
52-
test_poisson_neumann(rocm, false, NewtonSolver, cg_solver)
53-
test_poisson_neumann(rocm, true, NewtonSolver, cg_solver)
41+
for cond in condensed
42+
for lsolver in lsolvers
43+
test_poisson_dirichlet(cpu, cond, NewtonSolver, lsolver)
44+
test_poisson_dirichlet_multi_block_quad4_quad4(cpu, cond, NewtonSolver, lsolver)
45+
test_poisson_dirichlet_multi_block_quad4_tri3(cpu, cond, NewtonSolver, lsolver)
46+
test_poisson_neumann(cpu, cond, NewtonSolver, lsolver)
47+
end
5448
end
5549

56-
if CUDA.functional()
57-
test_poisson_dirichlet(cuda, false, NewtonSolver, cg_solver)
58-
test_poisson_dirichlet(cuda, true, NewtonSolver, cg_solver)
59-
test_poisson_neumann(cuda, false, NewtonSolver, cg_solver)
60-
test_poisson_neumann(cuda, true, NewtonSolver, cg_solver)
50+
if AMDGPU.functional()
51+
for cond in condensed
52+
test_poisson_dirichlet(rocm, cond, NewtonSolver, cg_solver)
53+
test_poisson_dirichlet_multi_block_quad4_quad4(rocm, cond, NewtonSolver, cg_solver)
54+
test_poisson_dirichlet_multi_block_quad4_tri3(rocm, cond, NewtonSolver, cg_solver)
55+
test_poisson_neumann(rocm, cond, NewtonSolver, cg_solver)
56+
end
57+
# test_poisson_dirichlet(rocm, false, NewtonSolver, cg_solver)
58+
# test_poisson_dirichlet(rocm, true, NewtonSolver, cg_solver)
59+
# test_poisson_neumann(rocm, false, NewtonSolver, cg_solver)
60+
# test_poisson_neumann(rocm, true, NewtonSolver, cg_solver)
6161
end
62+
63+
# if CUDA.functional()
64+
# test_poisson_dirichlet(cuda, false, NewtonSolver, cg_solver)
65+
# test_poisson_dirichlet(cuda, true, NewtonSolver, cg_solver)
66+
# test_poisson_neumann(cuda, false, NewtonSolver, cg_solver)
67+
# test_poisson_neumann(cuda, true, NewtonSolver, cg_solver)
68+
# end
6269
end
6370

6471
@testset ExtendedTestSet "Mechanics Problem" begin

0 commit comments

Comments
 (0)