Advertisement
Guest User

vtkread.py

a guest
Oct 10th, 2012
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.18 KB | None | 0 0
  1. from xml.etree.ElementTree import ElementTree
  2. import numpy as np
  3. import os
  4. import vtk
  5. import array_handler
  6.  
  7. from dolfin import Mesh, MeshEditor, VectorFunctionSpace, FunctionSpace, Function
  8.  
  9. def vtk_ug_to_dolfin_mesh(ug):
  10.     """
  11.    Create a DOLFIN Mesh from a vtkUnstructuredGrid object
  12.    """
  13.     if not isinstance(ug, vtk.vtkUnstructuredGrid):
  14.         raise TypeError("Expected a 'vtkUnstructuredGrid'")
  15.    
  16.     # Get mesh data
  17.     num_cells = int(ug.GetNumberOfCells())
  18.     num_vertices = int(ug.GetNumberOfPoints())
  19.    
  20.     # Get topological and geometrical dimensions
  21.     cell = ug.GetCell(0)
  22.     gdim = int(cell.GetCellDimension())
  23.     cell_type = cell.GetCellType()                                                                                                                                          
  24.     if cell_type not in [vtk.VTK_TETRA, vtk.VTK_TRIANGLE]:                                                                                                                  
  25.         raise TypeError("DOLFIN only support meshes of triangles "\                                                                                                        
  26.                         "and tetrahedrons.")
  27.    
  28.     tdim = 3 if cell_type == vtk.VTK_TETRA else 2
  29.    
  30.     # Create empty DOLFIN Mesh
  31.     mesh = Mesh()
  32.     editor = MeshEditor()
  33.     editor.open(mesh, tdim, gdim)
  34.     editor.init_cells(num_cells)
  35.     editor.init_vertices(num_vertices)
  36.     editor.close()
  37.    
  38.     # Assign the cell and vertex informations directly from the vtk data
  39.     cells_array = array_handler.vtk2array(ug.GetCells().GetData())
  40.    
  41.     # Get the assumed fixed size of indices and create an index array
  42.     cell_size = cell.GetPointIds().GetNumberOfIds()
  43.     cellinds = np.arange(len(cells_array))
  44.    
  45.     # Each cell_ids_size:th data point need to be deleted from the
  46.     # index array
  47.     ind_delete = slice(0, len(cells_array), cell_size+1)
  48.    
  49.     # Check that the removed value all have the same value which should
  50.     # be the size of the data
  51.     if not np.all(cells_array[ind_delete]==cell_size):
  52.         raise ValueError("Expected all cells to be of the same size")
  53.    
  54.     cellinds = np.delete(cellinds, ind_delete)
  55.    
  56.     # Get cell data from mesh and make it writeable (cell data is non
  57.     # writeable by default) and update the values
  58.     mesh_cells = mesh.cells()
  59.     mesh_cells.flags.writeable = True
  60.     mesh_cells[:] = np.reshape(cells_array[cellinds], \
  61.                               (num_cells , cell_size))
  62.    
  63.     # Set coordinates from vtk data
  64.     vertex_array = array_handler.vtk2array(ug.GetPoints().GetData())
  65.     if vertex_array.shape[1] != gdim:
  66.         vertex_array = vertex_array[:,:gdim]
  67.     mesh.coordinates()[:] = vertex_array
  68.     return mesh
  69.    
  70.  
  71.  
  72. class VTKToDOLFIN(object):
  73.     """
  74.    A wrapper around vtk to simplify handling of VTK files
  75.    generated from DOLFIN.
  76.  
  77.    The class handles reading of data into DOLFIN objects for further processing
  78.    
  79.    """
  80.     def __init__(self, filename, mesh=None, deepcopy=False):
  81.         """
  82.        Initialize a the reader with a pvd or a vtu filename
  83.        """
  84.         if not os.path.isfile(filename):
  85.             raise IOError("File '%s' does not excist"%filename)
  86.         filetype = filename.split(".")[-1]
  87.         self._name = ".".join(filename.split(".")[0:-1])
  88.         if filetype not in ["pvd", "vtu"]:
  89.             raise TypeError("Expected a 'pvd' or a 'vtu' file")
  90.  
  91.         # Get dirname
  92.         dirname = os.path.dirname(filename)
  93.        
  94.         # Check mesh argument
  95.         if mesh is not None and not isinstance(mesh, Mesh):
  96.             raise TypeError, "Expected a 'Mesh' for the mesh arguments"
  97.  
  98.         # Store deepcopy argument
  99.         self._deepcopy = deepcopy
  100.        
  101.         # Store mesh
  102.         self._mesh = mesh
  103.        
  104.         # Initialize the filename cache
  105.         self._filenames = []
  106.         if filetype == "vtu":
  107.             self._filenames.append(filename)
  108.             self._times = np.array([], "")
  109.         else:
  110.             # Parse pvd file
  111.             tree = ElementTree(file=filename)
  112.             times = []
  113.             for item in tree.iter():
  114.                 if item.tag == "DataSet":
  115.                     self._filenames.append(os.path.join(\
  116.                         dirname,item.attrib["file"]))
  117.                     times.append(float(item.attrib["timestep"]))
  118.            
  119.             times = np.array(times, dtype='d')
  120.  
  121.             # If there are no time data stored in the file use an empty array
  122.             if np.all(np.diff(times)==1):
  123.                 times = np.array([], "")
  124.  
  125.             # Store time data
  126.             self._times = times
  127.  
  128.         # Construct file reader
  129.         self.reader = vtk.vtkXMLUnstructuredGridReader()
  130.        
  131.         # Read in data from file
  132.         self._update_vtk_data()
  133.  
  134.         # Init dolfin structures (Function, FunctionSpace)
  135.         self._init_dolfin_data()
  136.  
  137.     def _update_vtk_data(self, index=0):
  138.         "Set a new data file"
  139.  
  140.         # Update file name
  141.         print "Reading '%s'"%self._filenames[index]
  142.         self.reader.SetFileName(self._filenames[index])
  143.        
  144.         # Read data
  145.         self.reader.Update()
  146.        
  147.         # Set data type (scalar or vector)
  148.         # FIXME: Include Tensors when that is supported by DOLFIN
  149.         self.scalar = self.reader.GetOutput().GetPointData().GetScalars() is not None
  150.  
  151.         print "Scalar data set" if self.scalar else "Vector data set"
  152.        
  153.     def _init_dolfin_data(self):
  154.         "Update DOLFIN function from vtk data"
  155.        
  156.         if self.reader.GetNumberOfPointArrays() != 1:
  157.             raise ValueError("Expected the vtk file to include one data "\
  158.                              "set per vertex.")
  159.  
  160.         # Initilize FunctionSpace and Function if not initialized
  161.         if self.scalar:
  162.             self._V = FunctionSpace(self.mesh(), "CG", 1)
  163.         else:
  164.             self._V = VectorFunctionSpace(self.mesh(), "CG", 1)
  165.        
  166.         self._u = Function(self._V)
  167.        
  168.     def _update_dolfin_data(self):
  169.         "Update dolfin data from present VTK file"
  170.        
  171.         # Get VTK point data
  172.         point_data = self.reader.GetOutput().GetPointData()
  173.  
  174.         # Get data and update Function
  175.         if self.scalar:
  176.             self._u.vector()[:] = array_handler.vtk2array(point_data.GetScalars())
  177.         else:
  178.             values = array_handler.vtk2array(point_data.GetVectors()).transpose()
  179.             self._u.vector()[:] = np.reshape(values, (np.prod(values.shape),))
  180.    
  181.     def functions_space(self):
  182.         "Return the FunctionSpace"
  183.         return self._V
  184.    
  185.     def mesh(self):
  186.         "Return the dolfin mesh"
  187.  
  188.         # If no mesh is stored read in from UnstructuredGridData
  189.         if self._mesh is None:
  190.             self._mesh = vtk_ug_to_dolfin_mesh(self.reader.GetOutput())
  191.  
  192.         # Small sanity check
  193.         assert(self._mesh.num_vertices() == \
  194.                self.reader.GetOutput().GetNumberOfPoints() and \
  195.                self._mesh.num_cells() == \
  196.                self.reader.GetOutput().GetNumberOfCells())
  197.        
  198.         return self._mesh
  199.    
  200.     def name(self):
  201.         "Return the name"
  202.         return self._name
  203.  
  204.     def __getitem__(self, index):
  205.         "x.__getitem__(y) <==> x[y]"
  206.         # Update data structures to next index if not out of files
  207.         if not isinstance(index, int):
  208.             raise TypeError("Expected an int for the index argument")
  209.         if index < 0 or index >= len(self):
  210.             raise IndexError("index need to be smaller than ")
  211.  
  212.         # Update the stored data
  213.         self._update_vtk_data(index)
  214.         self._update_dolfin_data()
  215.  
  216.         # Should we return a copy of the stored data?
  217.         u = self._u.copy() if self._deepcopy else self._u
  218.  
  219.         # If time is registered return with this information
  220.         if len(self._times):
  221.             return self._times[index], u
  222.        
  223.         return u
  224.  
  225.     def __len__(self):
  226.         "x.__len__() <==> len(x)"
  227.         return len(self._filenames)
  228.  
  229.     def __iter__(self):
  230.         "x.__iter__() <==> iter(x)"
  231.         for i in xrange(len(self)):
  232.             yield self[i]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement