Callbacks

TrixiParticles.DensityReinitializationCallbackType
DensityReinitializationCallback(; interval::Integer=0, dt=0.0)

Callback to reinitialize the density field when using ContinuityDensity [70].

Keywords

  • interval=0: Reinitialize the density every interval time steps.
  • dt: Reinitialize the density in regular intervals of dt in terms of integration time. This callback does not add extra time steps / tstops; instead, reinitialization is triggered at the first solver step after each dt interval has elapsed.
  • reinit_initial_solution: Reinitialize the initial solution (default=true)
source
TrixiParticles.InfoCallbackMethod
InfoCallback()

Create and return a callback that prints a human-readable summary of the simulation setup at the beginning of a simulation and then resets the timer. When the returned callback is executed directly, the current timer values are shown.

source
TrixiParticles.MechanicalWorkCalculatorCallbackType
MechanicalWorkCalculatorCallback(system::TotalLagrangianSPHSystem, semi; interval=1,
                                 eachparticle=(n_integrated_particles(system) + 1):nparticles(system),
                                 only_compute_force_on_fluid=false)

Callback that accumulates the work done by a set of particles in a TotalLagrangianSPHSystem by integrating the instantaneous power over time.

With the default arguments it tracks the work done by the clamped particles that follow a PrescribedMotion. By selecting a different particle set, it can also be used to measure the work done by the structure on the surrounding fluid.

  • Prescribed/clamped motion work (default) – monitor only the clamped particles by leaving eachparticle at its default range (n_integrated_particles(system) + 1):nparticles(system).
  • Fluid load measurement – set eachparticle=eachparticle(system) together with only_compute_force_on_fluid=true to accumulate the work that the entire structure exerts on the surrounding fluid (useful for drag or lift estimates).

Internally the callback integrates the instantaneous power, i.e. the dot product between the force exerted by the particle and its prescribed velocity, using an explicit Euler time integration scheme.

The accumulated value can be retrieved via calculated_mechanical_work.

Experimental implementation

This is an experimental feature and may change in future releases.

Arguments

Keywords

  • interval=1: Interval (in number of time steps) at which to compute the instantaneous power. It is recommended to keep this at 1 (every time step) or small (≤ 5) to limit time integration errors in the integral.
  • eachparticle=(n_integrated_particles(system) + 1):nparticles(system): Iterator selecting which particles contribute. The default includes all clamped particles in the system; pass eachparticle(system) to include every particle.
  • only_compute_force_on_fluid=false: When true, only interactions with fluid systems are accounted for. Combined with eachparticle=eachparticle(system), this accumulates the work that the entire structure exerts on the fluid, which is useful for drag or lift estimates.

Examples

semi = Semidiscretization(system)
ode = semidiscretize(semi, (0.0, 1.0))

# Note that `Semidiscretization` might create a deep copy of the system,
# which means we have to extract the new system from `semi`.
# When working with GPUs, `semidiscretize` also creates a deep copy of `semi` and another
# copy of the system, so the clean way to get the correct new system is this:
semi_new = ode.p.semi
system_new = semi_new.systems[1]

# Create a mechanical work calculator callback that is called every 2 time steps
mechanical_work_cb = MechanicalWorkCalculatorCallback(system_new, semi_new; interval=2)

# After the simulation, retrieve the accumulated mechanical work
mechanical_work = calculated_mechanical_work(mechanical_work_cb)
source
TrixiParticles.calculated_mechanical_workMethod
calculated_mechanical_work(cb::DiscreteCallback{<:Any, <:MechanicalWorkCalculatorCallback})

Get the accumulated mechanical work from a MechanicalWorkCalculatorCallback.

Arguments

Examples

# Create a mechanical work calculator callback
mechanical_work_cb = MechanicalWorkCalculatorCallback(system, semi)

# After the simulation, retrieve the accumulated mechanical work
mechanical_work = calculated_mechanical_work(mechanical_work_cb)
source
TrixiParticles.PostprocessCallbackType
PostprocessCallback(; interval::Integer=0, dt=0.0, exclude_boundary=true, filename="values",
                    output_directory="out", append_timestamp=false, write_csv=true,
                    write_json=true, write_file_interval=1, funcs...)

Create a callback to post-process simulation data at regular intervals. This callback allows for the execution of a user-defined function func at specified intervals during the simulation. The function is applied to the current state of the simulation, and its results can be saved or used for further analysis. The provided function cannot be anonymous as the function name will be used as part of the name of the value.

The callback can be triggered either by a fixed number of time steps (interval) or by a fixed interval of simulation time (dt).

Keywords

  • funcs...: Functions to be executed at specified intervals during the simulation. Each function must have the arguments (system, data, t), which will be called for every system, where data is a named tuple with fields depending on the system type, and t is the current simulation time. Check the available data for each system with available_data(system). See Custom Quantities for a list of pre-defined custom quantities that can be used here. Note: When using GPU backends, all data is automatically transferred to the CPU before being passed to the custom quantity functions. This ensures compatibility but may introduce overhead for frequent callbacks on large simulations.
  • interval=0: Specifies the number of time steps between each invocation of the callback. If set to 0, the callback will not be triggered based on time steps. Either interval or dt must be set to something larger than 0.
  • dt=0.0: Specifies the simulation time interval between each invocation of the callback. If set to 0.0, the callback will not be triggered based on simulation time. Either interval or dt must be set to something larger than 0.
  • exclude_boundary=true: If set to true, boundary particles will be excluded from the post-processing.
  • filename="values": The filename of the postprocessing files to be saved.
  • output_directory="out": The path where the results of the post-processing will be saved.
  • write_csv=true: If set to true, write a csv file.
  • write_json=true: If set to true, write a json file.
  • append_timestep=false: If set to true, the current timestamp will be added to the filename.
  • write_file_interval=1: Files will be written after every write_file_interval number of postprocessing execution steps. A value of 0 indicates that files are only written at the end of the simulation, eliminating I/O overhead.

Examples

# Create a callback that is triggered every 100 time steps
postprocess_callback = PostprocessCallback(interval=100, example_quantity=kinetic_energy)

# Create a callback that is triggered every 0.1 simulation time units
postprocess_callback = PostprocessCallback(dt=0.1, example_quantity=kinetic_energy)
source
TrixiParticles.SolutionSavingCallbackType
SolutionSavingCallback(; interval::Integer=0, dt=0.0, save_times=Float64[],
                       save_initial_solution=true, save_final_solution=true,
                       output_directory="out", append_timestamp=false, prefix="",
                       verbose=false, overwrite=false, max_coordinates=2^15,
                       custom_quantities...)

Callback to save the current numerical solution in VTK format. Use at most one of interval, dt, and save_times: pass interval to save every interval accepted time steps, dt to save in intervals of dt in terms of integration time by adding additional tstops (note that this may change the solution), or save_times to save at specific times. The initial and final solution can be added independently with save_initial_solution and save_final_solution.

Additional user-defined quantities can be saved by passing keyword arguments. A custom quantity can be an array or a function. Functions are called as (system, dv_ode, du_ode, v_ode, u_ode, semi, t) when that method exists, otherwise as (system, data, t). In the latter case, data is a named tuple with fields depending on the system type. To ignore a custom quantity for a specific system, return nothing.

Keywords

  • interval=0: Save the solution every interval accepted time steps. A value of 0 disables step-interval saves, so only the initial and final solution are saved based on save_initial_solution and save_final_solution, unless save_times or dt are used.
  • dt: Save the solution in regular intervals of dt in terms of integration time by adding additional tstops (note that this may change the solution).
  • save_times=Float64[]: Specific times at which to save a solution. These times are mutually exclusive with interval and dt.
  • save_initial_solution=true: Save the initial solution. Setting this to false does not suppress an initial time explicitly listed in save_times.
  • save_final_solution=true: Save the final solution. Setting this to false does not suppress a final time explicitly listed in save_times.
  • overwrite=false: If true, previously written VTK files are overwritten instead of creating a new file set at each save interval. In this case, filenames receive the postfix _current. This option is useful for memory efficiency in large simulations where only the final results matter. It provides a rolling checkpoint at each save interval. If false (default), files are not overwritten and an iteration postfix is appended for each interval.
  • output_directory="out": Directory to save the VTK files.
  • append_timestamp=false: Append current timestamp to the output directory.
  • prefix="": Prefix added to the filename.
  • verbose=false: Print to standard IO when a file is written.
  • max_coordinates=2^15: The coordinates of particles will be clipped if their absolute values exceed this threshold.
  • custom_quantities...: Additional custom quantities to include in the VTK output. Check the available data for each system with available_data(system). See Custom Quantities for a list of pre-defined custom quantities that can be used here.

Examples

# Save every 100 time steps
saving_callback = SolutionSavingCallback(interval=100)

# Save in intervals of 0.1 in terms of simulation time
saving_callback = SolutionSavingCallback(dt=0.1)

# Additionally store the kinetic energy of each system as "my_custom_quantity"
saving_callback = SolutionSavingCallback(dt=0.1, my_custom_quantity=kinetic_energy)
source
TrixiParticles.SortingCallbackMethod
SortingCallback(; interval=-1, dt=0.0, initial_sort=true)

Reorders particles according to neighborhood-search cells for performance optimization.

When particles become very unordered throughout a long-running simulation, performance degrades due to increased cache-misses (on CPUs) and lack of block structure (on GPUs). On GPUs, a fully shuffled particle ordering causes a 3-4x slowdown compared to a sorted configuration. On CPUs the performance penalty grows linearly with the problem size and can reach up to a 10x slowdown for very large problems (65M particles). See #1044 for more details.

Keywords

  • interval: Sort particles at the end of every interval time steps.
  • dt: Sort particles in regular intervals of dt in terms of integration time. This callback does not add extra time steps / tstops; instead, sorting is triggered at the first solver step after each dt interval has elapsed.
  • initial_sort=true: When enabled, particles are sorted at the beginning of the simulation. When the initial configuration is a perfect grid of particles, sorting at the beginning is not necessary and might even slightly slow down the first time steps, since a perfect grid is even better than sorting by NHS cell index.
source
TrixiParticles.SplitIntegrationCallbackMethod
SplitIntegrationCallback(alg; stage_coupling=false, predict_positions=true, kwargs...)

Callback to integrate the TotalLagrangianSPHSystems in a Semidiscretization separately from the other systems. For each time step of the main integrator (in which TLSPH systems are ignored), the TLSPH systems are integrated for multiple smaller time steps with their own integrator.

This is useful if the TLSPH systems require much smaller time steps than the fluid systems, which is usually the case when stiff materials are simulated. It is especially useful if additionally the number of TLSPH particles is much smaller than the number of fluid particles, so that a fluid time step is much more expensive than a TLSPH substep.

For fluid-structure interactions with stiff materials like metal or carbon fiber composites, this can lead to significant speedups of several hundred times if the ratio of fluid to solid particles is large enough (e.g. 100:1 or more).

Arguments

  • alg: The time integration algorithm to use for the TLSPH systems.

Keywords

  • stage_coupling=false: If false, the TLSPH systems are only updated between full time steps of the main integrator. If true, the TLSPH systems are integrated to the intermediate stage times of the main integrator. The sub-integrator integrates from the previous fluid stage time to the next stage time, using the intermediate stage predictions for the fluid state. This strategy is highly efficient (no sub-steps have to be repeated) but less accurate than repeating the sub-integration with the final (as opposed to predicted) fluid state. Note that this type of stage-level coupling is still more accurate than step-level coupling (stage_coupling=false). For large time step size ratios, stage_coupling=false might require a significantly (often 2x) smaller fluid time step size for stability at the FSI interface. For small time step size ratios, stage_coupling=false might be sufficiently stable and more efficient than stage_coupling=true. Note that stage_coupling=true is only compatible with fluid time integration schemes that have monotonically increasing stage times and no stage time smaller than the time of the previous full step.
  • predict_positions=true: If false, use the old structure state together with the new fluid state. If true, predict the structure positions for the fluid force calculation. The force on the structure due to the fluid is kept constant during one sub-integration call. When computing this force, the new fluid state and the old structure state are available. To avoid inconsistencies and improve accuracy (not stability), we can predict the structure positions at the new time with a simple Euler step, $u \leftarrow u + v\,(t_{\mathrm{new}} - t_{\mathrm{previous}})$, which is only used for the fluid force calculation.
  • kwargs...: Additional keyword arguments passed to the integrator of the TLSPH systems. Use this for callbacks like the StepsizeCallback for choosing the sub-integration time step.

Examples

using OrdinaryDiffEqLowStorageRK

# Low-storage RK method with CFL condition for time step size
callback = SplitIntegrationCallback(CarpenterKennedy2N54(williamson_condition=false),
                                    dt=1.0, # This is overwritten by the stepsize callback
                                    callback=StepsizeCallback(cfl=1.6),
                                    stage_coupling=true)
source
TrixiParticles.SteadyStateReachedCallbackType
SteadyStateReachedCallback(; interval::Integer=0, dt=0.0,
                           interval_size::Integer=10, abstol=1.0e-8, reltol=1.0e-6)

Terminates the integration when the change of kinetic energy between time steps falls below the threshold specified by abstol + reltol * ekin, where ekin is the total kinetic energy of the simulation.

Keywords

  • interval=0: Check steady state condition every interval time steps.
  • dt=0.0: Check steady state condition in regular intervals of dt in terms of integration time by adding additional tstops (note that this may change the solution).
  • interval_size: The interval in which the change of the kinetic energy is considered. interval_size is a (integer) multiple of interval or dt.
  • abstol: Absolute tolerance.
  • reltol: Relative tolerance.
source
TrixiParticles.StepsizeCallbackMethod
StepsizeCallback(; cfl::Real)

Set the time step size according to a CFL condition if the time integration method isn't adaptive itself.

The current implementation is using the simplest form of CFL condition, which chooses a time step size that is constant during the simulation. The step size is therefore only applied once at the beginning of the simulation.

The step size $\Delta t$ is chosen as the minimum

\[ \Delta t = \min(\Delta t_\eta, \Delta t_a, \Delta t_c),\]

where

\[ \Delta t_\eta = 0.125 \, h^2 / \eta, \quad \Delta t_a = 0.25 \sqrt{h / \lVert g \rVert}, \quad \Delta t_c = \text{CFL} \, h / c,\]

with $\nu = \alpha h c / (2n + 4)$, where $\alpha$ is the parameter of the viscosity and $n$ is the number of dimensions.

Experimental implementation

This is an experimental feature and may change in future releases.

References

[35], [1], [42], [71]

source
TrixiParticles.UpdateCallbackMethod
UpdateCallback(; interval::Integer, dt=0.0)

Callback to update quantities either at the end of every interval time steps or in intervals of dt in terms of integration time by adding additional tstops (note that this may change the solution).

Keywords

  • interval=1: Update quantities at the end of every interval time steps.
  • dt: Update quantities in regular intervals of dt in terms of integration time by adding additional tstops (note that this may change the solution).
source

Custom Quantities

The following pre-defined custom quantities can be used with the SolutionSavingCallback and PostprocessCallback.