Write Xdmf
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.