Skip to content

Commit

Permalink
Added load_timestep function. (#1528)
Browse files Browse the repository at this point in the history
* Added load_timestep function.
Corrected time index in restart simulations.

* Changed doc string for load_timestep to clarify that we read the iteration number.

* Added reading function for dt.
Changed restart example elixir such that they use dt from previous simulation.

* Get attribute 'current_filename' when loading an existing mesh.
This fixes issues with converting from hdf5 into vtk
when rerunning a simulation.

* format

* Update make.jl to include restart simulation documentation.

* Create restart.md.

* Added unformatted docs on how to restart a simulation from an old snapshot.

* Completed restart tutorial.

* Fixed a few typos in the docs for restarting a simulation.

* Minor typo.

* Added myself to the contributor list.

* Update docs/src/restart.md

Co-authored-by: Hendrik Ranocha <[email protected]>

* Update docs/src/restart.md

Co-authored-by: Hendrik Ranocha <[email protected]>

* Update docs/src/restart.md

Co-authored-by: Hendrik Ranocha <[email protected]>

* Update docs/src/restart.md

Co-authored-by: Hendrik Ranocha <[email protected]>

* Update docs/src/restart.md

Co-authored-by: Michael Schlottke-Lakemper <[email protected]>

* Update docs/src/restart.md

Co-authored-by: Michael Schlottke-Lakemper <[email protected]>

* Update restart.md

Added a few links to the restart documentation.

* Update docs/src/restart.md

Co-authored-by: Hendrik Ranocha <[email protected]>

* Corrected reference file name.

* Added reference to save solution callback.

---------

Co-authored-by: Hendrik Ranocha <[email protected]>
Co-authored-by: Michael Schlottke-Lakemper <[email protected]>
Co-authored-by: Hendrik Ranocha <[email protected]>
  • Loading branch information
4 people authored Jul 11, 2023
1 parent 5ff677c commit 42732db
Show file tree
Hide file tree
Showing 13 changed files with 205 additions and 22 deletions.
1 change: 1 addition & 0 deletions AUTHORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ are listed in alphabetical order:

* Maximilian D. Bertrand
* Benjamin Bolm
* Simon Candelaresi
* Jesse Chan
* Lars Christmann
* Christof Czernik
Expand Down
1 change: 1 addition & 0 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ makedocs(
"Getting started" => [
"Overview" => "overview.md",
"Visualization" => "visualization.md",
"Restart simulation" => "restart.md",
],
"Tutorials" => tutorials,
"Basic building blocks" => [
Expand Down
89 changes: 89 additions & 0 deletions docs/src/restart.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# [Restart simulation](@id restart)

You can continue running an already finished simulation by first
preparing the simulation for the restart and then performing the restart.
Here we suppose that in the first run your simulation stops at time 1.0
and then you want it to run further to time 2.0.

## [Prepare the simulation for a restart](@id restart_preparation)
In you original elixir you need to specify to write out restart files.
Those will later be read for the restart of your simulation.
This is done almost the same way as writing the snapshots using the
[`SaveSolutionCallback`](@ref) callback.
For the restart files it is called [`SaveRestartCallback`](@ref):
```julia
save_restart = SaveRestartCallback(interval=100,
save_final_restart=true)
```
Make this part of your `CallbackSet`.

An example is
[```examples/examples/structured_2d_dgsem/elixir_advection_extended.jl```](https://github.com/trixi-framework/Trixi.jl/blob/main/examples/structured_2d_dgsem/elixir_advection_extended.jl).


## [Perform the simulation restart](@id restart_perform)
Since all of the information about the simulation can be obtained from the
last snapshot, the restart can be done with relatively few lines
in an extra elixir file.
However, some might prefer to keep everything in one elixir and
conditionals like ```if restart``` with a boolean variable ```restart``` that is user defined.

First we need to define from which file we want to restart, e.g.
```julia
restart_file = "restart_000021.h5"
restart_filename = joinpath("out", restart_file)
```

Then we load the mesh file:
```julia
mesh = load_mesh(restart_filename)
```

This is then needed for the semidiscretization:
```julia
semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver)
```

We then define a new time span for the simulation that takes as starting
time the one form the snapshot:
```julia
tspan = (load_time(restart_filename), 2.0)
```

We now also take the last ```dt```, so that our solver does not need to first find
one to fulfill the CFL condition:
```julia
dt = load_dt(restart_filename)
```

The ODE that we will pass to the solver is now:
```julia
ode = semidiscretize(semi, tspan, restart_filename)
```

You should now define a [`SaveSolutionCallback`](@ref) similar to the
[original simulation](https://github.com/trixi-framework/Trixi.jl/blob/main/examples/structured_2d_dgsem/elixir_advection_extended.jl),
but with ```save_initial_solution=false```, otherwise our initial snapshot will be overwritten.
If you are using one file for the original simulation and the restart
you can reuse your [`SaveSolutionCallback`](@ref), but need to set
```julia
save_solution.condition.save_initial_solution = false
```

Before we compute the solution using
[OrdinaryDiffEq.jl](https://github.com/SciML/OrdinaryDiffEq.jl)
we need to set the integrator
and its time step number, e.g.:
```julia
integrator = init(ode, CarpenterKennedy2N54(williamson_condition=false),
dt=dt, save_everystep=false, callback=callbacks);
integrator.iter = load_timestep(restart_filename)
integrator.stats.naccept = integrator.iter
```

Now we can compute the solution:
```julia
sol = solve!(integrator)
```

An example is in `[``examples/structured_2d_dgsem/elixir_advection_restart.jl```](https://github.com/trixi-framework/Trixi.jl/blob/main/examples/structured_2d_dgsem/elixir_advection_restart.jl).
16 changes: 13 additions & 3 deletions examples/p4est_2d_dgsem/elixir_advection_restart.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,23 @@ semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver,
boundary_conditions=boundary_conditions)

tspan = (load_time(restart_filename), 2.0)
dt = load_dt(restart_filename)
ode = semidiscretize(semi, tspan, restart_filename);

# Do not overwrite the initial snapshot written by elixir_advection_extended.jl.
save_solution.condition.save_initial_solution = false

integrator = init(ode, CarpenterKennedy2N54(williamson_condition=false),
dt=dt, # solve needs some value here but it will be overwritten by the stepsize_callback
save_everystep=false, callback=callbacks);

# Get the last time index and work with that.
integrator.iter = load_timestep(restart_filename)
integrator.stats.naccept = integrator.iter


###############################################################################
# run the simulation

sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false),
dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback
save_everystep=false, callback=callbacks);
sol = solve!(integrator)
summary_callback() # print the timer summary
16 changes: 13 additions & 3 deletions examples/p4est_3d_dgsem/elixir_advection_restart.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,23 @@ mesh = load_mesh(restart_filename)
semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, solver)

tspan = (load_time(restart_filename), 2.0)
dt = load_dt(restart_filename)
ode = semidiscretize(semi, tspan, restart_filename);

# Do not overwrite the initial snapshot written by elixir_advection_extended.jl.
save_solution.condition.save_initial_solution = false

integrator = init(ode, CarpenterKennedy2N54(williamson_condition=false),
dt=dt, # solve needs some value here but it will be overwritten by the stepsize_callback
save_everystep=false, callback=callbacks);

# Get the last time index and work with that.
integrator.iter = load_timestep(restart_filename)
integrator.stats.naccept = integrator.iter


###############################################################################
# run the simulation

sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false),
dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback
save_everystep=false, callback=callbacks);
sol = solve!(integrator)
summary_callback() # print the timer summary
15 changes: 12 additions & 3 deletions examples/structured_2d_dgsem/elixir_advection_restart.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,22 @@ mesh = load_mesh(restart_filename)
semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver)

tspan = (load_time(restart_filename), 2.0)
dt = load_dt(restart_filename)
ode = semidiscretize(semi, tspan, restart_filename);

# Do not overwrite the initial snapshot written by elixir_advection_extended.jl.
save_solution.condition.save_initial_solution = false

integrator = init(ode, CarpenterKennedy2N54(williamson_condition=false),
dt=dt, # solve needs some value here but it will be overwritten by the stepsize_callback
save_everystep=false, callback=callbacks);

# Get the last time index and work with that.
integrator.iter = load_timestep(restart_filename)
integrator.stats.naccept = integrator.iter

###############################################################################
# run the simulation

sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false),
dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback
save_everystep=false, callback=callbacks);
sol = solve!(integrator)
summary_callback() # print the timer summary
16 changes: 13 additions & 3 deletions examples/structured_3d_dgsem/elixir_advection_restart.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,23 @@ mesh = load_mesh(restart_filename)
semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, solver)

tspan = (load_time(restart_filename), 2.0)
dt = load_dt(restart_filename)
ode = semidiscretize(semi, tspan, restart_filename);

# Do not overwrite the initial snapshot written by elixir_advection_extended.jl.
save_solution.condition.save_initial_solution = false

integrator = init(ode, CarpenterKennedy2N54(williamson_condition=false),
dt=dt, # solve needs some value here but it will be overwritten by the stepsize_callback
save_everystep=false, callback=callbacks);

# Get the last time index and work with that.
integrator.iter = load_timestep(restart_filename)
integrator.stats.naccept = integrator.iter


###############################################################################
# run the simulation

sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false),
dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback
save_everystep=false, callback=callbacks);
sol = solve!(integrator)
summary_callback() # print the timer summary
16 changes: 13 additions & 3 deletions examples/tree_2d_dgsem/elixir_advection_restart.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,23 @@ mesh = load_mesh(restart_filename)
semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver)

tspan = (load_time(restart_filename), 2.0)
dt = load_dt(restart_filename)
ode = semidiscretize(semi, tspan, restart_filename);

# Do not overwrite the initial snapshot written by elixir_advection_extended.jl.
save_solution.condition.save_initial_solution = false

integrator = init(ode, CarpenterKennedy2N54(williamson_condition=false),
dt=dt, # solve needs some value here but it will be overwritten by the stepsize_callback
save_everystep=false, callback=callbacks)

# Get the last time index and work with that.
integrator.iter = load_timestep(restart_filename)
integrator.stats.naccept = integrator.iter

###############################################################################
# run the simulation

sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false),
dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback
save_everystep=false, callback=callbacks);
sol = solve!(integrator)

summary_callback() # print the timer summary
16 changes: 13 additions & 3 deletions examples/tree_3d_dgsem/elixir_advection_restart.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,23 @@ mesh = load_mesh(restart_filename)
semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver)

tspan = (load_time(restart_filename), 2.0)
dt = load_dt(restart_filename)
ode = semidiscretize(semi, tspan, restart_filename);

# Do not overwrite the initial snapshot written by elixir_advection_extended.jl.
save_solution.condition.save_initial_solution = false

integrator = init(ode, CarpenterKennedy2N54(williamson_condition=false),
dt=dt, # solve needs some value here but it will be overwritten by the stepsize_callback
save_everystep=false, callback=callbacks);

# Get the last time index and work with that.
integrator.iter = load_timestep(restart_filename)
integrator.stats.naccept = integrator.iter


###############################################################################
# run the simulation

sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false),
dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback
save_everystep=false, callback=callbacks);
sol = solve!(integrator)
summary_callback() # print the timer summary
16 changes: 13 additions & 3 deletions examples/unstructured_2d_dgsem/elixir_euler_restart.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,24 @@ semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver,
boundary_conditions=boundary_conditions)

tspan = (load_time(restart_filename), 1.0)
dt = load_dt(restart_filename)
ode = semidiscretize(semi, tspan, restart_filename);

# Do not overwrite the initial snapshot written by elixir_advection_extended.jl.
save_solution.condition.save_initial_solution = false

integrator = init(ode, CarpenterKennedy2N54(williamson_condition=false),
dt=dt, # solve needs some value here but it will be overwritten by the stepsize_callback
save_everystep=false, callback=callbacks);

# Get the last time index and work with that.
integrator.iter = load_timestep(restart_filename)
integrator.stats.naccept = integrator.iter


###############################################################################
# run the simulation

sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false),
dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback
save_everystep=false, callback=callbacks);
sol = solve!(integrator)
summary_callback() # print the timer summary

2 changes: 1 addition & 1 deletion src/Trixi.jl
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ export SummaryCallback, SteadyStateCallback, AnalysisCallback, AliveCallback,
GlmSpeedCallback, LBMCollisionCallback, EulerAcousticsCouplingCallback,
TrivialCallback, AnalysisCallbackCoupled

export load_mesh, load_time
export load_mesh, load_time, load_timestep, load_dt

export ControllerThreeLevel, ControllerThreeLevelCombined,
IndicatorLöhner, IndicatorLoehner, IndicatorMax,
Expand Down
22 changes: 22 additions & 0 deletions src/callbacks_step/save_restart.jl
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,28 @@ function load_time(restart_file::AbstractString)
end
end

"""
load_timestep(restart_file::AbstractString)
Load the time step number (`iter` in OrdinaryDiffEq.jl) saved in a `restart_file`.
"""
function load_timestep(restart_file::AbstractString)
h5open(restart_file, "r") do file
read(attributes(file)["timestep"])
end
end

"""
load_dt(restart_file::AbstractString)
Load the time step size (`dt` in OrdinaryDiffEq.jl) saved in a `restart_file`.
"""
function load_dt(restart_file::AbstractString)
h5open(restart_file, "r") do file
read(attributes(file)["dt"])
end
end

function load_restart_file(semi::AbstractSemidiscretization, restart_file)
load_restart_file(mesh_equations_solver_cache(semi)..., restart_file)
end
Expand Down
1 change: 1 addition & 0 deletions src/meshes/mesh_io.jl
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ function load_mesh_serial(mesh_file::AbstractString; n_cells_max, RealT)

mesh = StructuredMesh(size, mapping; RealT = RealT, unsaved_changes = false,
mapping_as_string = mapping_as_string)
mesh.current_filename = mesh_file
elseif mesh_type == "UnstructuredMesh2D"
mesh_filename, periodicity_ = h5open(mesh_file, "r") do file
return read(attributes(file)["mesh_filename"]),
Expand Down

0 comments on commit 42732db

Please sign in to comment.