- changed status to invalid
XDMF writer: share mesh between different functions (avoid ParaView oddities)
Issue #885
invalid
Thanks to PR #338, FEniCS has support for Xdmf3 time series with multiple data sets.
So far, the data sets are stores as
<?xml version="1.0"?>
<!DOCTYPE Xdmf SYSTEM "Xdmf.dtd" []>
<Xdmf Version="3.0" xmlns:xi="http://www.w3.org/2001/XInclude">
<Domain>
<Grid Name="TimeSeries_u" GridType="Collection" CollectionType="Temporal">
<Grid Name="mesh" GridType="Uniform">
<Topology NumberOfElements="2121" TopologyType="Triangle" NodesPerElement="3">
<DataItem Dimensions="2121 3" NumberType="UInt" Format="HDF">all.h5:/Mesh/0/mesh/topology</DataItem>
</Topology>
<Geometry GeometryType="XY">
<DataItem Dimensions="1149 2" Format="HDF">all.h5:/Mesh/0/mesh/geometry</DataItem>
</Geometry>
<Time Value="0" />
<Attribute Name="u" AttributeType="Vector" Center="Node">
<DataItem Dimensions="1149 3" Format="HDF">all.h5:/VisualisationVector/0</DataItem>
</Attribute>
</Grid>
<Grid>
<xi:include xpointer="xpointer(//Grid[@Name="TimeSeries_u"]/Grid[1]/*[self::Topology or self::Geometry])" />
<Time Value="0.001" />
<Attribute Name="u" AttributeType="Vector" Center="Node">
<DataItem Dimensions="1149 3" Format="HDF">all.h5:/VisualisationVector/3</DataItem>
</Attribute>
</Grid>
<!-- More time steps ... -->
<Grid Name="TimeSeries_p" GridType="Collection" CollectionType="Temporal">
<Grid Name="mesh" GridType="Uniform">
<Topology NumberOfElements="2121" TopologyType="Triangle" NodesPerElement="3">
<DataItem Dimensions="2121 3" NumberType="UInt" Format="HDF">all.h5:/Mesh/1/mesh/topology</DataItem>
</Topology>
<Geometry GeometryType="XY">
<DataItem Dimensions="1149 2" Format="HDF">all.h5:/Mesh/1/mesh/geometry</DataItem>
</Geometry>
<Time Value="0" />
<Attribute Name="p" AttributeType="Scalar" Center="Node">
<DataItem Dimensions="1149 1" Format="HDF">all.h5:/VisualisationVector/1</DataItem>
</Attribute>
</Grid>
<Grid>
<xi:include xpointer="xpointer(//Grid[@Name="TimeSeries_p"]/Grid[1]/*[self::Topology or self::Geometry])" />
<Time Value="0.001" />
<Attribute Name="p" AttributeType="Scalar" Center="Node">
<DataItem Dimensions="1149 1" Format="HDF">all.h5:/VisualisationVector/4</DataItem>
</Attribute>
</Grid>
<!-- ... -->
</Grid>
</Domain>
</Xdmf>
Every data set (here u
and p
has its own TimeSeries
.
This has multiple disadvantages:
- The mesh cannot be shared between
u
andp
. - ParaView recognized the data sets as partial, leading to all sorts of funny errors (see, e.g., here).
In case the the data sets share the same mesh – which I assume is the dominant use case –, the data could be stored like
<?xml version="1.0"?>
<!DOCTYPE Xdmf SYSTEM "Xdmf.dtd" []>
<Xdmf Version="3.0" xmlns:xi="http://www.w3.org/2001/XInclude">
<Domain>
<Grid Name="TimeSeries_u" GridType="Collection" CollectionType="Temporal">
<Grid Name="mesh" GridType="Uniform">
<Topology NumberOfElements="2121" TopologyType="Triangle" NodesPerElement="3">
<DataItem Dimensions="2121 3" NumberType="UInt" Format="HDF">all.h5:/Mesh/0/mesh/topology</DataItem>
</Topology>
<Geometry GeometryType="XY">
<DataItem Dimensions="1149 2" Format="HDF">all.h5:/Mesh/0/mesh/geometry</DataItem>
</Geometry>
<Time Value="0" />
<Attribute Name="u" AttributeType="Vector" Center="Node">
<DataItem Dimensions="1149 3" Format="HDF">all.h5:/VisualisationVector/0</DataItem>
</Attribute>
<Attribute Name="p" AttributeType="Scalar" Center="Node">
<DataItem Dimensions="1149 1" Format="HDF">all.h5:/VisualisationVector/1</DataItem>
</Attribute>
</Grid>
<Grid>
<xi:include xpointer="xpointer(//Grid[@Name="TimeSeries_u"]/Grid[1]/*[self::Topology or self::Geometry])" />
<Time Value="0.001" />
<Attribute Name="u" AttributeType="Vector" Center="Node">
<DataItem Dimensions="1149 3" Format="HDF">all.h5:/VisualisationVector/2</DataItem>
</Attribute>
<Attribute Name="p" AttributeType="Scalar" Center="Node">
<DataItem Dimensions="1149 1" Format="HDF">all.h5:/VisualisationVector/3</DataItem>
</Attribute>
</Grid>
<!-- More time steps ... -->
</Domain>
</Xdmf>
Advantages:
- (slightly) smaller files
- better support for ParaView.
For implementing this, I see two possible interfaces:
- Provide a parameter (like the exisitng
'rewrite_function_mesh'
) that tells the writer to share the mesh between all input functions - Add a
write_all
method with the signaturewrite_all(list_of_functions, time)
.
The latter is perhaps cleaner in that it forces all functions to be present at all time steps.
Comments (1)
-
reporter - Log in to comment
Okay, that was easier than expected. Looking at the code, one finds the parameter
'functions_share_mesh'
that does exactly what's described.