Skip to content

Exercise 2 - A Tornado simulation

Introduction

In this exercise we will take a look at the results of simulating the air flow in a tornado. The relevant dataset contains velocity vectors on a regular 3D grid (a so-called flow field). The data is contained in a simple file format: the well-known comma separated values format (CSV).

The advantage of CSV is that it is a simple and human-readable format, and can be written and read by many applications. However, it is not always an efficient way of storing (large) datasets.

Importing and preparing the data

The data contained in the CSV file is not automatically identified and understood correctly by ParaView, it simply does not have enough information for that. Therefore when we open a CSV file, we first have to apply some filters to map the data to the correct data arrays that we can operate on. After this is done, we can use a stream-tracer filter on it to get a good impression of the air flow in this simulation.

▶ The first thing to do is to create a new session, and start with a clean view. For this, use the disconnect button in the toolbar and pressing Yes (or the File → Disconnect menu option). This will completely clean your current pipeline, so you can start the next exercise:

▶ Open the wervel.csv file and click Apply. ParaView will ask which reader to use, pick CSV Reader and click Ok. Next, use Apply to actually load the data. A new view pane with a table representation of the data will get added next to existing the 3D view. The table is similar to a spreadsheet:

If you would open the CSV file in a text editor you would see the file contains 7 values per line, with each line representing one grid point. ParaView turns this into a list of rows, each with 8 columns holding values. Note that ParaView adds the Row ID column itself, it does not come from the file.

The column values are:

  • A unique identifier per point, i
  • x, y, and z values defining a location on a 3D cartesian grid.
  • vx, vy and vz values, representing a 3D velocity vector at the (x,y,z) location

▶ Verify that the ParaView spreadsheet view indeed shows the same set of data.

ParaView does not know by itself how these individual variables relate to the points and cells in its data model, so we have to provide that mapping manually.

▶ The first step is to add a TableToPoints filter to our data source. This filter creates a 3D point for each row in the table, based on a set of table values you choose. You can find this filter under Filters → Alphabetical → TableToPoints. Set the X, Y and Z columns correctly to the table columns representation 3D point position, check Keep All Data Arrays and hit Apply.

▶ Compare the Information tabs of the wervel.csv source and the TableToPoints filter to see how the output data has changed (type, number of points/cells, etc), and verify that the data arrays produced by the TableToPoints filter match those of the wervel.csv source.

▶ If needed, enable visibility of the TableToPoints output by clicking the eye icon next to it in the pipeline browser. If you have both a RenderView (the 3D panel) and a Spreadsheet view then make sure you have the RenderView selected (by clicking in it) before enabling visibility of the TableToPoints output. You should now see a regular 3D grid of (white) points, indicating that the point position values from the CSV data have correctly been set based on the table input.

Creating velocity vectors

Next, we need to combine the three separate scalar values vx, vy and vz into one 3D vector value. To do this, we use the Calculator filter that is built into ParaView.

Note

There is also a Python Calculator filter, which is more powerful, but we don't use it here as it is somewhat buggy for what we want to do here.

▶ With the TableToPoints filter selected add a Calculator filter (Filter → Common → Calculator). In the Result Array Name field enter "Velocity", in the text box below that enter the exact expression shown and hit Apply. This will create a Velocity data array that holds the vector value (vx,vy,vz) for each point. Again, check the filter output data on the Information tab to verify this.

Warning

A common mistake is to enter the expression in the Search box above the calculator properties:

This will cause properties to get filtered to those matching the entered text (and there aren't any), hiding them all.

You will probably have understood the name iHat to represent the vector î, i.e. (1, 0, 0). Using the Calculator filter fairly complex expressions can be used to augment existing datasets with new and useful values, both scalars and vectors.

The pipeline we built up to this point, shown above, creates a Polygonal Mesh dataset which contains only points: the input point positions with their respective 3D velocity vectors. You can see this on the Information tab for the Calculator filter in the pipeline browser (as shown below). Note that there is a single cell, but it holds 25,000 points. If you were to check the spreadsheet view you would see that that one cell is of type Polyvertex, meaning it only holds 3D points (but not 3D cell regions, or surfaces).

We also added a quantity derived from the input data, i.e the Velocity vector. Note that its X and Y components cover a fairly even positive and negative range, while for the Z component the value range is mostly positive. The latter gives some indication of how the 3D velocity vectors in the field are oriented (and what this means for air flow in the tornado).

Visualizing the flow field

Now that our data is converted from the CSV input to an adequata ParaView dataset we can start looking at our flow field. To do this, we want to use the stream-tracer filter. With this filter we simulate injecting particles in our flow field at specific locations. By letting these particles follow the flow based on the velocity vectors in the grid, and tracing them using integration, we get an impression of the fluid flow through the dataset.

However, the stream-tracer filter is based on tracing a virtual particle through the cells of a dataset, i.e. small sub-regions of the model space. The flow direction within a cell, as indicated by the velocity vector value, is then integrated by the filter to determine a particle's position over time, thereby creating a trace of the particle through the dataset.

But as noted above, there's currently only a single cell in our dataset holding only 3D points, which provides no meaningful way to trace particles. So we need to divide up the dataset domain into smaller regions.

We can fix this applying a 3D Delaunay triangulation. This creates cells on the dataset spanning the existing 3D point locations. The cells created are small regions of 3D space, and are detailed enough so that our Stream Tracer filter can reasonably work and provide useful output.

▶ Select the Calculator1 filter and add a Delaunay 3D filter using Filters → Miscellaneous → Delaunay3D and click Apply. It might take a few seconds for the computation to complete.

The representation of the data in the 3D view will now have changed to a block, instead of points, indicating that there are now cells which take up regions of 3D space. If you were to check the spreadsheet view you would see that all cells produced by the Delaunay 3D filter are of the type Tetrahedron, a four-sided geometric shape specified by four 3D points.

▶ Check the Information tab for the Delaunay 3D filter and switch to Surface With Edges representation to see how the data has changed, in terms of type, cells and points. You could also clip away part of the dataset with the Clip filter to look at the cell structure inside of the dataset.

The pipeline we constructed so far should look like this:

Tracing particles

Now let's do some initial particle tracing through the flow field using the stream tracer filter.

▶ In the pipeline, select the Delaunay3D filter and add a Stream Tracer filter. You can find this under Filters → Common → Stream Tracer. Do not press Apply just yet.

▶ The Stream Tracer filter has quite a few parameters. Important ones are integration settings and the seed location for the particles to trace. Change them to, for example, the values below and click Apply:

This will give you a set of lines, each representing a trace of a particle as it follows the flow in the tornado.

▶ Note the small red 3D axis and large sphere at the bottom of the tornado: this is the seed region centered at (12,12,1) with given radius 12 from which the 100 traced particles start. You could experiment with different locations of the seed region to see how this influences the streamlines.

Accidental sphere changes / Resetting a filter to last executed values

The sphere shown can actually be moved by dragging in the 3D view, which alters the corresponding values set for the Point Cloud Parameters. Sometimes, during 3D interaction with the view you might accidentally change a widget, such as the sphere here (there's more widgets, for example to set the location of a clip plane), which changes filter parameters. In case you did not want this to happen you can reset a filter back to the values it used since the last Apply by using the Reset button at the top of the Properties panel.

In most cases a widget can be hidden using a filter option, which prevents further interaction with it. Hiding the sphere here can be done by disabling the Show Sphere option under Point Cloud Parameters.

Tubes, and tweaking the streamlines

▶ To make the streamlines more visually appealing, we add another filter on the output of the StreamTracer filter, namely a Tube filter (Filters → Miscellaneous → Tube). In the Tube filter's Properties tab, set the radius of the tubes to 0.1 and click Apply. Notice how this changes the appearance of the streamlines.

▶ At this point, we'd like to add the original data domain as an outline. For this, enable visibility of the TableToPoints filter and switch its representation to Outline.

▶ As you can see the stream lines do not reach the top of the domain (while we would expect the upward draft within the tornado to go high). In the Stream Tracer filter we have set a Maximum Streamline Length, which limits the length of the stream lines. Try some different values for this setting.

▶ The stream trace filter currently integrates the path of the virtual particles in the forward direction only, as option Integration Direction is set to FORWARD. Another tweak we can make is to also allow the stream trace filter to integrate backwards, by setting the option to BOTH. By also following the velocity vectors in the opposite direction it adds parts of the streamlines that can reach the seed region (instead of only originating from it).

▶ You can experiment with different colorings of the tubes, based on e.g. velocity, angular velocity or rotation. Use the coloring controls in the filters settings under Coloring for this.

Finally, here's an example of visualizing the tornado dataset, based on the options given above:

Glyphs

Finally, we'll add a different representation instead of the streamlines, called glyphs, which are used a lot for flow fields. Glyphs are simple and (usually) small 3D objects, like arrows or spheres. These glyphs get placed at each point position in a dataset to show a particular value. The glyphs are then colored, scaled and/or oriented based on scalar or vector values at the location. We'll use arrow glyphs here to show the flow velocity magnitude and direction in the tornado.

▶ Hide all filter output, except the TableToPoints filter (the domain), by clicking the relevant eye icons.

▶ Select the Calculator2 filter and add a Glyph filter (Filters → Common → Glyph). Set the Glyph Type to Arrow, set the Orientation Array to Velocity (i.e. our computed velocity vectors) and Scale Mode to No scale array. Click Apply.

Point versus cell input

Note that there is no need to base the Glyph filter on the Delaunay 3D output, as the Glyph filter works on 3D points, as present in the original data set. This is unlike the Streamtracer filter, which operates on cells (which we created by adding the Delaunay 3D filter).

ParaView does provide generic Point Data to Cell Data and Cell Data to Point Data filters, to convert between the two using interpolation.

You should now see a large number of arrows nicely distributed over the tornado dataset, indicating the direction of air flow. As we have set the Scale Mode to Off all arrows are the same size, obscuring the insides and giving less of a visual clue to air speed.

Let's try to improve the overall visualization, to make it easier to interpret.

▶ Set the Scale Array to Velocity and the Scale Factor to 0.2 and press Apply.

▶ Make sure the coloring is set to VelocityMag and verify that the size and colors of a glyph arrow corresponds to its velocity value.

You might wonder about the the number of glyphs placed, compared to the 25,000 points in the dataset. There is currently quite a large number of glyphs, and perhaps still too many to be effective. This doesn't help in the overall visual interpretation of the data, but we do need to balance getting enough coverage of the full dataset.

▶ The filter settings under Masking provide different options for the number and distribution of the glyphs placed. For example, see what happens when using Glyph Mode Every Nth point when you show a glyph for every 10th or 11th point (the Stride value). Or use 500 glyphs uniformly distributed (and why that means you need choose these kinds of parameters with care).

▶ A useful variant is to apply glyphs to the output of the Stream Trace filter, by creating a second Glyph filter. This is possible because the generated streamlines are themselves polygonal data, where each streamline consists of a PolyLine (or Line) cell that is described by a set of 3D points. As a Glyph filter uses point positions to place glyphs we can place them for each streamline. Experiment with this, using different types of glyphs, like Sphere and Arrow. Also try coloring by IntegrationTime to verify the direction in which the streamlines where "grown".