filedriver_miniapp.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. r"""
  2. This script is a miniapp that acts a Catalyst-instrumented simulation code.
  3. Instead of doing some computation, however, this script reads the files
  4. specified through command line arguments and provides the data read in as the
  5. simulation data.
  6. Example usage:
  7. mpirun -np 8 ./bin/pvbatch --sym -m paraview.demos.filedriver_miniapp \
  8. -g "/tmp/extracts/Wavelet1_*.pvti" -s /tmp/foo.py
  9. """
  10. import argparse, time, os.path, glob
  11. parser = argparse.ArgumentParser(\
  12. description="File-based MiniApp for Catalyst testing")
  13. parser.add_argument("-s", "--script", type=str, action="append",
  14. help="path(s) to the Catalyst script(s) to use for in situ processing. Can be a "
  15. ".py file or a Python package zip or directory",
  16. required=True)
  17. parser.add_argument("--script-version", type=int,
  18. help="choose Catalyst analysis script version explicitly, otherwise it "
  19. "will be determined automatically. When specifying multiple scripts, this "
  20. "setting applies to all scripts.", default=0)
  21. parser.add_argument("-d", "--delay", type=float,
  22. help="delay (in seconds) between timesteps (default: 0.0)", default=0.0)
  23. parser.add_argument("-c", "--channel", type=str,
  24. help="Catalyst channel name (default: input)", default="input")
  25. parser.add_argument("-g", "--glob", type=str,
  26. help="Pattern to use to locate input filenames.", required=True)
  27. def create_reader(files):
  28. from paraview import simple
  29. reader = simple.OpenDataFile(files)
  30. if not reader:
  31. raise RuntimeError("Failed to create a suitable reader for files: %s", str(files))
  32. return reader
  33. def read_dataset(reader, time, rank, num_ranks):
  34. reader.UpdatePipeline(time)
  35. vtk_reader = reader.GetClientSideObject()
  36. ds = vtk_reader.GetOutputDataObject(0)
  37. if ds.GetExtentType() == 1: # VTK_3D_EXTENT
  38. key = vtk_reader.GetExecutive().WHOLE_EXTENT()
  39. whole_extent = vtk_reader.GetOutputInformation(0).Get(key)[:]
  40. return (ds, whole_extent)
  41. else:
  42. return (ds, None)
  43. def main(args):
  44. """The main loop"""
  45. # this globbling logic is copied from `filedriver.py`. It may be worth
  46. # cleaning this up to ensure it handles typical use-cases we encounter.
  47. files = glob.glob(args.glob)
  48. # In case the filenames aren't padded we sort first by shorter length and then
  49. # alphabetically. This is a slight modification based on the question by Adrian and answer by
  50. # Jochen Ritzel at:
  51. # https://stackoverflow.com/questions/4659524/how-to-sort-by-length-of-string-followed-by-alphabetical-order
  52. files.sort(key=lambda item: (len(item), item))
  53. # initialize Catalyst
  54. from paraview.catalyst import bridge
  55. from paraview import print_info, print_warning
  56. bridge.initialize()
  57. # add analysis script
  58. for script in args.script:
  59. bridge.add_pipeline(script, args.script_version)
  60. # Some MPI related stuff to figure out if we're running with MPI
  61. # and if so, on how many ranks.
  62. try:
  63. from mpi4py import MPI
  64. comm = MPI.COMM_WORLD
  65. rank = comm.Get_rank()
  66. num_ranks = comm.Get_size()
  67. except ImportError:
  68. print_warning("missing mpi4py, running in serial (non-distributed) mode")
  69. rank = 0
  70. num_ranks = 1
  71. reader = create_reader(files)
  72. timesteps = reader.TimestepValues[:]
  73. step = 0
  74. numsteps = len(timesteps)
  75. for time in timesteps:
  76. if args.delay > 0:
  77. import time
  78. time.sleep(args.delay)
  79. if rank == 0:
  80. print_info("timestep: {0} of {1}".format((step+1), numsteps))
  81. dataset, wholeExtent = read_dataset(reader, time, rank, num_ranks)
  82. # "perform" coprocessing. results are outputted only if
  83. # the passed in script says we should at time/step
  84. bridge.coprocess(time, step, dataset, name=args.channel, wholeExtent=wholeExtent)
  85. del dataset
  86. del wholeExtent
  87. step += 1
  88. # finalize Catalyst
  89. bridge.finalize()
  90. if __name__ == "__main__":
  91. args = parser.parse_args()
  92. main(args)