Skip to content

Commit 9caa3a0

Browse files
authored
Merge pull request #43 from gridap/extend_assembler_to_multiple_fields
This PR extends the FE assembly routines to support weak forms with several terms, which are integrated in different domains. E.g., problems with Neumann BCs. This PR addresses issue #42
2 parents e86ad2f + d7d54c0 commit 9caa3a0

16 files changed

+271
-105
lines changed

NEWS.md

+4
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111
- `NonIterableCellMap`, a cell map that has iteration intentionally disabled. Available since commit [956a537](https://github.com/gridap/Gridap.jl/commit/956a5374db6c3b9546e85e0d4d49ae0560057565).
1212
- `BoundaryTriangulation` an integration mesh used to integrate `CellField` and `CellBasis` objects restricted on a surface. Available since commit [e981f3c](https://github.com/gridap/Gridap.jl/commit/e981f3c221f3624cfc6764efa47f22652fc22b4f)
1313
- Function `restrict` for restricting `CellField` and `CellBasis` objects to surfaces. Available since commit [e981f3c](https://github.com/gridap/Gridap.jl/commit/e981f3c221f3624cfc6764efa47f22652fc22b4f)
14+
- `IdentityCellNumber`, an indexable cell number that simply returns the given index. Also efficient implementation of `reindex` for this type (i.e. do nothing). Available since commit [b6b4c32](https://github.com/gridap/Gridap.jl/commit/b6b4c32c8c4b826a41ba64c770ac8a1c394e16f0)
1415

1516
### Changed
17+
- Changed the signature of `assemble`, `apply_constraints`, `apply_constraints_rows`, and `apply_constraints_cols` to support FE assembly of several terms, which are integrated in different domains. The old API of `asseble` is still functional, but not for the `apply_constraints` et al.
18+
19+
1620
### Removed
1721
### Deprecated
1822
### Fixed

src/CellValues/IdentityCellNumbers.jl

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
module IdentityCellNumbers
2+
3+
using Gridap
4+
5+
export IdentityCellNumber
6+
import Gridap: reindex
7+
import Base: size
8+
import Base: getindex
9+
10+
struct IdentityCellNumber{T} <: IndexCellValue{T,1}
11+
length::Int
12+
end
13+
14+
function IdentityCellNumber(::Type{T},l::Integer) where T <: Integer
15+
IdentityCellNumber{T}(l)
16+
end
17+
18+
function getindex(c::IdentityCellNumber{T},i::Integer) where T
19+
@assert i > 0
20+
@assert i <= c.length
21+
j::T = i
22+
j
23+
end
24+
25+
size(c::IdentityCellNumber) = (c.length,)
26+
27+
function reindex(values::IndexCellValue, indices::IdentityCellNumber)
28+
@assert length(values) == length(indices)
29+
values
30+
end
31+
32+
end # module

src/CellValues/files.jl

+3
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,7 @@ include("CompressedCellValues.jl")
5353
include("NonIterableCellMaps.jl")
5454
@reexport using Gridap.NonIterableCellMaps
5555

56+
include("IdentityCellNumbers.jl")
57+
@reexport using Gridap.IdentityCellNumbers
58+
5659

src/FESpaces/Assemblers.jl

+66-56
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,6 @@ export SparseMatrixAssembler
1111
export assemble
1212
export assemble!
1313

14-
#@fverdugo for the moment the abstract interface of Assembler
15-
# (and therefore its concrete implementations)
16-
# assumes single field, and single term
17-
1814
"""
1915
Abstract assembly operator
2016
Parametrized by the type of returned matrix and vector
@@ -24,31 +20,53 @@ abstract type Assembler{M<:AbstractMatrix,V<:AbstractVector} end
2420
"""
2521
Assembly of a vector allocating output
2622
"""
27-
function assemble(::Assembler{M,V},::CellVector)::V where {M,V}
23+
function assemble(
24+
::Assembler{M,V},
25+
::Vararg{Tuple{<:CellVector,<:CellNumber}})::V where {M,V}
2826
@abstractmethod
2927
end
3028

3129
"""
3230
Assembly of a matrix allocating output
3331
"""
34-
function assemble(::Assembler{M,V},::CellMatrix)::M where {M,V}
32+
function assemble(
33+
::Assembler{M,V},
34+
::Vararg{Tuple{<:CellMatrix,<:CellNumber}})::M where {M,V}
3535
@abstractmethod
3636
end
3737

3838
"""
3939
In-place assembly of a vector (allows optimizations)
4040
"""
41-
function assemble!(::V,::Assembler{M,V},::CellVector)::V where {M,V}
41+
function assemble!(
42+
::V,
43+
::Assembler{M,V},
44+
::Vararg{Tuple{<:CellVector,<:CellNumber}})::V where {M,V}
4245
@abstractmethod
4346
end
4447

4548
"""
4649
In-place assembly of a matrix (allows a LOT of optimizations)
4750
"""
48-
function assemble!(::M,::Assembler{M,V},::CellMatrix)::M where {M,V}
51+
function assemble!(
52+
::M,
53+
::Assembler{M,V},
54+
::Vararg{Tuple{<:CellMatrix,<:CellNumber}})::M where {M,V}
4955
@abstractmethod
5056
end
5157

58+
function assemble(a::Assembler,cv::CellArray)
59+
l = length(cv)
60+
ide = IdentityCellNumber(Int,l)
61+
assemble(a,(cv,ide))
62+
end
63+
64+
function assemble!(r,a::Assembler,cv::CellArray)
65+
l = length(cv)
66+
ide = IdentityCellNumber(Int,l)
67+
assemble!(r,a,(cv,ide))
68+
end
69+
5270
"""
5371
Assembler that produces SparseMatrices from the SparseArrays package
5472
"""
@@ -62,19 +80,28 @@ function SparseMatrixAssembler(test::FESpace{D,Z,T}, trial::FESpace{D,Z,T}) wher
6280
SparseMatrixAssembler{E}(trial,test)
6381
end
6482

65-
function assemble(this::SparseMatrixAssembler{E}, vals::CellVector) where E
83+
function assemble(
84+
this::SparseMatrixAssembler{E},
85+
vals::Vararg{Tuple{<:CellVector,<:CellNumber}}) where E
86+
6687
n = num_free_dofs(this.testfesp)
6788
vec = zeros(E,n)
68-
assemble!(vec,this,vals)
89+
assemble!(vec,this,vals...)
6990
vec
7091
end
7192

7293
function assemble!(
73-
vec::Vector{E},this::SparseMatrixAssembler{E}, vals::CellVector) where E
74-
_vals = apply_constraints(this.testfesp, vals)
75-
_rows = celldofids(this.testfesp)
94+
vec::Vector{E},
95+
this::SparseMatrixAssembler{E},
96+
allvals::Vararg{Tuple{<:CellVector,<:CellNumber}}) where E
97+
7698
vec .= zero(E)
77-
_assemble_vector!(vec, _vals, _rows)
99+
rows = celldofids(this.testfesp)
100+
for (vals, cellids) in allvals
101+
_vals = apply_constraints(this.testfesp, vals, cellids)
102+
_rows = reindex(rows,cellids)
103+
_assemble_vector!(vec, _vals, _rows)
104+
end
78105
end
79106

80107
function _assemble_vector!(vec,vals,rows)
@@ -87,17 +114,28 @@ function _assemble_vector!(vec,vals,rows)
87114
end
88115
end
89116

90-
function assemble(this::SparseMatrixAssembler{E}, vals::CellMatrix) where E
91-
_vals = apply_constraints_rows(this.testfesp, vals)
92-
rows_m = celldofids(this.testfesp)
93-
_vals = apply_constraints_cols(this.trialfesp, _vals)
94-
cols_m = celldofids(this.trialfesp)
95-
args = _assemble_sparse_matrix_values(_vals,rows_m,cols_m,Int,E)
96-
sparse(args...)
97-
end
117+
function assemble(
118+
this::SparseMatrixAssembler{E},
119+
allvals::Vararg{Tuple{<:CellMatrix,<:CellNumber}}) where E
98120

99-
function _assemble_sparse_matrix_values(vals,rows,cols,I,E)
121+
I = Int
100122
aux_row = I[]; aux_col = I[]; aux_val = E[]
123+
124+
_rows_m = celldofids(this.testfesp)
125+
_cols_m = celldofids(this.trialfesp)
126+
127+
for (vals,cellids) in allvals
128+
_vals = apply_constraints_rows(this.testfesp, vals, cellids)
129+
rows_m = reindex(_rows_m, cellids)
130+
vals_m = apply_constraints_cols(this.trialfesp, _vals, cellids)
131+
cols_m = reindex(_cols_m, cellids)
132+
_assemble_sparse_matrix_values!(
133+
aux_row,aux_col,aux_val,vals_m,rows_m,cols_m)
134+
end
135+
sparse(aux_row,aux_col,aux_val)
136+
end
137+
138+
function _assemble_sparse_matrix_values!(aux_row,aux_col,aux_val,vals,rows,cols)
101139
for (rows_c, cols_c, vals_c) in zip(rows,cols,vals)
102140
for (j,gidcol) in enumerate(cols_c)
103141
if gidcol > 0
@@ -111,44 +149,16 @@ function _assemble_sparse_matrix_values(vals,rows,cols,I,E)
111149
end
112150
end
113151
end
114-
(aux_row, aux_col, aux_val)
115152
end
116153

117154
function assemble!(
118-
mat::SparseMatrixCSC{E}, this::SparseMatrixAssembler{E}, vals::CellMatrix) where E
155+
mat::SparseMatrixCSC{E},
156+
this::SparseMatrixAssembler{E},
157+
vals::Vararg{Tuple{<:CellMatrix,<:CellNumber}}) where E
119158
# This routine can be optimized a lot taking into a count the sparsity graph of mat
120159
# For the moment we create an intermediate matrix and then transfer the nz values
121-
m = assemble(this,vals)
160+
m = assemble(this,vals...)
122161
mat.nzval .= m.nzval
123162
end
124163

125-
# Draft of multi field assembler
126-
#function _assemble_sparse_matrix_values(mf_vals,mf_rows,mf_cols,I,E)
127-
# aux_row = I[]; aux_col = I[]; aux_val = E[]
128-
# for (mf_rows_c, mf_cols_c, mf_vals_c) in zip(mf_rows,mf_cols,mf_vals)
129-
# for (vals_c, (ifield, jfield)) in eachblock(mf_vals_c)
130-
# rows_c = mf_rows_c[ifield]
131-
# cols_c = mf_cols_c[jfield]
132-
# row_offset = row_offsets[ifield]
133-
# col_offset = col_offsets[jfield]
134-
# _asseble_cell_values!(aux_row,aux_col,aux_val,rows_c,cols_c,vals_c,col_offset,row_offset)
135-
# end
136-
# end
137-
# (aux_row, aux_col, aux_val)
138-
#end
139-
#
140-
#function _asseble_cell_values!(aux_row,aux_col,aux_val,rows_c,cols_c,vals_c,col_offset,row_offset)
141-
# for (j,gidcol) in enumerate(cols_c)
142-
# if gidcol > 0
143-
# for (i,gidrow) in enumerate(rows_c)
144-
# if gidrow > 0
145-
# push!(aux_row, gidrow+row_offset)
146-
# push!(aux_col, gidcol+col_offset)
147-
# push!(aux_val, vals_c[i,j])
148-
# end
149-
# end
150-
# end
151-
# end
152-
#end
153-
154-
end # module Assemblers
164+
end # module

src/FESpaces/FESpaces.jl

+12-12
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,15 @@ num_diri_dofs(::FESpace)::Int = @abstractmethod
5151

5252
diri_tags(::FESpace)::Vector{Int} = @abstractmethod
5353

54-
function apply_constraints(::FESpace, cellvec::CellVector)::CellVector
54+
function apply_constraints(::FESpace, cellvec::CellVector, cellids::CellNumber)::CellVector
5555
@abstractmethod
5656
end
5757

58-
function apply_constraints_rows(::FESpace, cellmat::CellMatrix)::CellMatrix
58+
function apply_constraints_rows(::FESpace, cellmat::CellMatrix, cellids::CellNumber)::CellMatrix
5959
@abstractmethod
6060
end
6161

62-
function apply_constraints_cols(::FESpace, cellmat::CellMatrix)::CellMatrix
62+
function apply_constraints_cols(::FESpace, cellmat::CellMatrix, cellids::CellNumber)::CellMatrix
6363
@abstractmethod
6464
end
6565

@@ -279,18 +279,18 @@ num_diri_dofs(f::FESpaceWithDirichletData) = num_diri_dofs(f.fespace)
279279
diri_tags(f::FESpaceWithDirichletData) = diri_tags(f.fespace)
280280

281281
function apply_constraints(
282-
f::FESpaceWithDirichletData, cellvec::CellVector)
283-
apply_constraints(f.fespace,cellvec)
282+
f::FESpaceWithDirichletData, cellvec::CellVector, cellids::CellNumber)
283+
apply_constraints(f.fespace,cellvec,cellids)
284284
end
285285

286286
function apply_constraints_rows(
287-
f::FESpaceWithDirichletData, cellmat::CellMatrix)
288-
apply_constraints_rows(f.fespace,cellmat)
287+
f::FESpaceWithDirichletData, cellmat::CellMatrix, cellids::CellNumber)
288+
apply_constraints_rows(f.fespace,cellmat,cellids)
289289
end
290290

291291
function apply_constraints_cols(
292-
f::FESpaceWithDirichletData, cellmat::CellMatrix)
293-
apply_constraints_cols(f.fespace,cellmat)
292+
f::FESpaceWithDirichletData, cellmat::CellMatrix, cellids::CellNumber)
293+
apply_constraints_cols(f.fespace,cellmat,cellids)
294294
end
295295

296296
function celldofids(f::FESpaceWithDirichletData)
@@ -377,17 +377,17 @@ num_diri_dofs(this::ConformingFESpace) = this.num_diri_dofs
377377
diri_tags(f::ConformingFESpace) = f.diri_tags
378378

379379
function apply_constraints(
380-
this::ConformingFESpace, cellvec::CellVector)
380+
this::ConformingFESpace, cellvec::CellVector, cellids::CellNumber)
381381
cellvec
382382
end
383383

384384
function apply_constraints_rows(
385-
this::ConformingFESpace, cellmat::CellMatrix)
385+
this::ConformingFESpace, cellmat::CellMatrix, cellids::CellNumber)
386386
cellmat
387387
end
388388

389389
function apply_constraints_cols(
390-
this::ConformingFESpace, cellmat::CellMatrix)
390+
this::ConformingFESpace, cellmat::CellMatrix, cellids::CellNumber)
391391
cellmat
392392
end
393393

0 commit comments

Comments
 (0)