def setup_pipeline(self): """Override this method so that it *creates* the tvtk pipeline. This method is invoked when the object is initialized via `__init__`. Note that at the time this method is called, the tvtk data pipeline will *not* yet be setup. So upstream data will not be available. The idea is that you simply create the basic objects and setup those parts of the pipeline not dependent on upstream sources and filters. You should also set the `actors` attribute up at this point. """ # Create and setup the default objects. self.seed = SourceWidget() self.stream_tracer = tvtk.StreamTracer( maximum_propagation=50, integration_direction='forward', compute_vorticity=True, integrator_type='runge_kutta4', ) self.ribbon_filter = tvtk.RibbonFilter() self.tube_filter = tvtk.TubeFilter() self.clean_filter = tvtk.CleanPolyData() self.actor = Actor() # Setup the actor suitably for this module. self.actor.property.line_width = 2.0
def make_tracer(self): """create a data object to store particles""" grid = self.grid # This drops unlinked polygons # Clean the polydata # If you do this for quadtrees you'll lose half of the particles # The better way would be to setup an AMR, but that only # works from >vtk6 clean = tvtk.CleanPolyData() clean.input = grid # gives a topological sound grid clean.update() # We need to convert to point data for interpolation of velocities. # This assumes vectors are cell centered cell2pointgrid = tvtk.CellDataToPointData() cell2pointgrid.input = clean.output cell2pointgrid.update() # Create a stream tracer # We want to use the particle class that also can interpolate over time # But it is not working as expected so we'll use the streamtracer # This gives the same results if the velocity field is stationary # If the velocity field is not stationary you have to reduce # your timestep st = tvtk.StreamTracer() # We attach 2 data source # Set the points in the streamer st.source = self.particles # Set the corner velocities st.input = cell2pointgrid.output # You can compute up to 2km per timestep (8km/hr for ) l = 2000 # max propagation n = 200 # max number of steps st.maximum_propagation = l # In m st.integration_step_unit = 1 # Minimum 10m per step st.minimum_integration_step = (l / n) # Maximum 100m per step st.maximum_integration_step = 10 * (l / n) # Maximum 200 steps st.maximum_number_of_steps = n # Maximum error 1cm st.maximum_error = 1e-2 # We use a path integration. You could argue that you need a # particle tracking algorithm that matches the numerical grid # (in our case edge velocities # and integration over a cell instead of over a line) st.integrator_type = 'runge_kutta45' return st
def make_tracer_pipeline(polydata, seed, maximum_number_of_steps=200, maximum_propagation=1000): """Make a tracer pileine based on a polydata and seed. The polydata is a vtk object with point_data for the velocities. Seed is a polydata with point_data for the seed coordinates. Propagation can be tuned using the other parameters (in meters). """ # create elements of the pipeline tracer = tvtk.StreamTracer() # maximum 1km tracer.maximum_propagation = maximum_propagation # # # Maximum 200 steps tracer.maximum_number_of_steps = maximum_number_of_steps # # # In m tracer.integration_step_unit = vtk.vtkStreamTracer.LENGTH_UNIT # # # Minimum 5 m per step tracer.minimum_integration_step = (maximum_propagation / maximum_number_of_steps) # # # Maximum 50m per step tracer.maximum_integration_step = 10 * tracer.minimum_integration_step # # # Maximum error 1cm tracer.maximum_error = 1e-2 # # # We use a path integration. You could argue that you need a # # # particle tracking algorithm that matches the numerical grid # # # (in our case edge velocities # # # and integration over a cell instead of over a line) tracer.integrator_type = 'runge_kutta45' tracer.debug = True cell2point = tvtk.CellDataToPointData() # setup the pipeline configure_input(cell2point, polydata) configure_input(tracer, cell2point) configure_source_data(tracer, seed) return tracer