# Animations With Paraview

In many of the previous episodes we produced animations of steady state Elmer FEM solutions. For simplicity we did not discuss the details of how to prepare them. The process is actually very simple, but there are few tips and tricks to keep in mind. This episode aims to provide a concise introduction to animations with ParaView.

# Animations at a Glance

Animations are natural to show the evolution of time dependent fields. When the solver outputs a time dependent field the process is straightforward. In this case Elmer will output a series of `vtu`

files, each for a particular timestamp in the simulation. One can import these files in bulk and process them as usual. We covered basic postprocessing in many of the previous episodes. Video exportation is also mentioned in the Intro to ParaView episode.

Sometimes the solver doesn’t output a time dependent field. Time dependent fields are typical of transient simulations. So far, the focus of this series has been harmonic steady state and eigenvalues problems. These kind of problems do not produce time dependent fields. We did still handle timestamped `vtu`

files, but as a convenience trick. For example, in the Rigid Walled Room - Part 3 episode, we “packed” eigenfunctions in timestamped `vtu`

files. This allowed us to carry postprocessing easier. In these cases the `vtu`

files series contains unrelated time independent fields. In other words, the timestamped `vtu`

files do not contain “snapshots” of a time varying field. Instead, the various `vtu`

files contain some fields of interest, all output by the same solver.

The solution of steady state and eigenvalue problems is not time dependent. Still, we can use it as an ingredient for the time dependent solution. Hence, we are in the conditions to build a series of timestamped `vtu`

files. Then, we can import these files into ParaView, and proceed as usual. In this episode we will cover the construction of these time series, which is the hardest bit. We will also mention few ParaView tricks which are useful to handle animations. From there, you can refer to the Intro to ParaView episode.

# Crafting a Time Series

Our goal is to construct a field $F \left( \mathbf{u}, t \right)$. $\mathbf{u}$ is the generic point of our domain $\mathcal{D} \in \mathbb{R}^{3}$ (or $\mathbb{R}^{2}$ or $\mathbb{R}$ depending on dimensionality). $t$ is a variable parameterising time, belonging to $\mathbb{R}$ or any meaningful subset of it. $F$ can either be a scalar field or a vector field depending on the problem. In the following we will describe the construction of $F$ from the type of fields we worked with before. We will sharpen $F$ definition in each case.

## Step 1: Building $F$

### Helmholtz Solutions

We covered the physical interpretation of Helmholtz solutions in the Interpreting Helmholtz Solver Solutions episode. Within that episode we define the physical time dependent field $p \left( \mathbf{u}, t \right)$. We can identify $F$ as the scalar field $p$. It is particularly useful to express $F$ in terms of magnitude $M$ and phase $\Phi$ fields. Hence:

$$ F:\mathcal{D} \times \mathbb{R} \rightarrow \mathbb{R} $$

$$ F\left(\mathbf{u}, t \right) \doteq A M\left(\mathbf{u} \right) \cos \left( \Phi\left(\mathbf{u} \right) + \omega t + \phi \right) $$

Where we defined $M$ and $\Phi$ as in the Interpreting Helmholtz Solver Solutions episode. $\omega \in \mathbb{R}^{+}$ is the angular frequency of the simulation. $A \in \mathbb{R}$ and $\phi \in \left[-\pi, \space \pi \right]$ are arbitrary scale and phase factor respectively. Since phase is normally not important we set $\phi$ to $0$. $A$ is set to a number different from $1$ only when there is a compelling reason for it. For example, when the simulation is set in such a way a final scaling factor is needed. We did not encounter such cases so far. The final form of the field $F$ for the most common $A$ and $\phi$ selections is then the following:

$$ F\left(\mathbf{u}, t \right) \doteq M\left(\mathbf{u} \right) \cos \left( \Phi\left(\mathbf{u} \right) + \omega t \right) $$

### Elastic Time Harmonic Solutions

The Linear Elasticity solver can perform harmonic steady state analysis. In that case it will provide a displacement vector field $d$:

$$ d : \mathcal{D} \rightarrow \mathbb{R}^3 $$

We used $\mathbb{R}^3$ as we assumed a three-dimensional problem. For any other dimensionality replace the exponent. As the name says, the solution is harmonic. So all we need to get a time dependent field is to multiply the field $d$ with an harmonic function:

$$ F:\mathcal{D} \times \mathbb{R} \rightarrow \mathbb{R}^3 $$

$$ F\left(\mathbf{u}, t \right) \doteq A d \left(\mathbf{u}\right) \cos\left(\omega t + \phi \right)$$

Again, $\omega$ is the angular frequency of the simulation. $A$ and $\phi$ are arbitrary amplitude and phase factors respectively. For the same reasons as those listed in the previous sections, they are most often set to $1$ and $0$, leading to:

$$ F\left(\mathbf{u}, t \right) \doteq d \left(\mathbf{u}\right) \cos\left(\omega t \right)$$

### Acoustic Eigenfunctions

We have this kind of solution when we use the Wave Equation solver to solve an eigenproblem. We did so in the Rigid Walled Room series (*Revisited* episodes). This solver provides us with a number $N_{E} \in \mathbb{N}$ of eigenvalues and eigenfunctions:

$$ n = 1 \space, 2 \space, \dots, \space N_{E} $$

$$ \lambda_{n} = \omega_{n}^2 = \left( 2 \pi f_{n} \right)^2 $$

$$ p_{n} : \mathcal{D} \rightarrow \mathbb{R} $$

$\lambda_{n}$ denotes the eigenvalues and $p_{n}$ denotes the eigenfunctions. The eigenfunctions are scalar pressure fields.

The construction of $F$ follows from the wave equation itself. We discussed the basics of eigenproblems in the Acoustic Modes of a Rectangular Room episode. The fundamentals also hold in the general case. We solve the eigenproblem by imposing the wave equation solution to be factorised. By factorised we mean that the solution is the product of a spatial and temporal part. The spatial part solution depends on the geometry and boundary conditions. Instead, the temporal part solution is always harmonic. The solver provides the spatial part: it is the eigenfunction. The temporal part is easy to construct. Hence, we have all the ingredients ready to compute $F$ for each eigenvalue number $n$:

$$ F_{n}:\mathcal{D} \times \mathbb{R} \rightarrow \mathbb{R} \quad \forall n = 1 \space, 2 \space, \dots, \space N_{E}$$

$$ F_{n} \left(\mathbf{u}, t \right) \doteq A_{n} p_{n}\left(\mathbf{u}\right) \cos \left( \omega_{n} t + \phi_{n} \right) = $$

$$ = A_{n} p_{n}\left(\mathbf{u}\right) \cos \left( \sqrt[+]{\lambda_{n}} t + \phi_{n} \right) $$

$A_{n} \in \mathbb{R}$ and $\phi_{n} \in \left[-\pi, \space \pi \right]$ are, for each $n$, an arbitrary amplitude and phase respectively. A common choice is reported below:

$$ A_{n} = \frac{1}{\max_{\mathcal{D}} \left( \left| p_{n}\left(\mathbf{u}\right) \right| \right)} $$

$$ \phi_{n} = 0 $$

With the choice above $F_{n}$ will only assume values in $\left[-1, \space 1 \right]$ and will have no phase shift. This special definition of $F_{n}$ is put together below for convenience:

$$ F_{n} \left(\mathbf{u}, t \right) \doteq \frac{p_{n}\left(\mathbf{u}\right)}{\max_{\mathcal{D}} \left( \left| p_{n}\left(\mathbf{u}\right) \right| \right)} \cos \left( \omega_{n} t \right) $$

### Elastic Eigenfunctions

We have this kind of solution when we use the Linear Elasticity solver to solve an eigenproblem. The eigenfunctions are now displacement vector fields. Hence:

$$ n = 1 \space, 2 \space, \dots, \space N_{E} $$

$$ \lambda_{n} = \omega_{n}^2 = \left( 2 \pi f_{n} \right)^2 $$

$$ d_{n} : \mathcal{D} \rightarrow \mathbb{R^3} $$

We now denote the eigenfunction with $d$ as that has the meaning of displacement. We formulated the above for three-dimensional problems. For any other dimensionality just change the exponent of $\mathbb{R}$. Also in this case $d$ is a spatial part that we complement with an harmonic temporal part. Hence:

$$ F_{n}:\mathcal{D} \times \mathbb{R} \rightarrow \mathbb{R}^3 \quad \forall n = 1 \space, 2 \space, \dots, \space N_{E}$$

$$ F_{n} \left(\mathbf{u}, t \right) \doteq A_{n} d_{n}\left(\mathbf{u}\right) \cos \left( \omega_{n} t + \phi_{n} \right) $$

The amplitude $A_{n}$ and phase $\phi_{n}$ can be set to any value. Most often the results are scaled to unit peak amplitude and the initial phase shift is set to $0$. We can do this as follows:

$$ A_{n} = \frac{1}{\max_{\mathcal{D}} \left( \left\lVert d_{n}\left(\mathbf{u}\right) \right\rVert \right)} $$

$$ \phi_{n} = 0 $$

Note the use of the euclidean norm $\left\lVert \bullet \right\rVert$ as we are now dealing with a vector field. The final form with the choices above is shown below:

$$ F_{n} \left(\mathbf{u}, t \right) \doteq \frac{d_{n}\left(\mathbf{u}\right)}{\max_{\mathcal{D}} \left( \left\lVert d_{n}\left(\mathbf{u}\right) \right\rVert \right)} \cos \left( \omega_{n} t \right) $$

### A Note one Eigenfunction Scaling

In the previous sections we scaled all eigenfunctions to unity. This is correct as eigenfunctions do not have an intrinsic physical amplitude. In fact, whenever a modal system is driven, its steady state is the sum of all the eigenfunctions. However, the the driving quantity dictates the amplitudes and phases of each eigenfunction. In the absence of a driving quantity simple scaling to unity is then appropriate.

## Step 2: Computing the Frames

Now we got $F$ (or $F_{n}$) for all the cases we treated so far. Of course, $F$ is defined for every time instant. Time is also a continuous real variable. When we make an animation we focus on a certain time interval. Then, we take *snapshots* of this time interval at regular times. These snapshots are called *frames*. This can be done in a variety of ways. Below we will discuss a simple effective way. Since $F$ and each of the $F_{n}$ are handled identically we will denote with $F$ any field under our consideration.

By looking at all the definitions of $F$ abvove we can see a regular pattern. They are all periodic (thanks to the $\cos$ terms). All depend on an angular frequency we can in general denote with $\omega$. Hence, the period is:

$$ T \dot = \frac{1}{f} = \frac{2 \pi}{\omega}$$

A natural selection for the interval of interest is then $\left[0, \space T \right)$. We can then compute all the frames of the animation over one period. For longer animations we loop one period without needing any further computation.

Next, we want to decide how long we want our period animation to be. We can have it $T$ seconds long. But, if the frequency is high (even just more than $10$ $\text{Hz}$) the period will play very fast. So, let’s call $T_{p} \in \mathbb{R}^{+}$ the period playback duration. We then replace $t$ in $F$ definition with $\tau$ defined as followed:

$$ \tau \doteq \frac{T}{T_{p}}t $$

$$ F \left(\mathbf{u}, t \right) \mapsto F \left(\mathbf{u}, \tau \right) = F \left(\mathbf{u}, \frac{T}{T_{p}}t \right) \quad \forall t \in \left[0, \space T \right)$$

This effectively changes the period of the field from $T$ to $T_{p}$. Equivalently, it changes its frequency from $f$ to the animation frequency $f_{p}=\frac{1}{T_{p}}$. We can think of this as observing the field with a different time speed:

$$ \frac{T}{T_{p}} > 1 \space \Rightarrow \space \text{fast} \space \text{forward} $$

$$ \frac{T}{T_{p}} = 1 \space \Rightarrow \space \text{no} \space \text{change} $$

$$ \frac{T}{T_{p}} < 1 \space \Rightarrow \space \text{slow} \space \text{motion} $$

The ratio between $T$ and $T_{p}$ then controls how we change the speed of time. If the ratio is $2$ then the animation will run twice as fast as the physical speed. If the ratio is $\frac{1}{2}$ then the animation will run at half speed.

Finally, we choose how many frames per unit time we want our animation to have. We introduce then the *frame rate* $\nu$, measured in $\text{Hz}$. Associated to it we have the *frame duration* $T_{f}$:

$$ T_{f} \doteq \frac{1}{\nu} $$

A common choice is $\nu=24$ frames per second ($\text{Hz}$). Now we can proceed to *sample* our field. Let’s call the resulting frames $V$. Hence:

$$ V\left[m\right] \doteq F \left(\mathbf{u}, \frac{T}{T_{p}} m T_{f} \right) $$

$m$ is an integer going from $0$ to $\lfloor T \nu \rfloor - 1$, with $\lfloor \bullet \rfloor$ denoting the flooring operation. To prevent aliasing, ensure the animation frequency $f_{p}$ is lower than $\frac{\nu}{2}$:

$$ \text{ensure} \space f_{p} < \frac{\nu}{2} \Leftrightarrow T_{p} > 2 T_{f} $$

To have a nice and smooth animation we will often have $T_{p}$ longer than $1$ $\text{s}$. Also, we will have many frames per second. If this is the case the condition above is satisfied.

## Step 3: Frames in Practice

Now that we have an expression for the frames $V\left[m\right]$ we can use the expression to produce real frames. The best way is to use a technical computing language. Python and Julia are very good choices, but other are possible (Matlab, Octave, …). With Python we can use the excellent package `meshio`

to import our `vtu`

file in our programming environment. Through PyCall.jl we can use `meshio`

with Julia as well. In fact, this is exactly what the functions `load_mesh`

and `write_mesh`

from our FEATools.jl package do. To have an introduction to `meshio`

from a Jula perspective, refer to the Intro to meshio episode.

In essence we want our algorithm to:

- Read the
`vtu`

file; - Read or be provided with the simulation frequency $f$ so that it can compute $T$;
- Be provided with the playback duration $T_{p}$ and the framerate $\nu$ to compute the sampling instants;
- For every sampling instant compute the frame $V\left[m\right]$ and save it to file with a timestamp suffix.

Rather than going into the details for each case we will provide a generalised pseudocode below. Also, we will point to existing implementations you can use as examples.

### Pseudocode

```
# These are either read from file or provided as input:
f # Simulation frequency, Hz
sol # Array containing the FEM field, one value (complex or real or vector) for each node point.
Tp # playback duration, s
nu # framerate, Hz
T = 1/f # physical period
Tf = 1 / nu # Frame duration
M = div(T, Tf) # This is the number of frames. div is integer division
m_axis = 0:(M - 1) # Frames index axis.
for m in m_axis:
V = # Use the correct equaiton above to compute V from sol, F and m
save('case_t$m.vtu') # We use the frame index in the file name.
```

### Examples:

It is recommended you read the Intro to meshio episode before reading the examples.

- Steady state pressure and elastic displacement field animation here;
- Elastic eigenfunctions animations here;

# Preparing Animations with ParaView

Now that we have a series of timestamped `vtu`

files we can import them into ParaView. Choose *File* > *Open* and navigate to the location where you stored your series of `vtu`

files. ParaView groups the all together, which is convenient. Select the entire group as shown below and click *OK*. You will also need to click *Apply* in the *Properties* browser on the left.

Now that the time series is imported you can apply filters. This works just like for single `vtu`

files. You can refer to the Intro to ParaView episode for guidance. Also, provided that you solve the study first, you can load into ParaView any of the `pvsm`

files in the repositories. You can use these files as examples for your postprocessing. Refer to the `README`

in each repository for instruction on how to do so.

To navigate between frames and play your animation you can use the controls in the top bar:

Note that every time you switch frame in ParaView the visualisation will be updated. Depending on how many filters you have, their type and complexity, this could take some time.

Whenever you apply a filter note that you can scale the colormap to the data range over all the timestamps. An example is shown below.

After you are satisfied with your animation you can export it. Use *File* > *Save Animation*. Saving it as an `avi`

file is perhaps easiest, as it produces a video rather than a set of pictures. Once you selected the file name the *Save Animation Options* windows will popup. If you have multiple views you might want to tick the *Save All Views* tickbox. Remember to input your frame rate in the *Frame Rate* textbox. An example is shown below. Click *OK* to begin exporting your animation. This can take some time.

If you are on Linux or Mac you will be able to use a simple `ffmpeg`

command to loop the animation. For example, if you saved your animation as `animation.avi`

and want to loop it $10$ times:

```
ffmpeg -stream_loop 10 -i animation.avi -c copy animation_loop.avi
```

This will create a file `animation_loop.avi`

which contains the $10$ looped periods.

# Conclusion

In this episode we covered the basic concepts behind creating animations with ParaView. The most important, and complex, part is the input data preparation. We need to have a series of timestamped `vtu`

files. Transient simulations will output such as series. Steady State simulations, harmonic simulations and eigenproblems will not. In this episode we have discussed how to:

- Create time dependent fields from steady state, harmonic and eigenfunction fields;
- Sample these fields at regular intervals to yield frames of an animation over one period;
- Compute and save the frames to file.

Once the frames are ready they can be imported in ParaView and processed as usual. We shown few specific options and controls for animations. For more details on ParaView, see the Intro to ParaView episode.

We did not solve transient simulations yet. We can import the output of those into ParaView. This is straightforward if the the timastamps are uniformly spaced. Otherwise we might need to carry extra processing before importing into ParaView. We will cover this when we handle transient simulations.

# License Information

This work is licensed under a Creative Commons Attribution 4.0 International License.