UnstructuredGridの記述

UnstructuredGrid の例

xml形式のデータファイルは以下の通り.

<?xml version="1.0" encoding="utf-8"?>
<VTKFile type="UnstructuredGrid">
  <UnstructuredGrid>
    <Piece NumberOfPoints="220" NumberOfCells="669">
      <CellData Scalars="Data">
        <DataArray Name="Data" type="Float64" NumberOfComponents="1" format="ascii">
	  0.6512950608594982 0.5899054147718982 0.6058387758450685 ............. 0.38268901561438984
	</DataArray>
      </CellData>
      <Points>
        <DataArray Name="Nodes" type="Float64" NumberOfComponents="3" format="ascii">
	  0.0 0.0 0.0
	  1.0 0.0 0.0
	  1.0 1.0 0.0
	  ......
	  0.5177636955782718 0.6856875512666446 0.4224184248075115
	</DataArray>
      </Points>
      <Cells>
        <DataArray Name="connectivity" type="Int64" NumberOfComponents="1" format="ascii">
	  195 196 125 213
	  131 196 201 213
	  131 125 196 213
	  ......
	  215 118 29 190
	</DataArray>
        <DataArray Name="offsets" type="Int64" NumberOfComponents="1" format="ascii">
	  4 8 12 ....... 2676 
	</DataArray>
        <DataArray Name="types" type="Int64" NumberOfComponents="1" format="ascii">
	  10 10 10 ....... 10 
	</DataArray>
      </Cells>
    </Piece>
  </UnstructuredGrid>
</VTKFile>
../_images/screenshot_unstruc_ParaView_sample.png

UnstructuredGrid 出力用クラス

  • 以下の引数をとる.

    • Data= [nElem]

    • Elem= [nElem,nVerts]

    • Node= [nNode,3]

    • VectorData= True or False

    • vtkFile= FileName

import sys, subprocess
import numpy as np


# ========================================================= #
# ===  vtk_makeUnstructuredGrid class                   === #
# ========================================================= #
class vtk_makeUnstructuredGrid():
    # ------------------------------------------------- #
    # --- class Initiator                           --- #
    # ------------------------------------------------- #
    def __init__( self, vtkFile=None, Data=None, Node=None, Elem=None, \
                  xAxis=None, yAxis=None, zAxis=None, VectorData=False, DataFormat="ascii" ):
        # --- [1-1] Arguments                       --- #
        if ( vtkFile is None ): vtkFile = "out.vtu"
        # --- [1-2] Variables Settings              --- #
        self.vtkFile     = vtkFile
        self.vtkContents = ''
        self.vtkEndTags  = ''
        self.Data        = Data
        self.Node        = Node
        self.Elem        = Elem
        self.DataFormat  = DataFormat
        self.VectorData  = VectorData
        self.DataDims    = None
        self.LILJLK      = None
        # --- [1-3] Routines                        --- #
        self.vtk_add_VTKFileTag  ( datatype="UnstructuredGrid" )
        self.vtk_add_UnstructuredGridTag( Data=self.Data, Node=self.Node, Elem=self.Elem, VectorData=self.VectorData )
        self.vtk_writeFile()
        
    # ------------------------------------------------- #
    # --- vtk_add_VTKFileTag                        --- #
    # ------------------------------------------------- #
    def vtk_add_VTKFileTag( self, datatype=None ):
        # ------------------------------------------------- #
        # --- [1] Add XML Definition & VTKFile Tag      --- #
        # ------------------------------------------------- #
        if ( datatype is None ): datatype = "UnstructuredGrid"
        self.vtkContents  += '<?xml version="1.0"?>\n'
        self.vtkContents  += '<VTKFile type="{0}">\n'.format( datatype )
        self.vtkEndTags    = '</VTKFile>'     + '\n' + self.vtkEndTags
        
    # ------------------------------------------------- #
    # --- vtk_add_UnstructuredGridTag               --- #
    # ------------------------------------------------- #
    def vtk_add_UnstructuredGridTag( self, Data=None , Node    =None, Elem=None, DataName=None, \
                                     VectorData=False, DataDims=None, WholeExtent=None, \
                                     PointData =False, CellData=True ):
        # ------------------------------------------------- #
        # --- [1] Arguments                             --- #
        # ------------------------------------------------- #
        if ( DataName is None ): DataName = "Data"
        self.prepareData( Data=Data, VectorData=VectorData )
        if ( Data     is None ): return()
        if ( Elem     is None ): return()
        if ( Node     is None ): return()
        if   ( VectorData is True  ):
            Scl_or_Vec   = "Vectors"
        elif ( VectorData is False ):
            Scl_or_Vec   = "Scalars"
        nNodes = Node.shape[0]
        nElems = Elem.shape[0]
        # ------------------------------------------------- #
        # --- [2] UnstructuredGrid & Piece Tag  Begin   --- #
        # ------------------------------------------------- #
        self.vtkContents  += '<UnstructuredGrid>\n'
        self.vtkContents  += '<Piece  NumberOfPoints="{0}" NumberOfCells="{1}">\n'.format( nNodes, nElems )
        # ------------------------------------------------- #
        # --- [3] PointData / CellData / Coordinates    --- #
        # ------------------------------------------------- #
        if   ( PointData is True ):
            self.vtkContents  += '<PointData {0}="{1}">\n'.format( Scl_or_Vec, DataName )
            self.vtkContents  += self.vtk_add_DataArray( Data=Data, DataName=DataName )
            self.vtkContents  += '</PointData>\n'
        elif ( CellData  is True ):
            self.vtkContents  += '<CellData {0}="{1}">\n' .format( Scl_or_Vec, DataName  )
            self.vtkContents  += self.vtk_add_DataArray( Data=Data, DataName=DataName )
            self.vtkContents  += '</CellData>\n'
        self.vtkContents  += '<Points>\n'
        self.vtkContents  += self.vtk_add_DataArray( Data=Node, DataName="Nodes", VectorData=True )
        self.vtkContents  += '</Points>\n'
        self.vtkContents  += self.vtk_add_Cells( Elem=Elem )
        # ------------------------------------------------- #
        # --- [4] Close UnstructuredGrid & Piece Tag    --- #
        # ------------------------------------------------- #
        self.vtkContents  += '</Piece>\n'         
        self.vtkContents  += '</UnstructuredGrid>\n'


    # ========================================================= #
    # ===  vtk_add_Cells                                    === #
    # ========================================================= #
    def vtk_add_Cells( self, Elem=None, ElementType=None ):
        if ( Elem is None ): sys.exit( "[vtk_add_Cell] Elem == ???" )
        ret    = ""
        nElems = Elem.shape[0]
        nVerts = Elem.shape[1]
        if ( ElementType is None ):
            if ( nVerts == 1 ): ElementType = "vertex"
            if ( nVerts == 2 ): ElementType = "line"
            if ( nVerts == 3 ): ElementType = "triangle"
            if ( nVerts == 4 ): ElementType = "tetra"
            if ( nVerts == 5 ): ElementType = "pyramid"
            if ( nVerts == 6 ): ElementType = "hexahedron"
        ElementTypeTable = { "vertex":1, "poly_vertex":2, "line":3, "poly_line":4, "triangle":5, \
                             "polygon":7, "pixel":8, "quad":9, "tetra":10, "voxel":11, "hexahedron":12, \
                             "hexa":12, "pyramid":14 }
        types   = np.ones( (nElems,), dtype=np.int64 ) * ElementTypeTable[ElementType]
        offsets = ( np.arange( nElems, dtype=np.int64 ) + 1 ) * nVerts
        connect = np.array( Elem, dtype=np.int64 )
        ret   += "<Cells>\n"
        ret   += self.vtk_add_DataArray( Data=connect , DataName="connectivity", VectorData=True, nComponents=1 )
        ret   += self.vtk_add_DataArray( Data=offsets , DataName="offsets"      )
        ret   += self.vtk_add_DataArray( Data=types   , DataName="types"        )
        ret   += "</Cells>\n"
        return( ret )

    
    # ------------------------------------------------- #
    # --- vtk_add_DataArray                         --- #
    # ------------------------------------------------- #
    def vtk_add_DataArray( self, Data=None, DataName=None, DataFormat=None, DataType=None, nComponents=None, nData=None, VectorData=False ):
        if ( Data        is None ): sys.exit( "[vtk_add_DataArray -@makeUnstructuredGrid-] Data     == ??? " )
        if ( DataName    is None ): sys.exit( "[vtk_add_DataArray -@makeUnstructuredGrid-] DataName == ??? " )
        if ( DataFormat  is None ): DataFormat  = self.DataFormat
        if ( DataType    is None ): DataType    = self.inquiryData( Data=Data, ret_DataType   =True, VectorData=VectorData )
        if ( nComponents is None ): nComponents = self.inquiryData( Data=Data, ret_nComponents=True, VectorData=VectorData )
        if ( nData       is None ): nData       = self.inquiryData( Data=Data, ret_nData      =True, VectorData=VectorData )
        ret  = ""
        ret += '<DataArray Name="{0}" type="{1}" NumberOfComponents="{2}" format="{3}">\n'\
                                 .format( DataName, DataType, nComponents, DataFormat )
        lines = ""
        if ( VectorData ):
            for line in Data:
                lines += ( " ".join( [ str( val ) for val in line ] ) + "\n" )
        else:
            for line in np.ravel( Data ):
                lines += "{0} ".format( line )
            lines += "\n"
        ret += lines
        ret += '</DataArray>\n'
        return( ret )
    
    
    # ------------------------------------------------- #
    # --- vtk_writeFile                             --- #
    # ------------------------------------------------- #
    def vtk_writeFile( self, vtkFile=None ):
        if ( vtkFile is None ): vtkFile = self.vtkFile
        with open( vtkFile, "w" ) as f:
            f.write( self.vtkContents )
            f.write( self.vtkEndTags  )
        subprocess.call( ( "xmllint --format --encode utf-8 {0} -o {0}"\
                           .format( vtkFile ) ).split() )
        print( "[vtk_writeFile-@makeUnstructuredGrid-] VTK File output :: {0}".format( vtkFile ) )


    # ------------------------------------------------- #
    # --- inquiryData                               --- #
    # ------------------------------------------------- #
    def inquiryData( self, Data=None, VectorData=False, ret_DataType=False, ret_nComponents=False, ret_nData=False ):
        if ( Data is None ): sys.exit( "[inquiryData-@vtk_makeUnstructuredGrid-] Data  == ??? " )
        # ------------------------------------------------- #
        # --- [1] DataType Check                        --- #
        # ------------------------------------------------- #
        if ( type(Data) is not np.ndarray ):
            sys.exit( "[inquiryData-@vtk_makeUnstructuredGrid-] Data should be np.ndarray [ERROR]" )
        if ( Data.dtype == np.int32   ): DataType = "Int32"
        if ( Data.dtype == np.int64   ): DataType = "Int64"
        if ( Data.dtype == np.float32 ): DataType = "Float32"
        if ( Data.dtype == np.float64 ): DataType = "Float64"
        # ------------------------------------------------- #
        # --- [2] Data Shape Check                      --- #
        # ------------------------------------------------- #
        if ( VectorData is True ):
            nComponents = Data.shape[-1]
            nData       = np.size( Data[-1][:] )
        else:
            nComponents = 1
            nData       = np.size( Data[:]    )
        # ------------------------------------------------- #
        # --- [3] Return                                --- #
        # ------------------------------------------------- #
        if ( ret_DataType    ): return( DataType    )
        if ( ret_nComponents ): return( nComponents )
        if ( ret_nData       ): return( nData       )
        return( { "DataType":DataType, "nComponents":nComponents, "nData":nData } )

        
    # ------------------------------------------------- #
    # --- prepareData                               --- #
    # ------------------------------------------------- #
    def prepareData( self, Data=None, VectorData=False ):
        # ------------------------------------------------- #
        # --- [1] Data Array Type/Shape Check           --- #
        # ------------------------------------------------- #
        if ( Data is None   ): return()
        if ( type(Data) is not np.ndarray ):
            sys.exit( "[prepareData-@vtk_makeUnstructuredGrid-] Data should be np.ndarray [ERROR]" )
        if ( Data.ndim >= 5 ):
            sys.exit( "[prepareData-@vtk_makeUnstructuredGrid-] incorrect Data size ( ndim >= 5 ) [ERROR]" )
        # ------------------------------------------------- #
        # --- [2] DataDims & LILJLK Check               --- #
        # ------------------------------------------------- #
        if ( VectorData is True ):
            self.DataDims   = Data.shape[-1]
            self.LILJLK     = Data.shape[:-1]
        else:
            self.DataDims   = 1
            self.LILJLK     = Data.shape[:]
        # ------------------------------------------------- #
        # --- [3] for 2D Data                           --- #
        # ------------------------------------------------- #
        if ( len( self.LILJLK ) == 2 ):
            self.LILJLK = self.LILJLK + (1,)
            Data        = Data.reshape( self.LILJLK )
        if ( len( self.LILJLK ) == 1 ):
            self.LILJLK = self.LILJLK + (1,1,)
            Data        = Data.reshape( self.LILJLK )


            
# ======================================== #
# ===  実行部                          === #
# ======================================== #
if ( __name__=="__main__" ):
    elemFile = "elems.dat"
    nodeFile = "nodes.dat"
    with open( elemFile, "r" ) as f:
        rElem = np.loadtxt( f )
        Elem  = np.array( rElem[:,1:], dtype=np.int64 )
    with open( nodeFile, "r" ) as f:
        Node  = np.loadtxt( f )
    Data    = np.zeros( (Elem.shape[0]) )
    for iE,el in enumerate( Elem ):
        Data[iE] = 0.25 * ( Node[el[0],2] + Node[el[1],2] + Node[el[2],2] + Node[el[3],2] )
    vtk     = vtk_makeUnstructuredGrid( Data=Data, Elem=Elem, Node=Node )