Assembly

When the local stiffness matrix and force vector have been calculated they should be assembled into the global stiffness matrix and the global force vector. This is just a matter of adding the local matrix and vector to the global one, at the correct place. Consider e.g. assembling the local stiffness matrix ke and the local force vector fe into the global K and f respectively. These should be assembled into the row/column which corresponds to the degrees of freedom for the cell:

K[celldofs, celldofs] += ke
f[celldofs]           += fe

where celldofs is the vector containing the degrees of freedom for the cell. The method above is very inefficient – it is especially costly to index into the sparse matrix K directly. Therefore we will instead use an Assembler that will help with the assembling of both the global stiffness matrix and the global force vector. It is also often convenient to create the sparse matrix just once, and reuse the allocated matrix. This is useful for e.g. iterative solvers or time dependent problems where the sparse matrix structure, or Sparsity Pattern will stay the same in every iteration/ time step.

Sparsity Pattern

Given a DofHandler we can obtain the corresponding sparse matrix by using the create_sparsity_pattern function. This will setup a SparseMatrixCSC with stored values on all the places corresponding to the degree of freedom numbering in the DofHandler. This means that when we assemble into the global stiffness matrix there is no need to change the internal representation of the sparse matrix since the sparse structure will not change.

Often the finite element problem is symmetric and will result in a symmetric sparse matrix. This information is often something that the sparse solver can take advantage of. If the solver only needs half the matrix there is no need to assemble both halves. For this purpose there is a create_symmetric_sparsity_pattern function that will only create the upper half of the matrix, and return a Symmetric wrapped SparseMatrixCSC.

Given a DofHandler dh we can obtain the (symmetric) sparsity pattern as

K = create_sparsity_pattern(dh)
K = create_symmetric_sparsity_pattern(dh)

The returned sparse matrix will be used together with an Assembler, which assembles efficiently into the matrix, without modifying the internal representation.

Assembler

Assembling efficiently into the sparse matrix requires some extra workspace. This workspace is allocated in an Assembler. start_assemble is used to create an Assembler:

A = start_assemble(K)
A = start_assemble(K, f)

where K is the global stiffness matrix, and f the global force vector. It is optional to give the force vector to the assembler – sometimes there is no need to assemble a global force vector.

fds

assemble!(A, celldofs, ke)
assemble!(A, celldofs, ke, fe)

To give a more

K = create_sparsity_pattern(dh)
f = zeros(ndofs(dh))
A = start_assemble(K, f)

for cell in CellIterator(dh)
    ke, fe = ...
    assemble!(A, celldofs(cell), ke, fe)
end