r""" This script is a miniapp that acts a Catalyst-instrumented simulation code. Instead of doing some computation, however, this script reads the files specified through command line arguments and provides the data read in as the simulation data. Example usage: mpirun -np 8 ./bin/pvbatch --sym -m paraview.demos.filedriver_miniapp \ -g "/tmp/extracts/Wavelet1_*.pvti" -s /tmp/foo.py """ import argparse, time, os.path, glob parser = argparse.ArgumentParser(\ description="File-based MiniApp for Catalyst testing") parser.add_argument("-s", "--script", type=str, action="append", help="path(s) to the Catalyst script(s) to use for in situ processing. Can be a " ".py file or a Python package zip or directory", required=True) parser.add_argument("--script-version", type=int, help="choose Catalyst analysis script version explicitly, otherwise it " "will be determined automatically. When specifying multiple scripts, this " "setting applies to all scripts.", default=0) parser.add_argument("-d", "--delay", type=float, help="delay (in seconds) between timesteps (default: 0.0)", default=0.0) parser.add_argument("-c", "--channel", type=str, help="Catalyst channel name (default: input)", default="input") parser.add_argument("-g", "--glob", type=str, help="Pattern to use to locate input filenames.", required=True) def create_reader(files): from paraview import simple reader = simple.OpenDataFile(files) if not reader: raise RuntimeError("Failed to create a suitable reader for files: %s", str(files)) return reader def read_dataset(reader, time, rank, num_ranks): reader.UpdatePipeline(time) vtk_reader = reader.GetClientSideObject() ds = vtk_reader.GetOutputDataObject(0) if ds.GetExtentType() == 1: # VTK_3D_EXTENT key = vtk_reader.GetExecutive().WHOLE_EXTENT() whole_extent = vtk_reader.GetOutputInformation(0).Get(key)[:] return (ds, whole_extent) else: return (ds, None) def main(args): """The main loop""" # this globbling logic is copied from `filedriver.py`. It may be worth # cleaning this up to ensure it handles typical use-cases we encounter. files = glob.glob(args.glob) # In case the filenames aren't padded we sort first by shorter length and then # alphabetically. This is a slight modification based on the question by Adrian and answer by # Jochen Ritzel at: # https://stackoverflow.com/questions/4659524/how-to-sort-by-length-of-string-followed-by-alphabetical-order files.sort(key=lambda item: (len(item), item)) # initialize Catalyst from paraview.catalyst import bridge from paraview import print_info, print_warning bridge.initialize() # add analysis script for script in args.script: bridge.add_pipeline(script, args.script_version) # Some MPI related stuff to figure out if we're running with MPI # and if so, on how many ranks. try: from mpi4py import MPI comm = MPI.COMM_WORLD rank = comm.Get_rank() num_ranks = comm.Get_size() except ImportError: print_warning("missing mpi4py, running in serial (non-distributed) mode") rank = 0 num_ranks = 1 reader = create_reader(files) timesteps = reader.TimestepValues[:] step = 0 numsteps = len(timesteps) for time in timesteps: if args.delay > 0: import time time.sleep(args.delay) if rank == 0: print_info("timestep: {0} of {1}".format((step+1), numsteps)) dataset, wholeExtent = read_dataset(reader, time, rank, num_ranks) # "perform" coprocessing. results are outputted only if # the passed in script says we should at time/step bridge.coprocess(time, step, dataset, name=args.channel, wholeExtent=wholeExtent) del dataset del wholeExtent step += 1 # finalize Catalyst bridge.finalize() if __name__ == "__main__": args = parser.parse_args() main(args)