Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
trixi-framework
GitHub Repository: trixi-framework/Trixi.jl
Path: blob/main/src/callbacks_step/visualization.jl
5586 views
1
# By default, Julia/LLVM does not use fused multiply-add operations (FMAs).
2
# Since these FMAs can increase the performance of many numerical algorithms,
3
# we need to opt-in explicitly.
4
# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details.
5
@muladd begin
6
#! format: noindent
7
8
struct VisualizationCallback{PlotDataCreator, SolutionVariables, VariableNames,
9
PlotCreator}
10
plot_data_creator::PlotDataCreator
11
interval::Int
12
solution_variables::SolutionVariables
13
variable_names::VariableNames
14
show_mesh::Bool
15
plot_creator::PlotCreator
16
plot_arguments::Dict{Symbol, Any}
17
end
18
19
function Base.show(io::IO,
20
cb::DiscreteCallback{Condition, Affect!}) where {Condition,
21
Affect! <:
22
VisualizationCallback
23
}
24
visualization_callback = cb.affect!
25
@unpack plot_data_creator, interval, plot_arguments, solution_variables, variable_names, show_mesh, plot_creator = visualization_callback
26
print(io, "VisualizationCallback(",
27
"plot_data_creator=", plot_data_creator, ", ",
28
"interval=", interval, ", ",
29
"solution_variables=", solution_variables, ", ",
30
"variable_names=", variable_names, ", ",
31
"show_mesh=", show_mesh, ", ",
32
"plot_creator=", plot_creator, ", ",
33
"plot_arguments=", plot_arguments, ")")
34
return nothing
35
end
36
37
function Base.show(io::IO, ::MIME"text/plain",
38
cb::DiscreteCallback{Condition, Affect!}) where {Condition,
39
Affect! <:
40
VisualizationCallback
41
}
42
if get(io, :compact, false)
43
show(io, cb)
44
else
45
visualization_callback = cb.affect!
46
47
setup = [
48
"plot data creator" => visualization_callback.plot_data_creator,
49
"interval" => visualization_callback.interval,
50
"plot arguments" => visualization_callback.plot_arguments,
51
"solution variables" => visualization_callback.solution_variables,
52
"variable names" => visualization_callback.variable_names,
53
"show mesh" => visualization_callback.show_mesh,
54
"plot creator" => visualization_callback.plot_creator
55
]
56
summary_box(io, "VisualizationCallback", setup)
57
end
58
end
59
60
"""
61
VisualizationCallback(semi, plot_data_creator = nothing;
62
interval=0,
63
solution_variables=cons2prim,
64
variable_names=[],
65
show_mesh=false,
66
plot_creator=show_plot,
67
plot_arguments...)
68
69
Create a callback that visualizes results during a simulation, also known as *in-situ
70
visualization*.
71
72
To customize the generated figure, `plot_data_creator` allows to use different plot data types.
73
Currently provided are [`PlotData1D`](@ref) and [`PlotData2D`](@ref), while the latter is used for both 2D and 3D.
74
75
The `interval` specifies the number of time step iterations after which a new plot is generated. The
76
available variables to plot are configured with the `solution_variables` parameter, which acts the
77
same way as for the [`SaveSolutionCallback`](@ref). The variables to be actually plotted can be
78
selected by providing a single string or a list of strings to `variable_names`, and if `show_mesh`
79
is `true`, an additional plot with the mesh will be generated.
80
81
With `plot_creator` you can further specify an own function to visualize results, which must support the
82
same interface as the default implementation [`show_plot`](@ref). All remaining
83
keyword arguments are collected and passed as additional arguments to the plotting command.
84
"""
85
function VisualizationCallback(semi, plot_data_creator = nothing;
86
interval = 0,
87
solution_variables = cons2prim,
88
variable_names = [],
89
show_mesh = false,
90
plot_creator = show_plot,
91
plot_arguments...)
92
mpi_isparallel() && error("this callback does not work in parallel yet")
93
94
if variable_names isa String
95
variable_names = String[variable_names]
96
end
97
98
if plot_data_creator === nothing # No custom plot data type provided
99
if ndims(semi) == 1
100
plot_data_creator = PlotData1D
101
else # 2D or 3D
102
plot_data_creator = PlotData2D
103
end
104
end
105
106
visualization_callback = VisualizationCallback(plot_data_creator,
107
interval,
108
solution_variables, variable_names,
109
show_mesh,
110
plot_creator,
111
Dict{Symbol, Any}(plot_arguments))
112
113
return DiscreteCallback(visualization_callback, visualization_callback, # the first one is the condition, the second the affect!
114
save_positions = (false, false),
115
initialize = initialize!)
116
end
117
118
function initialize!(cb::DiscreteCallback{Condition, Affect!}, u, t,
119
integrator) where {Condition, Affect! <: VisualizationCallback}
120
visualization_callback = cb.affect!
121
122
visualization_callback(integrator)
123
124
return nothing
125
end
126
127
# this method is called to determine whether the callback should be activated
128
function (visualization_callback::VisualizationCallback)(u, t, integrator)
129
@unpack interval = visualization_callback
130
131
# With error-based step size control, some steps can be rejected. Thus,
132
# `integrator.iter >= integrator.stats.naccept`
133
# (total #steps) (#accepted steps)
134
# We need to check the number of accepted steps since callbacks are not
135
# activated after a rejected step.
136
return interval > 0 && (integrator.stats.naccept % interval == 0 ||
137
isfinished(integrator))
138
end
139
140
# this method is called when the callback is activated
141
function (visualization_callback::VisualizationCallback)(integrator)
142
u_ode = integrator.u
143
semi = integrator.p
144
@unpack plot_data_creator, plot_arguments, solution_variables, variable_names, show_mesh, plot_creator = visualization_callback
145
146
# Extract plot data
147
plot_data = plot_data_creator(u_ode, semi, solution_variables = solution_variables)
148
149
# If variable names were not specified, plot everything
150
if isempty(variable_names)
151
variable_names = String[keys(plot_data)...]
152
end
153
154
# Create plot
155
plot_creator(plot_data, variable_names;
156
show_mesh = show_mesh, plot_arguments = plot_arguments,
157
time = integrator.t, timestep = integrator.stats.naccept)
158
159
# avoid re-evaluating possible FSAL stages
160
u_modified!(integrator, false)
161
return nothing
162
end
163
164
"""
165
show_plot(plot_data, variable_names;
166
show_mesh=true, plot_arguments=Dict{Symbol,Any}(),
167
time=nothing, timestep=nothing)
168
169
Visualize the plot data object provided in `plot_data` and display result, plotting only the
170
variables in `variable_names` and, optionally, the mesh (if `show_mesh` is `true`). Additionally,
171
`plot_arguments` will be unpacked and passed as keyword arguments to the `Plots.plot` command.
172
173
This function is the default `plot_creator` argument for the [`VisualizationCallback`](@ref).
174
`time` and `timestep` are currently unused by this function.
175
176
!!! note
177
This requires loading [Plots.jl](https://github.com/JuliaPlots/Plots.jl), e.g., via `using Plots`.
178
179
See also: [`VisualizationCallback`](@ref), [`save_plot`](@ref)
180
"""
181
function show_plot end
182
183
"""
184
save_plot(plot_data, variable_names;
185
show_mesh=true, plot_arguments=Dict{Symbol,Any}(),
186
time=nothing, timestep=nothing)
187
188
Visualize the plot data object provided in `plot_data` and save result as a PNG file in the `out`
189
directory, plotting only the variables in `variable_names` and, optionally, the mesh (if `show_mesh`
190
is `true`). Additionally, `plot_arguments` will be unpacked and passed as keyword arguments to the
191
`Plots.plot` command.
192
193
The `timestep` is used in the filename. `time` is currently unused by this function.
194
195
!!! note
196
This requires loading [Plots.jl](https://github.com/JuliaPlots/Plots.jl), e.g., via `using Plots`.
197
198
See also: [`VisualizationCallback`](@ref), [`show_plot`](@ref)
199
"""
200
function save_plot end
201
end # @muladd
202
203