Skip to content

Commit 5e24185

Browse files
authored
Modifying transient_heat_equation.jl
Added reference to fe_intro for derivation and discretisation. Changed notation of trial functions to be consistent with previous tutorials (v -> δu). Modified doassembly functions into one function for K, M and f. (If there is a reason why they were in two different function, please let me know since I am new to this library).
1 parent 2ecfdd4 commit 5e24185

1 file changed

Lines changed: 25 additions & 50 deletions

File tree

docs/src/literate-tutorials/transient_heat_equation.jl

Lines changed: 25 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -35,22 +35,28 @@
3535
# ```
3636
# The semidiscrete weak form is given by
3737
# ```math
38-
# \int_{\Omega}v \frac{\partial u}{\partial t} \ \mathrm{d}\Omega + \int_{\Omega} k \nabla v \cdot \nabla u \ \mathrm{d}\Omega = \int_{\Omega} f v \ \mathrm{d}\Omega,
38+
# \int_{\Omega}\delta u \frac{\partial u}{\partial t} \ \mathrm{d}\Omega + \int_{\Omega} k \nabla \delta u \cdot \nabla u \ \mathrm{d}\Omega = \int_{\Omega} f \delta u \ \mathrm{d}\Omega,
3939
# ```
40-
# where $v$ is a suitable test function. Now, we still need to discretize the time derivative. An implicit Euler scheme is applied,
40+
# where $\delta u$ is a suitable test function. Now, we still need to discretize the time derivative. An implicit Euler scheme is applied,
4141
# which yields:
4242
# ```math
43-
# \int_{\Omega} v\, u_{n+1}\ \mathrm{d}\Omega + \Delta t\int_{\Omega} k \nabla v \cdot \nabla u_{n+1} \ \mathrm{d}\Omega = \Delta t\int_{\Omega} f v \ \mathrm{d}\Omega + \int_{\Omega} v \, u_{n} \ \mathrm{d}\Omega.
43+
# \int_{\Omega} \delta u\, u_{n+1}\ \mathrm{d}\Omega + \Delta t\int_{\Omega} k \nabla \delta u \cdot \nabla u_{n+1} \ \mathrm{d}\Omega = \Delta t\int_{\Omega} f \delta u \ \mathrm{d}\Omega + \int_{\Omega} \delta u \, u_{n} \ \mathrm{d}\Omega.
4444
# ```
4545
# If we assemble the discrete operators, we get the following algebraic system:
4646
# ```math
4747
# \mathbf{M} \mathbf{u}_{n+1} + Δt \mathbf{K} \mathbf{u}_{n+1} = Δt \mathbf{f} + \mathbf{M} \mathbf{u}_{n}
4848
# ```
49+
# Here, `M` refers to the so called mass matrix, which always occurs in time related terms, i.e.
50+
# ```math
51+
# M_{ij} = \int_{\Omega} \delta u_i \, u_j \ \mathrm{d}\Omega,
52+
# ```
53+
# where $u_j$ and $\delta u_i$ are the shape functions of the trial and test functions, respectively.
4954
# In this example we apply the boundary conditions to the assembled discrete operators (mass matrix $\mathbf{M}$ and stiffnes matrix $\mathbf{K}$)
5055
# only once. We utilize the fact that in finite element computations Dirichlet conditions can be applied by
5156
# zero out rows and columns that correspond
5257
# to a prescribed dof in the system matrix ($\mathbf{A} = Δt \mathbf{K} + \mathbf{M}$) and setting the value of the right-hand side vector to the value
53-
# of the Dirichlet condition. Thus, we only need to apply in every time step the Dirichlet condition to the right-hand side of the problem.
58+
# of the Dirichlet condition. Thus, we only need to apply in every time step the Dirichlet condition to the right-hand side of the problem. For more details
59+
# on the derivation and discretisation, see the [Introduction to FEM](@ref fe-intro).
5460
#-
5561
# ## Commented program
5662
#
@@ -75,11 +81,6 @@ add!(dh, :u, ip)
7581
close!(dh);
7682

7783
# By means of the `DofHandler` we can allocate the needed `SparseMatrixCSC`.
78-
# `M` refers here to the so called mass matrix, which always occurs in time related terms, i.e.
79-
# ```math
80-
# M_{ij} = \int_{\Omega} v_i \, u_j \ \mathrm{d}\Omega,
81-
# ```
82-
# where $u_i$ and $v_j$ are trial and test functions, respectively.
8384
K = allocate_matrix(dh);
8485
M = allocate_matrix(dh);
8586
# We also preallocate the right hand side
@@ -107,18 +108,21 @@ close!(ch)
107108
update!(ch, 0.0);
108109

109110
# ### Assembling the linear system
110-
# As in the heat equation example we define a `doassemble!` function that assembles the diffusion parts of the equation:
111-
function doassemble_K!(K::SparseMatrixCSC, f::Vector, cellvalues::CellValues, dh::DofHandler)
111+
# As in the [heat equation example](@ref heat_equation.jl) we define a `doassemble!` function that assembles the diffusion and diffusive parts of the equation:
112+
function doassemble!(K::SparseMatrixCSC, M::SparseMatrixCSC, f::Vector, cellvalues::CellValues, dh::DofHandler)
112113

113114
n_basefuncs = getnbasefunctions(cellvalues)
114115
Ke = zeros(n_basefuncs, n_basefuncs)
116+
Me = zeros(n_basefuncs, n_basefuncs)
115117
fe = zeros(n_basefuncs)
116118

117119
assembler = start_assemble(K, f)
118-
120+
assembler_M = start_assemble(M)
121+
119122
for cell in CellIterator(dh)
120123

121124
fill!(Ke, 0)
125+
fill!(Me, 0)
122126
fill!(fe, 0)
123127

124128
reinit!(cellvalues, cell)
@@ -127,56 +131,27 @@ function doassemble_K!(K::SparseMatrixCSC, f::Vector, cellvalues::CellValues, dh
127131
= getdetJdV(cellvalues, q_point)
128132

129133
for i in 1:n_basefuncs
130-
v = shape_value(cellvalues, q_point, i)
131-
v = shape_gradient(cellvalues, q_point, i)
132-
fe[i] += 0.1 * v *
134+
δu = shape_value(cellvalues, q_point, i)
135+
δu = shape_gradient(cellvalues, q_point, i)
136+
fe[i] += 0.1 * δu *
133137
for j in 1:n_basefuncs
138+
u = shape_value(cellvalues, q_point, j)
134139
∇u = shape_gradient(cellvalues, q_point, j)
135-
Ke[i, j] += 1.0e-3 * (∇v ∇u) *
140+
Ke[i, j] += 1.0e-3 * (∇δu ∇u) *
141+
Me[i, j] += (δu * u) *
136142
end
137143
end
138144
end
139145

140146
assemble!(assembler, celldofs(cell), Ke, fe)
147+
assemble!(assembler_M, celldofs(cell), Me)
141148
end
142-
return K, f
143-
end
144-
#md nothing # hide
145-
# In addition to the diffusive part, we also need a function that assembles the mass matrix `M`.
146-
function doassemble_M!(M::SparseMatrixCSC, cellvalues::CellValues, dh::DofHandler)
147-
148-
n_basefuncs = getnbasefunctions(cellvalues)
149-
Me = zeros(n_basefuncs, n_basefuncs)
150-
151-
assembler = start_assemble(M)
152-
153-
for cell in CellIterator(dh)
154-
155-
fill!(Me, 0)
156-
157-
reinit!(cellvalues, cell)
158-
159-
for q_point in 1:getnquadpoints(cellvalues)
160-
= getdetJdV(cellvalues, q_point)
161-
162-
for i in 1:n_basefuncs
163-
v = shape_value(cellvalues, q_point, i)
164-
for j in 1:n_basefuncs
165-
u = shape_value(cellvalues, q_point, j)
166-
Me[i, j] += (v * u) *
167-
end
168-
end
169-
end
170-
171-
assemble!(assembler, celldofs(cell), Me)
172-
end
173-
return M
149+
return K, M, f
174150
end
175151
#md nothing # hide
176152
# ### Solution of the system
177153
# We first assemble all parts in the prior allocated `SparseMatrixCSC`.
178-
K, f = doassemble_K!(K, f, cellvalues, dh)
179-
M = doassemble_M!(M, cellvalues, dh)
154+
K, M, f = doassemble!(K, M, f, cellvalues, dh)
180155
A = (Δt .* K) + M;
181156
# Now, we need to save all boundary condition related values of the unaltered system matrix `A`, which is done
182157
# by `get_rhs_data`. The function returns a `RHSData` struct, which contains all needed information to apply

0 commit comments

Comments
 (0)