Pin37 movie

Overview

This movie was composed of four main parts:

  1. Animating over time while zoomed in. (The zoom in view is referred to as "J3".)
    • This section is referred to as "J3", because J3 is a location in the volume.
  2. Animating over time again while animating the camera
    • This section is referred to as "fly"
  3. Animating over time while zoomed out
    • This section is referred to as "starwars"
  4. Animating a clip plane while animating in time
    • This section is referred to as "clip"

The simulation is of turbulent flow in a nuclear reactor. Because it is so turbulent, we decided to loop the time-varying data over and over. So each section is repeating the same data.

Also, because it takes so long to read in each time slice, we rendered each of the four movie sections (J3, fly, starwars, & clip) while the time slice was in memory.

Script

# *****************************************************************************
#  Script: 37pin.py
# 
#  Purpose:
#     Makes a movie of a turbulence simulation.
#
#  Notes:
#     (1) This script should be run as:
#           /soft/apps/visit/bin/visit -cli -nowin -verbose -s 37pin.py
#     (2) Frequent parameters to change are:
#           I.   The views (located in StarWarsView, J3View, and FlyView)
#           II.  The volume transfer function (located in AddVolumePlot)
#           III. The window size (located in the SaveWindowAttributes)
#           IV.  The number of processors (located in LaunchComputeEngine)
#
#  Author:   Hank Childs
#  Creation: November 2008
#
# *****************************************************************************

import os
import sys

def LaunchComputeEngine():
   OpenComputeEngine("localhost", ("-l", "qsub/mpirun", "-t", "1200", "-np", "160", "-nn", "80", "-machinefile", "$COBALT_NODEFILE", "-lb-stride"))

# This allows us to have acceleration, which makes the transition between
# effects like fly-throughs and clips not feel jumpy.
def SineParameterize(nFrames, curFrame, ramp):
   # We are going to construct a function that has sine curves at either
   # end and a flat ramp in the middle.  We will then parameterize space
   # by determining what portion of the total area has been covered by
   # frame "curFrame".
   nFrames -= 1
   if 2*ramp > nFrames:
      print "Ramp too large -- correcting"
      ramp = nFrames / 2
   if ramp <= 0:
      return 1.
   if nFrames <= 0:
      return 1.
   nNonRamp = nFrames - 2*ramp
   # determine the height of our function
   height=1./(float(nNonRamp) + 4*float(ramp)/math.pi)
   if curFrame < ramp:
      factor=2*height*ramp/math.pi
      eval=math.cos((math.pi/2.)*(float(curFrame)/float(ramp)))
      return (1. - eval)*factor
   elif curFrame > nFrames-ramp:
      amount_left = nFrames-curFrame
      factor=2*height*ramp/math.pi
      eval=math.cos((math.pi/2.)*(float(amount_left)/float(ramp)))
      return 1. - (1. - eval)*factor
   else:
      amount_in_quad=curFrame-ramp
      quad_part=amount_in_quad*height
      curve_part=height*(2*ramp)/math.pi
      return quad_part+curve_part

# Turn off annotation, set up colors
def GeneralSetup():
  r = RenderingAttributes()
  r.scalableActivationMode = r.Always
  SetRenderingAttributes(r)
  a = GetAnnotationAttributes()
  a.axes3D.visible = 0
  a.axes3D.bboxFlag = 0
  a.axes3D.triadFlag = 0
  a.userInfoFlag = 0
  a.databaseInfoFlag = 0
  a.legendInfoFlag = 0
  a.backgroundColor = (0, 0, 0, 255)
  a.foregroundColor = (0, 0, 0, 255)
  a.gradientBackgroundStyle = a.Radial  
  a.gradientColor1 = (0, 0, 0, 255)
  a.gradientColor2 = (0, 0, 0, 255)
  a.backgroundMode = a.Solid  # Solid, Gradient, Image, ImageSphere
  SetAnnotationAttributes(a)
  l = GetLight(1)
  l.enabledFlag = 1
  l.type = l.Ambient
  l.brightness = 0.25
  SetLight(1, l)

# We need to clip away part of the volume to see inside.
def ApplyClip():
  AddOperator("Clip")
  c = ClipAttributes()
  c.quality = c.Accurate  # Fast, Accurate
  c.funcType = c.Plane  # Plane, Sphere
  c.plane1Status = 1
  c.plane2Status = 1
  c.plane3Status = 1
  c.plane1Origin = (0, 3.58, 0)
  c.plane2Origin = (2.91, 2.11, 0)
  c.plane3Origin = (2.91, -2.11, 0)
  c.plane1Normal = (0, -1, 0)
  c.plane2Normal = (-1.73, -1, 0)
  c.plane3Normal = (-1.73, 1, 0)
  c.planeInverse = 1
  SetOperatorOptions(c)


def ApplyIsosurface():
  AddOperator("Isosurface")
  i = IsosurfaceAttributes()
  i.contourMethod = i.Value
  i.variable = "z_velocity"
  i.contourValue = (0.001)
  SetOperatorOptions(i)

def AddPseudocolorPlot():
  AddPlot("Pseudocolor", "pressure")
  pc = PseudocolorAttributes()
  pc.minFlag = 1
  pc.maxFlag = 1
  pc.min = -1.5
  pc.max = 0.75
  pc.colorTableName = "bluehot"
  SetPlotOptions(pc)

# This volume plot was made in the GUI and then copied over.  
# (Actually, I then tweaked it again from the CLI.)
def AddVolumePlot():
  AddPlot("Volume", "z_velocity")
  v = VolumeAttributes()
  v.legendFlag = 1
  #v.lightingFlag = 1
  v.lightingFlag = 0
  v.GetColorControlPoints().RemoveControlPoints(4)
  v.colorControlPoints.GetControlPoints(0).colors = (255, 255, 0, 0)
  v.colorControlPoints.GetControlPoints(0).position = 0
  v.colorControlPoints.GetControlPoints(1).colors = (255, 255, 0, 0)
  v.colorControlPoints.GetControlPoints(1).position = 0.75
  v.colorControlPoints.GetControlPoints(2).colors = (128, 0, 0, 0)
  v.colorControlPoints.GetControlPoints(2).position = 0.875
  v.colorControlPoints.GetControlPoints(3).colors = (255, 0, 0, 0)
  v.colorControlPoints.GetControlPoints(3).position = 1
  v.colorControlPoints.smoothingFlag = 1
  v.colorControlPoints.equalSpacingFlag = 0
  v.colorControlPoints.discreteFlag = 0
  v.colorControlPoints.externalFlag = 0
  v.opacityAttenuation = 0.3
  v.freeformFlag = 1
  #controlPoints does not contain any GaussianControlPoint objects.
  v.opacityVariable = "default"
  v.freeformOpacity = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 148, 152, 156, 160, 164, 168, 172, 176, 180, 184, 188, 192, 196, 200, 204, 208, 212, 216, 220, 224, 228, 232, 236, 240, 244, 248, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255)
  v.useColorVarMin = 1
  v.colorVarMin = 0
  v.useColorVarMax = 1
  v.colorVarMax = 2
  v.samplesPerRay = 2500
  v.rendererType = v.RayCasting  # Splatting, Texture3D, RayCasting, RayCastingIntegration, SLIVR
  SetPlotOptions(v)

def StarWarsView():
  v = GetView3D()
  v.viewNormal = (0.377094, 0.128091, 0.917275)
  v.focus = (0, 0, 13.3203)
  v.viewUp = (-0.123671, 0.988485, -0.0871936)
  v.viewAngle = 30
  v.parallelScale = 14.4013
  v.nearPlane = -15.8026
  v.farPlane = 15.8026
  v.imagePan = (0.0330559, 0.0411823)
  v.imageZoom = 2.60908
  v.perspective = 1
  v.eyeAngle = 2
  v.centerOfRotationSet = 0
  v.centerOfRotation = (0, 0, 13.3203)
  SetView3D(v)

def J3View():
  v = GetView3D()
  v.viewNormal = (0.377094, 0.128091, 0.917275)
  v.focus = (0, 0, 13.3203)
  v.viewUp = (-0.123671, 0.988485, -0.0871936)
  v.viewAngle = 30
  v.parallelScale = 14.4013
  v.nearPlane = -15.8026
  v.farPlane = 15.8026
  v.imagePan = (-0.0865573, -0.0752562)
  v.imageZoom = 20
  v.perspective = 1
  v.eyeAngle = 2
  v.centerOfRotationSet = 0
  v.centerOfRotation = (0, 0, 13.3203)
  SetView3D(v)

# Sets the view based on interpolating a spline
def FlyView(i, N):
  v1 = GetView3D()
  v1.viewNormal = (0.377094, 0.128091, 0.917275)
  v1.focus = (0, 0, 13.3203)
  v1.viewUp = (-0.123671, 0.988485, -0.0871936)
  v1.viewAngle = 30
  v1.parallelScale = 14.4013
  v1.nearPlane = -15.8026
  v1.farPlane = 15.8026
  v1.imagePan = (-0.0865573, -0.0752562)
  v1.imageZoom = 20
  v1.perspective = 1
  v1.eyeAngle = 2
  v1.centerOfRotationSet = 0
  v1.centerOfRotation = (0, 0, 13.3203)
  # J3View, looking over to the side
  v2 = GetView3D()
  v2.viewNormal = (0.167224, 0.0931997, 0.981504)
  v2.focus = (-1.13302, -0.27483, 12.4838)
  v2.viewUp = (-0.121935, 0.989834, -0.073216)
  v2.viewAngle = 30
  v2.parallelScale = 14.4013
  v2.nearPlane = -15.8026
  v2.farPlane = 15.8026
  v2.imagePan = (-0.0865573, -0.0752562)
  v2.imageZoom = 20
  v2.perspective = 1
  v2.eyeAngle = 2
  v2.centerOfRotationSet = 1
  v2.centerOfRotation = (2.78494, 2.32635, 7.55293)
  # Zoomed in, translated all the way over
  v3 = GetView3D()
  v3.viewNormal = (0.208352, 0.105336, 0.972365)
  v3.focus = (-1.48394, -0.369883, 12.6931)
  v3.viewUp = (-0.122478, 0.989167, -0.0809122)
  v3.viewAngle = 30
  v3.parallelScale = 14.4013
  v3.nearPlane = -15.8026
  v3.farPlane = 15.8026
  v3.imagePan = (-0.0768782, -0.0593683)
  v3.imageZoom = 7.16773
  v3.perspective = 1
  v3.eyeAngle = 2
  v3.centerOfRotationSet = 1
  v3.centerOfRotation = (2.97878, 1.991, 20.8292)
  # Star wars view
  v4 = GetView3D()
  v4.viewNormal = (0.377094, 0.128091, 0.917275)
  v4.focus = (0, 0, 13.3203)
  v4.viewUp = (-0.123671, 0.988485, -0.0871936)
  v4.viewAngle = 30
  v4.parallelScale = 14.4013
  v4.nearPlane = -15.8026
  v4.farPlane = 15.8026
  v4.imagePan = (0.0330559, 0.0411823)
  v4.imageZoom = 2.60908
  v4.perspective = 1
  v4.eyeAngle = 2
  v4.centerOfRotationSet = 0
  v4.centerOfRotation = (0, 0, 13.3203)
  vpts = (v1, v2, v3, v4)
  x = [0, 0.25, 0.5, 1.0]
  pos=SineParameterize(N, i, 32)
  v = EvalCubicSpline(pos, x, vpts)
  SetView3D(v)


def Beep():
  print "\a"
  print "\a"
  print "\a"

# Used to animate a Clip across the volume
def ApplyXClip(i, N):
  c = ClipAttributes()
  c.quality = c.Accurate
  c.funcType = c.Plane
  c.plane1Status = 1
  c.plane2Status = 0
  c.plane3Status = 0
  pos=SineParameterize(N, i, 32)
  X = -8.0*(pos) + 4.0
  c.plane1Origin = (X, 0, 0)
  c.plane1Normal = (1, 0, 0)
  c.planeInverse = 0
  SetActivePlots((0,1))
  SetDefaultOperatorOptions(c)
  AddOperator("Clip")


def SetUpPlots():
  AddPseudocolorPlot()
  ApplyIsosurface()
  ApplyClip()
  AddVolumePlot()

# Always launch the engine before opening a file.  
# When you open a file, VisIt will try to launch an engine if one does not already exist 
# and it will probably do a bad job.
LaunchComputeEngine()
OpenDatabase("/gpfs/home/fischer/p37/Fl/p37l.nek3d")
GeneralSetup()


for i in range((TimeSliderGetNStates()/2)+1):
   timestep = 2*i
   print "\n\n\nTimestep is %d\n\n\n" %(timestep)
   names = [ "starwars", "j3_", "fly", "clip" ]
   needOne=False
   for j in range(len(names)):
      fullname = "%s%04d.tif" %(names[j], timestep)
      if not os.path.exists(fullname):
          needOne=True
   if not needOne:
      print "\n\n\nSKIPPING %d\n\n\n" %(timestep)
      continue
   else:
      print "\n\n\nDoing timestep %d\n\n\n" %(timestep)
   TimeSliderSetState(timestep)
   SetUpPlots()
   DrawPlots()
   Beep()
   for j in range(4):
      name = "%s%04d.tif" %(names[j], timestep)
      if os.path.exists(name):
         print "\n\n\nSKIPPING %s\n\n\n" %(name)
         continue
      else:
         print "\n\n\nDOING %s\n\n\n" %(name)
      if j == 0:
         StarWarsView()
      elif j == 1:
         J3View()
      elif j == 2:
         FlyView(timestep, TimeSliderGetNStates())
      elif j == 3:
         ApplyXClip(timestep, TimeSliderGetNStates())
         DrawPlots()
         StarWarsView()
      sw = SaveWindowAttributes()
      sw.fileName = "%s%04d" %(names[j], timestep)
      sw.family = 0
      sw.width = 1920
      sw.height = 1080
      sw.resConstraint = sw.NoConstraint
      SetSaveWindowAttributes(sw)
      SaveWindow()
      Beep()
   DeleteAllPlots()

SymLinks

Since the frames created by this script cannot be input directly to a movie encoder, we need to rename them so they can. I do this with symlinks.

#!/bin/ksh

rm -rf f????.ppm

X=0

Y=0
while (( Y <= 324 )) ; do
   Y4=$(printf %04d $Y)
   X4=$(printf %04d $X)
   ln -s small_j3_${Y4}.tif f${X4}.ppm
   (( X += 1 ))
   (( Y += 2 ))
done

Y=0
while (( Y <= 324 )) ; do
   Y4=$(printf %04d $Y)
   X4=$(printf %04d $X)
   ln -s small_j3_${Y4}.tif f${X4}.ppm
   (( X += 1 ))
   (( Y += 2 ))
done

Y=0
while (( Y <= 324 )) ; do
   Y4=$(printf %04d $Y)
   X4=$(printf %04d $X)
   ln -s small_fly${Y4}.tif f${X4}.ppm
   (( X += 1 ))
   (( Y += 2 ))
done

Y=0
while (( Y <= 324 )) ; do
   Y4=$(printf %04d $Y)
   X4=$(printf %04d $X)
   ln -s small_starwars${Y4}.tif f${X4}.ppm
   (( X += 1 ))
   (( Y += 2 ))
done

Y=0
while (( Y <= 324 )) ; do
   Y4=$(printf %04d $Y)
   X4=$(printf %04d $X)
   ln -s small_starwars${Y4}.tif f${X4}.ppm
   (( X += 1 ))
   (( Y += 2 ))
done

Y=0
while (( Y <= 324 )) ; do
   Y4=$(printf %04d $Y)
   X4=$(printf %04d $X)
   ln -s small_clip${Y4}.tif f${X4}.ppm
   (( X += 1 ))
   X4=$(printf %04d $X)
   ln -s small_clip${Y4}.tif f${X4}.ppm
   (( X += 1 ))
   (( Y += 2 ))
done

Movie encoding

See here