Author: Riley X. Brady
Date: March 17th, 2020
Note: This is a very early draft. I'll likely expand this into a blog post in the future.
The particles first need to be pre-processed to work in ParaView. At the base level, our particles are saved out in netCDF history files with xParticle, yParticle, zParticle, zLevelParticle (depth).
We use this script to convert the raw netCDF into VTK files: https://gist.github.com/bradyrx/b9d8ba50ab42372521d2501f82fead97.
This creates VTK "Points" data with the appropriate x, y, and z labeling it is seeking. All other variables (like depth,
temperature, latitude and longitude, etc.) get carried along. What's crucial is that the x/y/z information is encoded in
the x/y/z entries, e.g. pointsToVTK(f_out, x, y, z, data=particleData)
in the script. This helps the particle filter
in ParaView recognize how to draw the pathlines behind the particle.
NOTE:
If you only have lat/lon on the particles, we use this function to convert from x, y, z to lat/lon. I'm sure it can be worked backwards to find how to go from lat/lon to x, y, z:
subroutine convert_latlon_from_xyz(lat, lon, x, y, z) !{{{
implicit none
! given xyz coordinates determine the latitude and longitude
real(kind=RKIND), intent(out) :: &
lat, & !< Output: latitude of point
lon !< Output: longitude of point
real(kind=RKIND), intent(in) :: &
x, & !< Input: x position of point
y, & !< Input: y position of point
z !< Input: z position of point
real(kind=RKIND) :: r !< Computed: radius of earth
r = sqrt(x*x + y*y + z*z)
lon = atan2(y, x)
lat = asin(z/r)
! ensure range in 0, 2*pi
if (lon < 0.0_RKIND) then
lon = 2*pii + lon
end if
end subroutine convert_latlon_from_xyz !}}}
-
After setting up your Eulerian mesh, bathymetry/topography, etc. in ParaView, load in the particles VTK file. There will probably be a file for each time step, so you load in the
.pvd
file containing all time steps. -
Apply the
Temporal Interpolation
filter to the object, leaving all arguments blank in the filter. If you save out an animation, this interpolates the particle paths smoothly if you have more frames than time steps in the particle trajectories. -
Apply
TemporalParticlesToPathlines
filter to your particles. The "Mask Points" option says how many particles you want to mask. If you enter1
, you'll get all particles,2
is every other, and so on. "Max Track Length" is how many time steps to retain when drawing the pathlines. I think of it like the old arcade game snake. The tail will disappear at the max track length value. If you have 180 time steps and enter 180 here, you'll have the whole path plotted. "Max Step Distance" will remove particles that move a certain distance (buggy particles). Our particles have true cartesian x/y/z information, so I make this1e6
since it's moving in units of meters around the Earth's surface at 2-day output. This just ensures I keep all the particles.
- This creates a
Pathlines
andParticles
object in the viewer. TheParticles
object shows the current location of the particle. You can make this a sphere for instance. ThePathlines
will show up as you step forward in time in Paraview. These are the pathlines of the particle trajectory history. You can color these lines by a variable, particleID, or just make them a solid color.
NOTE: The biggest thing to learn is that you have to actually manually step through each time step to draw the pathlines. You can't just jump to time step 100 and have the whole path drawn. Paraview draws the path as the particles move. So once you have everything set up, click it forward a few steps to make sure it looks good before drawing out the whole path (i.e. pressing the "play" button and moving through all time steps).
Once I have everything working, I do "Save Animation" with pngs and save out every frame to make into a movie
with ffmpeg
or DaVinci Resolve.