Python coprocessing example: Difference between revisions

From KitwarePublic
Jump to navigationJump to search
(Created page with 'This example is used to demonstrate how the coprocessing library can be used with a python based simulation code. Note that this example requires MPI to be available on your syst…')
 
 
(17 intermediate revisions by the same user not shown)
Line 1: Line 1:
This example is used to demonstrate how the coprocessing library can be used with a python based simulation code. Note that this example requires MPI to be available on your system as well as pyMPI to initialize and finalize MPI from the python script. The executable takes in a python coprocessing script and a number of time steps to be run for. Note to remember to set your system environment propery. See [[1]] for details.  
This example is used to demonstrate how the co-processing library can be used with a python based simulation code. Note that this example requires MPI to be available on your system as well as pyMPI to initialize and finalize MPI from the python script. The executable takes in a python co-processing script and a number of time steps to be run for. Note to remember to set your system environment properly. See [[http://paraview.org/Wiki/ParaView/Python_Scripting#Getting_Started]] for details.  


 
== Serial python driver code ==
== Python driver code ==
<source lang="python">
<source lang="python">
import sys
import sys
if len(sys.argv) != 3:
if len(sys.argv) != 3:
     print "command is 'pyMPI <python driver code> <script name> <number of time steps>'"
     print "command is 'python <python driver code> <script name> <number of time steps>'"
     sys.exit(1)
     sys.exit(1)
import mpi
mpi.initialized()
import paraview
import paraview
import paraview.vtk as vtk
import paraview.vtk as vtk
# initialize and read input parameters
paraview.options.batch = True
paraview.options.symmetric = True
def _refHolderMaker(obj):
    def _refHolder(obj2, string):
tmp = obj
    return _refHolder


def coProcess(grid, time, step, scriptname):
def coProcess(grid, time, step, scriptname):
     import libvtkCoProcessorPython #on windows do import vtkCoProcessorPython
     import vtkCoProcessorPython # import libvtkCoProcessorPython for older PV versions
    if scriptname.endswith(".py"):
        scriptname = scriptname[0:len(scriptname)-3]#scriptname.rstrip(".py")
     try:
     try:
cpscript = __import__(scriptname) # this doesn't seem to work properly for me
        cpscript = __import__(scriptname)
     except:
     except:
         print 'Cannot find ', scriptname, ' -- no coprocessing will be performed.'
         print 'Cannot find ', scriptname, ' -- no coprocessing will be performed.'
         return
         return


     datadescription = libvtkCoProcessorPython.vtkCPDataDescription()
     datadescription = vtkCoProcessorPython.vtkCPDataDescription()
     datadescription.SetTimeData(time, step)
     datadescription.SetTimeData(time, step)
     datadescription.AddInput("input")
     datadescription.AddInput("input")
Line 37: Line 27:
     if inputdescription.GetIfGridIsNecessary() == False:
     if inputdescription.GetIfGridIsNecessary() == False:
         return
         return
    import paraview.simple
    import paraview.vtk as vtk
    import paraview.numpy_support


     inputdescription.SetGrid(grid)
     inputdescription.SetGrid(grid)
    inputdescription.SetWholeExtent(grid.GetWholeExtent())
     cpscript.DoCoProcessing(datadescription)
     cpscript.DoCoProcessing(datadescription)


Line 48: Line 35:
     numsteps = int(sys.argv[2])
     numsteps = int(sys.argv[2])
except ValueError:
except ValueError:
     print 'the last argument should be a number'
     print 'the last argument should be a number, setting the number of time steps to 10'
     numsteps = 10
     numsteps = 10


for step in range(numsteps):
for step in range(numsteps):
     # assume simulatione time is from 0 to 1
     # assume simulation time starts at 0
     time = step/float(numsteps-1)
     time = step/float(numsteps)


     # create the input to the coprocessing library.  normally
     # create the input to the coprocessing library.  normally
Line 61: Line 47:
     imageData.SetOrigin(0, 0, 0)
     imageData.SetOrigin(0, 0, 0)
     imageData.SetSpacing(.1, .1, .1)
     imageData.SetSpacing(.1, .1, .1)
     imageData.SetDimensions(10, 12, 12)
     imageData.SetExtent(0, 10, 0, 12, 0, 12)
    imageData.SetWholeExtent(imageData.GetExtent())
     pointArray = vtk.vtkDoubleArray()
     pointArray = vtk.vtkDoubleArray()
     pointArray.SetNumberOfTuples(imageData.GetNumberOfPoints())
     pointArray.SetNumberOfTuples(imageData.GetNumberOfPoints())
Line 72: Line 59:
     # the passed in script says we should at time/step
     # the passed in script says we should at time/step
     coProcess(imageData, time, step, sys.argv[1])
     coProcess(imageData, time, step, sys.argv[1])
</source>
== Parallel python driver code ==
<source lang="python">
import sys
if len(sys.argv) != 3:
  print "command is 'mpirun -np <#> pyMPI parallelexample.py <script name> <number of time steps>'"
  sys.exit(1)


import paraview
import paraview.vtk as vtk
import mpi
mpi.initialized()
import paraview
import libvtkParallelPython
import paraview.simple
import vtk
# set up ParaView to properly use MPI
pm = paraview.servermanager.vtkProcessModule.GetProcessModule()
globalController = pm.GetGlobalController()
if globalController == None or globalController.IsA("vtkDummyController") == True:
  globalController = vtk.vtkMPIController()
  globalController.Initialize()
  globalController.SetGlobalController(globalController)
def coProcess(grid, simtime, simstep, scriptname):
  # the name of the library was changed so for previous version of ParaView
  # you have to import libvtkCoProcessorPython instead of vtkCoProcessorPython
  #import libvtkCoProcessorPython as vtkCoProcessorPython
  import vtkCoProcessorPython
  if scriptname.endswith(".py"):
    scriptname = scriptname[0:len(scriptname)-3]#scriptname.rstrip(".py")
  try:
    cpscript = __import__(scriptname)
  except:
    print 'Cannot find ', scriptname, ' -- no coprocessing will be performed.'
    return
  datadescription = vtkCoProcessorPython.vtkCPDataDescription()
  datadescription.SetTimeData(simtime, simstep)
  datadescription.AddInput("input")
  cpscript.RequestDataDescription(datadescription)
  inputdescription = datadescription.GetInputDescriptionByName("input")
  if inputdescription.GetIfGridIsNecessary() == False:
    return
  import paraview.simple
  extents = grid.GetWholeExtent()
  inputdescription.SetWholeExtent(extents)
  inputdescription.SetGrid(grid)
  cpscript.DoCoProcessing(datadescription)
def createGrid(time):
  """
  Create a vtkImageData and a point data field called 'pointData'.
  time is used to make the field time varying. The grid is
  partitioned in slices in the x-direction here but that is
  not required.
  """
  imageData = vtk.vtkImageData()
  imageData.Initialize()
  imageData.SetOrigin(0, 0, 0)
  imageData.SetSpacing(.1, .1, .1)
  imageData.SetWholeExtent(0, 2*mpi.size, 0, 5, 0, 5)
  imageData.SetExtent(mpi.rank*2, (mpi.rank+1)*2, 0, 5, 0, 5)
  pointArray = vtk.vtkDoubleArray()
  pointArray.SetNumberOfTuples(imageData.GetNumberOfPoints())
  for i in range(imageData.GetNumberOfPoints()):
    pointArray.SetValue(i, i+time)
  pointArray.SetName("pointData")
  imageData.GetPointData().AddArray(pointArray)
  return imageData
try:
  numsteps = int(sys.argv[2])
except ValueError:
  print 'the last argument should be a number, setting the number of time steps to 10'
  numsteps = 10
for step in range(numsteps):
  # assume simulation time starts at 0
  time = step/float(numsteps)
  # create the input to the coprocessing library.  normally
  # this will come from the adaptor
  grid = createGrid(time)
  # "perform" coprocessing.  results are outputted only if
  # the passed in script says we should at time/step
  coProcess(grid, time, step, sys.argv[1])
globalController.SetGlobalController(None)
globalController = None
mpi.finalized()
mpi.finalized()
</source>
</source>


== Sample coprocessing script ==
== Sample coprocessing script ==
Line 81: Line 163:
try: paraview.simple
try: paraview.simple
except: from paraview.simple import *
except: from paraview.simple import *
cp_writers = []


def RequestDataDescription(datadescription):
def RequestDataDescription(datadescription):
Line 96: Line 177:
def DoCoProcessing(datadescription):
def DoCoProcessing(datadescription):
     "Callback to do co-processing for current timestep"
     "Callback to do co-processing for current timestep"
    global cp_writers
     cp_writers = []
     cp_writers = []
     timestep = datadescription.GetTimeStep()
     timestep = datadescription.GetTimeStep()


     Sphere1 = CreateProducer( datadescription, "input" )
     grid = CreateProducer( datadescription, "input" )
     ImageWriter1 = CreateWriter( XMLPImageDataWriter, "input_grid_%t.pvti", 1 )
     ImageWriter1 = CreateWriter( XMLPImageDataWriter, "input_grid_%t.pvti", 1, cp_writers )


     for writer in cp_writers:
     for writer in cp_writers:
Line 109: Line 189:


     # explicitly delete the proxies -- we do it this way to avoid problems with prototypes
     # explicitly delete the proxies -- we do it this way to avoid problems with prototypes
     tobedeleted = GetProxiesToDelete()
     tobedeleted = GetNextProxyToDelete()
     while len(tobedeleted) > 0:
     while tobedeleted != None:
         Delete(tobedeleted[0])
         Delete(tobedeleted)
         tobedeleted = GetProxiesToDelete()
         tobedeleted = GetNextProxyToDelete()
 
def GetProxiesToDelete():
    iter = servermanager.vtkSMProxyIterator()
    iter.Begin()
    tobedeleted = []
    while not iter.IsAtEnd():
      if iter.GetGroup().find("prototypes") != -1:
        iter.Next()
        continue
      proxy = servermanager._getPyProxy(iter.GetProxy())
      proxygroup = iter.GetGroup()
      iter.Next()
      if proxygroup != 'timekeeper' and proxy != None and proxygroup.find("pq_helper_proxies") == -1 :
          tobedeleted.append(proxy)


     return tobedeleted
def GetNextProxyToDelete():
    proxyiterator = servermanager.ProxyIterator()
    for proxy in proxyiterator:
        group = proxyiterator.GetGroup()
        if group.find("prototypes") != -1:
            continue
        if group != 'timekeeper' and group.find("pq_helper_proxies") == -1 :
            return proxy
     return None


def CreateProducer(datadescription, gridname):
def CreateProducer(datadescription, gridname):
  "Creates a producer proxy for the grid"
    "Creates a producer proxy for the grid"
  if not datadescription.GetInputDescriptionByName(gridname):
    if not datadescription.GetInputDescriptionByName(gridname):
    raise RuntimeError, "Simulation input name '%s' does not exist" % gridname
        raise RuntimeError, "Simulation input name '%s' does not exist" % gridname
  grid = datadescription.GetInputDescriptionByName(gridname).GetGrid()
    grid = datadescription.GetInputDescriptionByName(gridname).GetGrid()
  producer = TrivialProducer()
    producer = PVTrivialProducer()
  producer.GetClientSideObject().SetOutput(grid)
    producer.GetClientSideObject().SetOutput(grid)
  producer.UpdatePipeline()
    if grid.IsA("vtkImageData") == True or grid.IsA("vtkStructuredGrid") == True or grid.IsA("vtkRectilinearGrid") == True:
  return producer
        extent = datadescription.GetInputDescriptionByName(gridname).GetWholeExtent()
        producer.WholeExtent= [ extent[0], extent[1], extent[2], extent[3], extent[4], extent[5] ]
    producer.UpdatePipeline()
    return producer


def CreateWriter(proxy_ctor, filename, freq):
def CreateWriter(proxy_ctor, filename, freq, cp_writers):
    global cp_writers
     writer = proxy_ctor()
     writer = proxy_ctor()
     writer.FileName = filename
     writer.FileName = filename

Latest revision as of 19:33, 10 February 2012

This example is used to demonstrate how the co-processing library can be used with a python based simulation code. Note that this example requires MPI to be available on your system as well as pyMPI to initialize and finalize MPI from the python script. The executable takes in a python co-processing script and a number of time steps to be run for. Note to remember to set your system environment properly. See [[1]] for details.

Serial python driver code

<source lang="python"> import sys if len(sys.argv) != 3:

   print "command is 'python <python driver code> <script name> <number of time steps>'"
   sys.exit(1)

import paraview import paraview.vtk as vtk

def coProcess(grid, time, step, scriptname):

   import vtkCoProcessorPython # import libvtkCoProcessorPython for older PV versions
   if scriptname.endswith(".py"):
       scriptname = scriptname[0:len(scriptname)-3]#scriptname.rstrip(".py")
   try:
       cpscript = __import__(scriptname)
   except:
       print 'Cannot find ', scriptname, ' -- no coprocessing will be performed.'
       return
   datadescription = vtkCoProcessorPython.vtkCPDataDescription()
   datadescription.SetTimeData(time, step)
   datadescription.AddInput("input")
   cpscript.RequestDataDescription(datadescription)
   inputdescription = datadescription.GetInputDescriptionByName("input")
   if inputdescription.GetIfGridIsNecessary() == False:
       return
   inputdescription.SetGrid(grid)
   inputdescription.SetWholeExtent(grid.GetWholeExtent())
   cpscript.DoCoProcessing(datadescription)

try:

   numsteps = int(sys.argv[2])

except ValueError:

   print 'the last argument should be a number, setting the number of time steps to 10'
   numsteps = 10

for step in range(numsteps):

   # assume simulation time starts at 0
   time = step/float(numsteps)
   # create the input to the coprocessing library.  normally
   # this will come from the adaptor
   imageData = vtk.vtkImageData()
   imageData.SetOrigin(0, 0, 0)
   imageData.SetSpacing(.1, .1, .1)
   imageData.SetExtent(0, 10, 0, 12, 0, 12)
   imageData.SetWholeExtent(imageData.GetExtent())
   pointArray = vtk.vtkDoubleArray()
   pointArray.SetNumberOfTuples(imageData.GetNumberOfPoints())
   for i in range(imageData.GetNumberOfPoints()):
       pointArray.SetValue(i, i)
   pointArray.SetName("pointData")
   imageData.GetPointData().AddArray(pointArray)
   # "perform" coprocessing.  results are outputted only if
   # the passed in script says we should at time/step
   coProcess(imageData, time, step, sys.argv[1])

</source>

Parallel python driver code

<source lang="python"> import sys if len(sys.argv) != 3:

 print "command is 'mpirun -np <#> pyMPI parallelexample.py <script name> <number of time steps>'"
 sys.exit(1)

import paraview import paraview.vtk as vtk

import mpi mpi.initialized()

import paraview import libvtkParallelPython import paraview.simple import vtk

  1. set up ParaView to properly use MPI

pm = paraview.servermanager.vtkProcessModule.GetProcessModule() globalController = pm.GetGlobalController() if globalController == None or globalController.IsA("vtkDummyController") == True:

 globalController = vtk.vtkMPIController()
 globalController.Initialize()
 globalController.SetGlobalController(globalController)

def coProcess(grid, simtime, simstep, scriptname):

 # the name of the library was changed so for previous version of ParaView
 # you have to import libvtkCoProcessorPython instead of vtkCoProcessorPython
 #import libvtkCoProcessorPython as vtkCoProcessorPython
 import vtkCoProcessorPython
 if scriptname.endswith(".py"):
   scriptname = scriptname[0:len(scriptname)-3]#scriptname.rstrip(".py")
 try:
   cpscript = __import__(scriptname)
 except:
   print 'Cannot find ', scriptname, ' -- no coprocessing will be performed.'
   return
 datadescription = vtkCoProcessorPython.vtkCPDataDescription()
 datadescription.SetTimeData(simtime, simstep)
 datadescription.AddInput("input")
 cpscript.RequestDataDescription(datadescription)
 inputdescription = datadescription.GetInputDescriptionByName("input")
 if inputdescription.GetIfGridIsNecessary() == False:
   return
 import paraview.simple
 extents = grid.GetWholeExtent()
 inputdescription.SetWholeExtent(extents)
 inputdescription.SetGrid(grid)
 cpscript.DoCoProcessing(datadescription)

def createGrid(time):

 """
 Create a vtkImageData and a point data field called 'pointData'.
 time is used to make the field time varying. The grid is
 partitioned in slices in the x-direction here but that is
 not required.
 """
 imageData = vtk.vtkImageData()
 imageData.Initialize()
 imageData.SetOrigin(0, 0, 0)
 imageData.SetSpacing(.1, .1, .1)
 imageData.SetWholeExtent(0, 2*mpi.size, 0, 5, 0, 5)
 imageData.SetExtent(mpi.rank*2, (mpi.rank+1)*2, 0, 5, 0, 5)
 pointArray = vtk.vtkDoubleArray()
 pointArray.SetNumberOfTuples(imageData.GetNumberOfPoints())
 for i in range(imageData.GetNumberOfPoints()):
   pointArray.SetValue(i, i+time)
 pointArray.SetName("pointData")
 imageData.GetPointData().AddArray(pointArray)
 return imageData

try:

 numsteps = int(sys.argv[2])

except ValueError:

 print 'the last argument should be a number, setting the number of time steps to 10'
 numsteps = 10

for step in range(numsteps):

 # assume simulation time starts at 0
 time = step/float(numsteps)
 # create the input to the coprocessing library.  normally
 # this will come from the adaptor
 grid = createGrid(time)
 # "perform" coprocessing.  results are outputted only if
 # the passed in script says we should at time/step
 coProcess(grid, time, step, sys.argv[1])


globalController.SetGlobalController(None) globalController = None mpi.finalized() </source>

Sample coprocessing script

<source lang="python"> try: paraview.simple except: from paraview.simple import *

def RequestDataDescription(datadescription):

   "Callback to populate the request for current timestep"
   timestep = datadescription.GetTimeStep()
   input_name = 'input'
   if (timestep % 1 == 0) :
       datadescription.GetInputDescriptionByName(input_name).AllFieldsOn()
       datadescription.GetInputDescriptionByName(input_name).GenerateMeshOn()
   else:
       datadescription.GetInputDescriptionByName(input_name).AllFieldsOff()
       datadescription.GetInputDescriptionByName(input_name).GenerateMeshOff()

def DoCoProcessing(datadescription):

   "Callback to do co-processing for current timestep"
   cp_writers = []
   timestep = datadescription.GetTimeStep()
   grid = CreateProducer( datadescription, "input" )
   ImageWriter1 = CreateWriter( XMLPImageDataWriter, "input_grid_%t.pvti", 1, cp_writers )
   for writer in cp_writers:
       if timestep % writer.cpFrequency == 0:
           writer.FileName = writer.cpFileName.replace("%t", str(timestep))
           writer.UpdatePipeline()
   # explicitly delete the proxies -- we do it this way to avoid problems with prototypes
   tobedeleted = GetNextProxyToDelete()
   while tobedeleted != None:
       Delete(tobedeleted)
       tobedeleted = GetNextProxyToDelete()

def GetNextProxyToDelete():

   proxyiterator = servermanager.ProxyIterator()
   for proxy in proxyiterator:
       group = proxyiterator.GetGroup()
       if group.find("prototypes") != -1:
           continue
       if group != 'timekeeper' and group.find("pq_helper_proxies") == -1 :
           return proxy
   return None

def CreateProducer(datadescription, gridname):

   "Creates a producer proxy for the grid"
   if not datadescription.GetInputDescriptionByName(gridname):
       raise RuntimeError, "Simulation input name '%s' does not exist" % gridname
   grid = datadescription.GetInputDescriptionByName(gridname).GetGrid()
   producer = PVTrivialProducer()
   producer.GetClientSideObject().SetOutput(grid)
   if grid.IsA("vtkImageData") == True or grid.IsA("vtkStructuredGrid") == True or grid.IsA("vtkRectilinearGrid") == True:
       extent = datadescription.GetInputDescriptionByName(gridname).GetWholeExtent()
       producer.WholeExtent= [ extent[0], extent[1], extent[2], extent[3], extent[4], extent[5] ]
   producer.UpdatePipeline()
   return producer

def CreateWriter(proxy_ctor, filename, freq, cp_writers):

   writer = proxy_ctor()
   writer.FileName = filename
   writer.add_attribute("cpFrequency", freq)
   writer.add_attribute("cpFileName", filename)
   cp_writers.append(writer)
   return writer

</source>