Write Xdmf

From XdmfWeb
Jump to navigationJump to search

Writing Xdmf

Xdmf can be generated in many different manners. Using the low level HDF5 library and print statements is certainly one of them. Utilizing the XDMF API, however, provides some convenient advantages. Suppose we wanted to generate an XDMF dataset of a co-rectilinear mesh with scalar values at each node

from Xdmf import *

root = XdmfDomain.New()
# Information
info = XdmfInformation.New() # Arbitrary Name=Value Facility
info.SetName("SampleLocation")
info.SetValue("4")
root.insert(i) # XML Domain is used as the keeper of the structure
               # Insert() creates an XML node and inserts it under
               # the parent
# Origin X,Y,Z
newGridOrigin = XdmfArray.New()
newGridOrigin.pushBackAsFloat64(1.0)
newGridOrigin.pushBackAsFloat64(2.0)
newGridOrigin.pushBackAsFloat64(3.0)
# Offset X,Y,Z
newBrickSize = XdmfArray.New()
newBrickSize.pushBackAsFloat64(0.1)
newBrickSize.pushBackAsFloat64(0.2)
newBrickSize.pushBackAsFloat64(0.3)
# Points per Dimensio0n
newNumPoints = XdmfArray.New()
newNumPoints.pushBackAsUInt32(10)
newNumPoints.pushBackAsUInt32(20)
newNumPoints.pushBackAsUInt32(30)
# Grid
grid = XdmfRegularGrid.New(newBrickSize, newNumPoints, newGridOrigin)
# Topology and Geometry are set based on the provided arrays
grid.setName("Structured Grid")
# Attribute
attr = XdmfAttribute.New()
attr.setName("Pressure")
attr.setAttributeCenter(XdmfAttributeCenter.Node());
attr.setAttributeType(XdmfAttributeType.Scalar());
# The attribute has the same dims as the Grid
attr.initialize(XdmfArrayType.Float64(), newNumPoints)
# Fill with values however you prefer
# Simply using a loop to fill in this case
for i in range(0, 10 * 20 * 30)
  attr.insertAsFloat64(i, 5.0)
grid.insert(attr)
writer = XdmfWriter.New('SMesh.xmf') 
root.accept(writer)


Would result in the Light Data XML to be written to the file SMesh.xmf and the Heavy data to be written to SMesh.h5.

<?xml version="1.0" ?>
<!DOCTYPE Xdmf SYSTEM "Xdmf.dtd" []>
<Xdmf xmlns:xi="http://www.w3.org/2003/XInclude" Version="2.2">
 <Information Name="SampleLocation" Value="4"/>
 <Domain>
   <Grid Name="Structured Grid" GridType="Uniform">
     <Topology TopologyType="3DCORECTMesh" NumberOfElements="10 20 30 "/>
     <Geometry GeometryType="ORIGIN_DXDYDZ">
       <DataItem Dimensions="3 " NumberType="Float" Precision="4" Format="XML">
          1 2 3
       </DataItem>
       <DataItem Dimensions="3 " NumberType="Float" Precision="4" Format="XML">
        0.1 0.2 0.3
       </DataItem>
     </Geometry>
     <Attribute Name="Pressure" AttributeType="Scalar" Center="Cell">
       <DataItem Dimensions="6000 " NumberType="Float" Precision="4" Format="HDF">SMesh.xmf.h5:/Data</DataItem>
     </Attribute>
   </Grid>
 </Domain>
</Xdmf>

Now suppose the HDF5 already existed or we wanted to write the HDF5 files in a specific manner. All XdmfArrays can be provided a child HeavyDataController that points to a dataset in heavy data. When the XdmfWriter is set to DistributedHeavyData mode it will not read in the data and write it out to a new heavy data location.

#!/usr/bin/env python

from Xdmf import *

# Example of How to Generate Xdmf
# The Heavy Data for the Attribute is written separately

# Write H5 Data
array = XdmfArray.New()
dims = UInt32Vector()
dims.push_back(10)
dims.push_back(20)
dims.push_back(30)
array.initialize(XdmfArrayType.Float64(), dims)
# Simply using a loop to fill in this case
for i in range(0, 10 * 20 * 30)
  attr.insertAsFloat64(i, 5.0)
h5writer = XdmfHDF5Writer.New('XdmfByHand.h5')
array.accept(h5writer)
# Retrieve the data set that the writer wrote to
dataset = array.getHeavyDataController().getDataSetPath()

root = XdmfDomain.New()
root.SetDOM(d)
# Information
i = XdmfInformation.New() # Arbitrary Name=Value Facility
i.setName("SampleLocation")
i.setValue("4")
root.insert(i) # XML Domain is used as the keeper of the structure
               # Insert() creates an XML node and inserts it under
               # the parent
# Origin X,Y,Z
newGridOrigin = XdmfArray.New()
newGridOrigin.pushBackAsFloat64(1.0)
newGridOrigin.pushBackAsFloat64(2.0)
newGridOrigin.pushBackAsFloat64(3.0)
# Offset X,Y,Z
newBrickSize = XdmfArray.New()
newBrickSize.pushBackAsFloat64(0.1)
newBrickSize.pushBackAsFloat64(0.2)
newBrickSize.pushBackAsFloat64(0.3)
# Points per Dimensio0n
newNumPoints = XdmfArray.New()
newNumPoints.pushBackAsUInt32(10)
newNumPoints.pushBackAsUInt32(20)
newNumPoints.pushBackAsUInt32(30)
# Grid
grid = XdmfRegularGrid.New(newBrickSize, newNumPoints, newGridOrigin)
# Topology and Geometry are set based on the provided arrays
grid.setName("Structured Grid")
root.insert(g)
# Attribute
attr = XdmfAttribute.New()
attr.setName("Pressure")
attr.setAttributeCenter(XdmfAttributeCenter.Node())
attr.setAttributeType(XdmfAttributeType.Scalar())
# Build a heavy data controller
starts = UInt32Vector()
starts.push_back(0)
starts.push_back(0)
starts.push_back(0)
strides = UInt32Vector()
strides.push_back(1)
strides.push_back(1)
strides.push_back(1)
controller = XdmfHDF5Controller.New('SMesh.h5',
                                    dataset, # Stored from earlier
                                    XdmfArrayType.Float64(),
                                    starts,
                                    strides,
                                    dims,
                                    dims)
writer = XdmfWriter.New('secondSMesh.h5')
writer.setMode(XdmfWriter.DistributedHeavyData)
root.accept(writer)

This results in identical XML with just the name of the HDF5 dataset changed.