Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add apply_analytical! function #532

Merged
merged 49 commits into from
Dec 16, 2022
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
0b22bcc
Add initial_conditions!
KnutAM Oct 29, 2022
8ef8b48
Add tests and fix minor bug
KnutAM Oct 30, 2022
3320f89
Clean code and move overloads
KnutAM Oct 30, 2022
161a357
Make code more clear
KnutAM Oct 30, 2022
b72ff7b
Remove Returns to support 1.6
KnutAM Oct 30, 2022
027eb41
Rename initial_conditions->apply_analytical!
KnutAM Oct 30, 2022
5d5b93f
Update transient heat flow example
KnutAM Oct 30, 2022
c96b88b
Improve Exception handling and add tests
KnutAM Oct 30, 2022
269d867
Fix tests for julia 1.6
KnutAM Oct 30, 2022
e327d75
Add colorbar
KnutAM Oct 30, 2022
106f049
Merge branch 'master' into kam/initial_conditions
KnutAM Oct 30, 2022
2887dc5
Update docs and make internal internal
KnutAM Oct 30, 2022
15d12d8
Reduce gif size
KnutAM Oct 30, 2022
3957086
Use gifsky and support svg images in examples
KnutAM Nov 1, 2022
9203026
Fix typos in example
KnutAM Nov 1, 2022
129e8c3
Add documentation
KnutAM Nov 1, 2022
faffed0
Use apply_analytical! in homogenization example
KnutAM Nov 1, 2022
e95ac23
Add semicolon to prevent output in example
KnutAM Nov 1, 2022
7714b89
Clarify DAE definition
KnutAM Nov 1, 2022
3d3165b
Rename to transfer_solution!
KnutAM Nov 4, 2022
9b7d775
Use u instead of x for unknown dof values in initial condition docs
KnutAM Nov 4, 2022
8e1baf0
Reorder args and make fieldname optional
KnutAM Nov 4, 2022
ebca08b
Update docs with new argument order and defaults
KnutAM Nov 4, 2022
a599d05
Revert back to apply_analytical!
KnutAM Nov 8, 2022
28863d8
Add warning about non-nodal interpolations
KnutAM Nov 8, 2022
1170e4f
Update filenames in tests
KnutAM Nov 8, 2022
0ea6420
Improve note-text
KnutAM Nov 8, 2022
cecbdfb
Merge branch 'master' into kam/initial_conditions
KnutAM Dec 11, 2022
b49bf62
fix example text mistake
KnutAM Dec 11, 2022
976e5ba
Move gif and svg to gh-pages/assets
KnutAM Dec 11, 2022
51d3f7e
Apply suggestions from code review
KnutAM Dec 12, 2022
c574a06
Julia formatting
KnutAM Dec 12, 2022
7f7b929
Require fieldname also for single-field problems
KnutAM Dec 12, 2022
450e9c5
Put apply_analytical tests last, before examples
KnutAM Dec 12, 2022
cacce2f
Add changelog [no ci]
KnutAM Dec 12, 2022
211c8ac
Merge branch 'master' into kam/initial_conditions
KnutAM Dec 12, 2022
494a2e1
Change argument order in apply_analytical
KnutAM Dec 12, 2022
10a7922
Introduce CellDofValues
KnutAM Dec 12, 2022
f95c6df
Revert bad autoformatting
KnutAM Dec 15, 2022
2166d14
Manual tuning back autoformatting
KnutAM Dec 15, 2022
a9bef3d
Fix more autoformat issues
KnutAM Dec 15, 2022
1bd56ae
Set whitespace_in_kwargs=false
KnutAM Dec 15, 2022
6e64ff8
fixes more autoformat
KnutAM Dec 15, 2022
cc92f33
Add simplified constructor for QuadratureRule
KnutAM Dec 15, 2022
da7e532
Use CellScalarValues instead of custom type
KnutAM Dec 15, 2022
60e3cb4
Reset cell_values.jl formatting
KnutAM Dec 15, 2022
4f85093
Final formatting
KnutAM Dec 15, 2022
3387146
Update src/Quadrature/quadrature.jl
KnutAM Dec 15, 2022
b736685
Reflect required dim in QuadratureRule
KnutAM Dec 15, 2022
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
2 changes: 1 addition & 1 deletion docs/generate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ include("download_resources.jl")
Literate.notebook(input, GENERATEDDIR, preprocess = nbpre, execute = is_ci) # Don't execute locally
end
end
elseif any(endswith.(example, [".png", ".jpg", ".gif"]))
elseif any(endswith.(example, [".png", ".jpg", ".gif", ".svg"]))
cp(joinpath(EXAMPLEDIR, example), joinpath(GENERATEDDIR, example); force=true)
else
@warn "ignoring $example"
Expand Down
6 changes: 1 addition & 5 deletions docs/src/literate/computational_homogenization.jl
Original file line number Diff line number Diff line change
Expand Up @@ -516,16 +516,12 @@ round.(ev; digits=-8)
# Finally, we export the solution and the stress field to a VTK file. For the export we
# also compute the macroscopic part of the displacement.

chM = ConstraintHandler(dh)
add!(chM, Dirichlet(:u, Set(1:getnnodes(grid)), (x, t) -> εᴹ[Int(t)] ⋅ x, [1, 2]))
close!(chM)
uM = zeros(ndofs(dh))

vtk_grid("homogenization", dh) do vtk
for i in 1:3
## Compute macroscopic solution
update!(chM, i)
apply!(uM, chM)
apply_analytical!(uM, dh, :u, x->εᴹ[i] ⋅ x)
## Dirichlet
vtk_point_data(vtk, dh, uM + u.dirichlet[i], "_dirichlet_$i")
vtk_point_data(vtk, projector, σ.dirichlet[i], "σvM_dirichlet_$i")
Expand Down
Binary file modified docs/src/literate/transient_heat.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
184 changes: 184 additions & 0 deletions docs/src/literate/transient_heat_colorbar.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 21 additions & 10 deletions docs/src/literate/transient_heat_equation.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# # Time Dependent Problems
#
# ![](transient_heat.gif)
# ![](transient_heat_colorbar.svg)
#
# *Figure 1*: Visualization of the temperature time evolution on a unit
# square where the prescribed temperature on the upper and lower parts
Expand All @@ -20,8 +21,8 @@
# ```
#
# where $u$ is the unknown temperature field, $k$ the heat conductivity,
# $f$ the heat source and $\Omega$ the domain. For simplicity we set $f = 1$
# and $k = 1$. We define homogeneous Dirichlet boundary conditions along the left and right edge of the domain.
# $f$ the heat source and $\Omega$ the domain. For simplicity, we hard code $f = 0.1$
# and $k = 10^{-3}$. We define homogeneous Dirichlet boundary conditions along the left and right edge of the domain.
# ```math
# u(x,t) = 0 \quad x \in \partial \Omega_1,
# ```
Expand All @@ -34,12 +35,12 @@
# ```
# The semidiscrete weak form is given by
# ```math
# \int_{\Omega}v \frac{\partial u}{\partial t} \ \mathrm{d}\Omega + \int_{\Omega} \nabla v \cdot \nabla u \ \mathrm{d}\Omega = \int_{\Omega} v \ \mathrm{d}\Omega,
# \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,
# ```
# where $v$ is a suitable test function. Now, we still need to discretize the time derivative. An implicit Euler scheme is applied,
# which yields:
# ```math
# \int_{\Omega} v\, u_{n+1}\ \mathrm{d}\Omega + \Delta t\int_{\Omega} \nabla v \cdot \nabla u_{n+1} \ \mathrm{d}\Omega = \Delta t\int_{\Omega} v \ \mathrm{d}\Omega + \int_{\Omega} v \, u_{n} \ \mathrm{d}\Omega.
# \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.
# ```
# If we assemble the discrete operators, we get the following algebraic system:
# ```math
Expand Down Expand Up @@ -91,15 +92,17 @@ f = zeros(ndofs(dh));
max_temp = 100
Δt = 1
T = 200
t_rise = 100
ch = ConstraintHandler(dh);

# Here, we define the boundary condition related to $\partial \Omega_1$.
∂Ω₁ = union(getfaceset.((grid, ), ["left", "right"])...)
dbc = Dirichlet(:u, ∂Ω₁, (x, t) -> 0)
add!(ch, dbc);
# While the next code block corresponds to the linearly increasing temperature description on $\partial \Omega_2$.
# While the next code block corresponds to the linearly increasing temperature description on $\partial \Omega_2$
# untill `t=t_rise`, and then keep constant
KnutAM marked this conversation as resolved.
Show resolved Hide resolved
∂Ω₂ = union(getfaceset.((grid, ), ["top", "bottom"])...)
dbc = Dirichlet(:u, ∂Ω₂, (x, t) -> t*(max_temp/T))
dbc = Dirichlet(:u, ∂Ω₂, (x, t) -> max_temp*clamp(t/t_rise, 0, 1))
KnutAM marked this conversation as resolved.
Show resolved Hide resolved
add!(ch, dbc)
close!(ch)
update!(ch, 0.0);
Expand Down Expand Up @@ -127,10 +130,10 @@ function doassemble_K!(K::SparseMatrixCSC, f::Vector, cellvalues::CellScalarValu
for i in 1:n_basefuncs
v = shape_value(cellvalues, q_point, i)
∇v = shape_gradient(cellvalues, q_point, i)
fe[i] += v * dΩ
fe[i] += 0.1*v * dΩ
KnutAM marked this conversation as resolved.
Show resolved Hide resolved
for j in 1:n_basefuncs
∇u = shape_gradient(cellvalues, q_point, j)
Ke[i, j] += (∇v ⋅ ∇u) * dΩ
Ke[i, j] += 1.e-3*(∇v ⋅ ∇u) * dΩ
KnutAM marked this conversation as resolved.
Show resolved Hide resolved
end
end
end
Expand Down Expand Up @@ -180,16 +183,24 @@ A = (Δt .* K) + M;
# by `get_rhs_data`. The function returns a `RHSData` struct, which contains all needed informations to apply
# the boundary conditions solely on the right-hand-side vector of the problem.
rhsdata = get_rhs_data(ch, A);
# We set the initial time step, denoted by uₙ, to $\mathbf{0}$.
# We set the values at initial time step, denoted by uₙ, to a bubble-shape described by
# $(x_1^2-1)(x_2^2-1)$, such that it is zero at the boundaries and half the max temperature in the center.
KnutAM marked this conversation as resolved.
Show resolved Hide resolved
uₙ = zeros(length(f));
apply_analytical!(uₙ, dh, :u, x->(x[1]^2-1)*(x[2]^2-1)*max_temp);
# Here, we apply **once** the boundary conditions to the system matrix `A`.
apply!(A, ch);

# To store the solution, we initialize a `paraview_collection` (.pvd) file.
pvd = paraview_collection("transient-heat.pvd");
t=0
KnutAM marked this conversation as resolved.
Show resolved Hide resolved
vtk_grid("transient-heat-$t", dh) do vtk
vtk_point_data(vtk, dh, uₙ)
vtk_save(vtk)
pvd[t] = vtk
Comment on lines +198 to +199
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think other examples use https://github.com/jipolanco/WriteVTK.jl/blob/6e528bd6a016efb84f5cb50f2dc43bcdc59ab8d4/src/gridtypes/ParaviewCollection.jl#L59 but since I don't see that in the WriteVTK documentation maybe it is deprecated or discouraged? Edit: I see that this approach was also used later in this file, so let's at least have it consistent (if you change here, also change below).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't seen collection_add_timestep before. What example did you think of?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My research code I guess :D I thought we had some other time dependent problems. It used to be the only advertised way before, but maybe that has changed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

end

# At this point everything is set up and we can finally approach the time loop.
for t in 0:Δt:T
for t in Δt:Δt:T
#First of all, we need to update the Dirichlet boundary condition values.
update!(ch, t)

Expand Down
26 changes: 26 additions & 0 deletions docs/src/manual/boundary_conditions.md
Original file line number Diff line number Diff line change
Expand Up @@ -260,3 +260,29 @@ pdbc = PeriodicDirichlet(
(x, t) -> ū + ∇ū ⋅ (x - x̄)
)
```

# Initial Conditions

When solving time-dependent problems, initial conditions, different from zero, may be required.
For finite element formulations of ODE-type,
i.e. ``\boldsymbol{x}'(t) = \boldsymbol{f}(\boldsymbol{x}(t),t)``,
where ``\boldsymbol{x}(t)`` are the degrees of freedom,
initial conditions can be specified by the [`apply_analytical!`](@ref) function.
For example, specify the initial pressure as a function of the y-coordinate
```julia
ρ = 1000; g=9.81 # density [kg/m³] and gravity [N/kg]
KnutAM marked this conversation as resolved.
Show resolved Hide resolved
grid = generate_grid(Quadrilateral, (10,10))
dh = DofHandler(grid); push!(dh, :u, 2); push!(dh, :p, 1); close!(dh)
x = zeros(ndofs(dh))
apply_analytical!(x, dh, :p, x->ρ*g*x[2])
```

See also [Time Dependent Problems](@ref) for one example.

*Note about solving DAE:*
A Differential Algebraic Equations (DAE) is an equation of the form
``\boldsymbol{r}(\boldsymbol{x}(t),\boldsymbol{x}'(t),t)=\boldsymbol{0}``,
which cannot be expressed as an ODE.
KnutAM marked this conversation as resolved.
Show resolved Hide resolved
In for such equations, it is usually necessary to specify initial conditions
for both ``\boldsymbol{x}(0)`` and ``\boldsymbol{x}'(0)``, and these must be consistent,
i.e. ``\boldsymbol{r}(\boldsymbol{x}(0),\boldsymbol{x}'(0),0)=\boldsymbol{0}``.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is only true for index 1 DAEs. For index>1 you get hidden constraints which must be fulfilled too. This makes the initialization so tricky.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps something like this then?

Suggested change
In for such equations, it is usually necessary to specify initial conditions
for both ``\boldsymbol{x}(0)`` and ``\boldsymbol{x}'(0)``, and these must be consistent,
i.e. ``\boldsymbol{r}(\boldsymbol{x}(0),\boldsymbol{x}'(0),0)=\boldsymbol{0}``.
For such equations, it is usually necessary to specify initial conditions
for both ``\boldsymbol{x}(0)`` and ``\boldsymbol{x}'(0)``.
These functions must be consistent, i.e. fulfilling both ``\boldsymbol{r}(\boldsymbol{x}(0),\boldsymbol{x}'(0),0)=\boldsymbol{0}`` and all additional constraints.

(I think I'll change from x to a for the unknowns later, just to avoid confusion with the coordinate)

6 changes: 6 additions & 0 deletions docs/src/reference/boundary_conditions.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,9 @@ get_rhs_data
apply_rhs!
Ferrite.RHSData
```

# Initial conditions

```@docs
apply_analytical!
```
2 changes: 2 additions & 0 deletions src/Dofs/MixedDofHandler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,9 @@ end

find_field(dh::MixedDofHandler, field_name::Symbol) = find_field(first(dh.fieldhandlers), field_name)
field_offset(dh::MixedDofHandler, field_name::Symbol) = field_offset(first(dh.fieldhandlers), field_name)
getfieldinterpolation(fh::FieldHandler, field_idx::Int) = fh.fields[field_idx].interpolation
getfieldinterpolation(dh::MixedDofHandler, field_idx::Int) = dh.fieldhandlers[1].fields[field_idx].interpolation
getfielddim(fh::FieldHandler, field_idx::Int) = fh.fields[field_idx].dim
getfielddim(dh::MixedDofHandler, field_idx::Int) = dh.fieldhandlers[1].fields[field_idx].dim

function reshape_to_nodes(dh::MixedDofHandler, u::Vector{T}, fieldname::Symbol) where T
Expand Down
1 change: 1 addition & 0 deletions src/Ferrite.jl
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ include("Dofs/MixedDofHandler.jl")
include("Dofs/ConstraintHandler.jl")

include("iterators.jl")
include("initial_conditions.jl")

# Assembly
include("assembler.jl")
Expand Down
1 change: 1 addition & 0 deletions src/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ export
FieldHandler,
Field,
reshape_to_nodes,
apply_analytical!,

# Constraints
ConstraintHandler,
Expand Down
Loading