XDMF(.xmf)形式についての覚書

# XDMF(.xmf)とは
XDMFはeXtensible Data Model and Formatの略称であり、データやモデルの幾何形状を保存するために使われるデータ形式です。本項執筆時ではVersion3.0が最新となっています。
本項は、[公式のドキュメント](http://www.xdmf.org/index.php/XDMF_Model_and_Format)に記されている情報を自分向けにまとめたものです。
また、ParaView5.2.0によって可視化した場合のサンプルもいくつか載せています。

# ベース: XML形式
XDMFは、基本的にはXMLのフォーマットに従っています。

```xml:sample1.xmf
<Tag>
    要素
</Tag>
```

以下のように、各要素に名前を指定することも可能です。

```xml:sample2.xmf
<Tag Name="Namae">
  要素
</Tag>
```

要素の種類を指定する際は、基本的に{要素名}Type="hoge"というアトリビュートを指定します。
GridならGridType、TopologyならTopologyType、AttributeならAttributeTypeです。
NameとDimensions以外のアトリビュートにはそれぞれデフォルトの値があり、指定されなかった場合はデフォルトの値と解釈されます。

※ 本記事内で"アトリビュート"と表記する時はXMLタグに付け加えるNameやGridTypeなどを指し、"Attribute"と表記する時はAttriubte要素を指します。

# XDMFの基本形式
XDMFファイルの内容は、Xdmfタグ内に記述される必要があります。
データは1つ以上のDomain要素から成り、Domain要素は1つ以上のGrid要素を持ちます。
Grid要素は1つ以上のTopology, Geometry要素を持つ必要があり、任意の数のAttribute要素を追加する事が可能です。それぞれ以下の役割を持ちます。

<dl>
  <dt>Topology</dt><dd>頂点の接続についての情報</dd>
  <dt>Geometry</dt><dd>頂点の座標についての情報</dd>
  <dt>Attribute</dt><dd>頂点や辺・面・セルに割り当てられるスカラ値、ベクトル値の分布</dd>
</dl>

また、実際の情報を指定する要素は全てDataItem要素で統一されています。したがって、XDMFの基本的な形は以下のようになります。

```xml:basic.xmf
<Xdmf>
  <Domain>
    <Grid>
      <Topology>
        <DataItem>...</DataItem>
      </Topology>
      <Geometry>
        <DataItem>...</DataItem>
      </Geometry>
      <Attribute> <!-- もし必要なら -->
        <DataItem>...</DataItem>
      </Attribute>
    </Grid>
  </Domain>
</Xdmf>
```
# `DataItem`要素
DataItemでは、ItemTypeとして以下の6つを指定することができます。デフォルトはUniformです。

<dl>
  <dt>Uniform(デフォルト)</dt>
  <dd>シンプルな値の配列</dd>
  <dt>Collection</dt>
  <dd>DataItem要素の配列</dd>
  <dt>Tree</dt>
  <dd>木構造を持ったDataItem要素</dd>
  <dt>HyperSlab</dt>
  <dd>子に指定したDataItem要素のうち、特定の範囲の値を抽出</dd>
  <dt>Coordinate</dt>
  <dd>子に指定したDataItem要素のうち、特定のインデックスの値を抽出</dd>
  <dt>Function</dt>
  <dd>式を適用した結果を生成</dd>
</dl>

CollectionやTreeから分かるように、DataItem要素は入れ子にすることが可能です。
DataItemにはItemTypeの他に、以下のようなアトリビュートを指定することが可能です。

```xml:attributes_of_data_item.xmf
<DataItem Name="DataItemDayo" ItemType="Uniform" Format="XML" NumberType="Float" Precision="4" Dimensions="3">
  1.0 2.0 3.0
</DataItem>
```

Dimensionsは必ず指定する必要がありますが、他のアトリビュートについては指定しない場合はデフォルトの値が使用されます。
多次元の場合、`Dimensions="3 5"`のように空白で区切ります。KJI（Z→Y→X）の順で解釈されるようです。

FormatはXML以外に、HDFとBinaryが指定可能です。
Formatが"Binary"の場合は、Endian、Compression、Seekを指定できます。

## Uniform
シンプルに配列です。Dimensionsと数が一致します。

```xml:uniform.xmf
<DataItem Dimensions="3" ItemType="Uniform">
 1.0 2.0 3.0
</DataItem>
```

基本的に、ほとんどの要素の一番下の子（葉）はUniformなDataItemで値を指定することになります。
（たまにValueアトリビュートで指定できるやつもいます）

## CollectionとTree
入れ子にします。CollectionはTree要素の子になることができますが、逆は無理です。
一番下部の葉はUniformでないといけません。

```xml:collections.xmf
<DataItem ItemType="Tree">
  <DataItem ItemType="Tree"> <!-- Treeの子のTree -->
    <DataItem ItemType="Collection"> <!-- Treeの子のTreeの子のCollection -->
      <DataItem ItemType="Uniform" Dimensions="3"> <!-- Treeの子のTreeの子のCollectionの子のUniform -->
        1.0 2.0 3.0
      </DataItem>
      <DataItem ItemType="Uniform" Dimensions="3">
        4.0 5.0 6.0
      </DataItem>
    </DataItem> 
  </DataItem>
  <DataItem ItemType="Collection"> <!-- Treeの子のCollection -->
    <DataItem ItemType="Uniform" Dimensions="3"> <!-- Treeの子のCollectionの子のUniform -->
      1.0 2.0 3.0
    </DataItem>
    <DataItem ItemType="Uniform" Dimensions="3">
      4.0 5.0 6.0
    </DataItem>
  </DataItem>
  <DataItem ItemType="Uniform" Dimensions="3"> <!-- Treeの子のUniform -->
    1.0 2.0 3.0
  </DataItem>
</DataItem>
```

## HyperSlab
あるDataItemのうち、起点、空間幅、要素数から自動的に抽出対象を生成するのがHyperSlabです。
データのサブセットを指定した範囲で抽出する時に使うっぽいです。

下記は公式の例ですが、HyperSlabの最初の子がそれぞれ起点、空間幅、要素数を各次元に対して持ちます。
この場合だと３成分のベクトルが100x200x300個、MyData.h5:/XYZに格納されており、
そのうち[0, 50]x[0,100]x[0,150]の範囲を、1個飛ばしで25x50x75個抽出する時の例です。（ややこしいですね）

```xml:hyperslab.xmf
<DataItem ItemType="HyperSlab" Dimensions="25 50 75 3">
    <DataItem Dimensions="3 4" Format="XML">
        0 0 0 0 
        2 2 2 1 
        25 50 75 3
    </DataItem>
    <DataItem Name="Points" Dimensions="100 200 300 3" Format="HDF">
        MyData.h5:/XYZ
    </DataItem>
</DataItem>
```

ItemType="HyperSlab"としたDataItem要素のDimensionsが、最初の子の最終行の要素数と一致する必要があることに注意してください。この例だとDimensions="25 50 75 3"と指定し、最初の子の最終行をそれと同様の25 50 75 3としています。

## Coordinate
HyperSlabと同様に子に持ったUniformなDataItemを対象として、非常に限定的な抽出を行うときに使用します。

下記も公式の例ですが、対象とするのは先程と同様に100x200x300個の３成分ベクトルです。
Coordinateは２つの子DataItem要素を持ち、最初の子が抽出する座標を指定します。
この例だと、100x200x300個のデータのうち欲しいのは２つの値だけで、

- 最初の値のY成分 = インデックス(0 0 0)のY成分(1)
- 最後の値のX成分 = インデックス(99 199 299)のX成分(0)

のみを抽出しています。なのでCoordinateのDimensionsは2になります。

```xml:coodinates.xmf
<DataItem ItemType="Coordinate" Dimensions="2">
    <DataItem Dimensions="2 4" Format="XML">
        0 0 0 1
        99 199 299 0
    </DataItem>
    <DataItem Name="Points" Dimensions="100 200 300 3" Format="HDF">
        MyData.h5:/XYZ
    </DataItem>
</DataItem>
```

## Function
子のDataItem要素を使って演算した結果を持つことができます。便利ですね。
式の内容はFunctionアトリビュート内に記述します。

```xml:function.xmf
<DataItem ItemType="Function" Function="$0 + $1" Dimensions="3">
    <DataItem Dimensions="3">
        1.0 2.0 3.0
    </DataItem>
    <DataItem Dimensions="3">
        4.1 5.2 6.3
    </DataItem>
</DataItem>
```

これは以下のDataItemと等価です。

```xml:equal_function.xmf
<DataItem Dimensions="3">
    5.1 7.2 9.3
</DataItem>
```

Function節内部では、

> The function description can be arbitrarily complex and contain SIN, COS, TAN, ACOS, ASIN, ATAN, LOG, EXP, ABS, and SQRT. In addition, there are the JOIN() and WHERE() expressions. JOIN can concatenate or interlace arrays while WHERE() can extract values where some condition is true. 

とあるように、四則演算以外に各種関数も適用できるようです。
JOIN & WHEREも可能なので、自動的な抽出もできるということですね。
下記のReferenceアトリビュートと合わせて上手く使えば可視化の手間が省けそうです。

## Referenceアトリビュート
Xpathベースで他のDataItemを参照することができます。
一度記述したものをHyperSlab、Coordinate、Function等で使い回す時に便利です。

```xml
<DataItem Name="addFunc" ItemType="Function" Function="10 + $0">
    <DataItem Reference="/Xdmf/DataItem[1]" />
</DataItem> 
```
この場合、<Xdmf>タグの直下に配置した最初のDataItem要素を参照しています。
詳しいパスの形式についてはXpathの項目を参照して下さい。

# Grid要素
Grid要素はGridTypeアトリビュートによって以下の種類を指定することができます。

<dl>
  <dt>Uniform</dt>
  <dd>デフォルト</dd>
  <dt>Collection</dt>
  <dd>同じアトリビュートを持ったUniformなGrid</dd>
  <dt>Tree</dt>
  <dd>階層構造を持ったGrid</dd>
  <dt>Subset</dt>
  <dd>他のグリッドの一部</dd>
</dl>

基本的にはUniformを使えば良さそうです。

## Uniform, Collection, Tree
Tree > Collection > Uniformな関係はDataItem要素と同様です。
UniformなGridは、前述したようにTopologyとGeometryを持つ必要があります。

## Subset
一度定義したGridもしくは内部で定義する新しいGridの、指定した部分をGridとして持つGridTypeです。

下記は公式の例です。部分指定する場合、SectionアトリビュートをDataItemとして、子にDataItemを持つ必要があります。

```xml
<Grid Name="Portion" GridType="Subset" Section="DataItem">
    <DataItem NumberType="Int" Dimensions="2" Format="XML">
        0 2
    </DataItem>
    <Grid Name="Target" Reference="XML">
        /Xdmf/Domain/Grid[@Name="Main Grid"]
    </Grid>
    <Attribute Name="New Values" Center="Cell">
        <DataItem Format="XML" Dimensions="2">
            100 150
        </DataItem>
    </Attribute>
</Grid>
```

Subsetの最初の子のDataItemでCellのインデックスを２つ指定しています。
Name="Target"としているのが既に定義したGridで、Xpathの形式でReferenceを持っています。
多分TopologyとGeometryの情報も自動的に関連付けられているんじゃないでしょうか。（確かめてないです）
抽出した２つのCellに対して、Cell中心のAttributeを指定しており、この場合のDataItemのDimensionsは抽出した際の数と一致します。（下記の例だと２になります）

Sectionアトリビュートを"All"にした場合、抽出部分を選ばない（同じGridをそのまま使う）となります。

```xml
<Grid Name="Portion" GridType="Subset" Section="All">
    <Grid Name="Target" Reference="XML">
        /Xdmf/Domain/Grid[@Name="Main Grid"]
    </Grid>
    <Attribute Name="New Values" Center="Cell">
        <DataItem Format="XML" Dimensions="3">
            100 150 200
        </DataItem>
    </Attribute>
</Grid>
```

この場合は参照先のGridに新しいAttributeを付け加えることになります。
参照を持ったGridは内部に子を持てないようなので、既に定義したグリッドにいろいろ付与したい場合に使うみたいです。

## Topology
TopologyTypeアトリビュートで格子の種類を指定します。
Structuredな格子の場合、Topologyは暗黙的に解決することが可能です。
数はDimensionsまたはNumberOfElementsアトリビュートで指定します。（どちらでも違いはなさそうです）

```xml:structured_topology.xmf
<Topology TopologyType="3DCoRectMesh" NumberOfElements="5 5 10"/>
```

Structuredな格子としては、以下を指定できます。

- 2DSMesh: 2次元Curvilinear
- 2DRectMesh: 2次元直交（グリッド幅は未定）
- 2DCoRectMesh: 2次元直交（グリッド幅一定）
- 3DSMesh
- 3DRectMesh
- 3DCoRectMesh

Unstructuredの場合、Connectivityを明示的に指定する必要があります。
詳しい形は[公式の図解](http://www.xdmf.org/index.php/XDMF_Model_and_Format#Topology)を参照してください。

<dl>
  <dt>Linear</dt>
  <dd>
    <ul>
      <li>Polyvertex</li>
      <li>Polyline</li>
      <li>Polygon</li>
      <li>Triangle</li>
      <li>Quadrilateral</li>
      <li>Tetrahedron</li>
      <li>Pyramid</li>
      <li>Wedge</li>
      <li>Hexahedron</li>
    </ul>
  </dd>
  <dt>Quadratic</dt>
  <dd>
    <ul>
      <li>Edge_3</li>
      <li>Tri_6</li>
      <li>Quad_8</li>
      <li>Tet_10</li>
      <li>Pyramid_13</li>
      <li>Wedge_15</li>
      <li>Hex_20</li>
    </ul>
  </dd>
<dt>Arbitrary</dt>
  <dd>
    <ul>
      <li>Mixed - 上記のUnstructuredな形状の集合</li>
    </li>
  </dd>
</dl>

## Geometry
GeometryTypeアトリビュートで幾何の種類を指定します。

<dl>
  <dt>XYZ</dt>
  <dd>(x, y, z) * 要素数の配列が必要</dd>
  <dt>XY</dt>
  <dd>(x, y) * 要素数の配列が必要、z = 0.0に固定</dd>
  <dt>X_Y_Z</dt>
  <dd>(x0, x1, x2, ..., xN), (y0, y1, y2, ..., yN), (z0, z1, z2, ..., zN)の形式. 要素数Nは一致する必要がある</dd>
  <dt>VXVYVZ</dt>
  <dd>各方向の1次元配列から全頂点を生成する（要素数不一致で良さそう）</dd>
  <dt>ORIGIN_DXDYDZ</dt>
  <dd>
    起点(x, y, z)のDataItemと各方向へのグリッド幅(dx, dy, dz)のDataItemから全頂点を生成。6要素のDataItemでないことに注意.
  </dd>
  <dt>ORIGIN_DXDY</dt>
  <dd>起点(x, y)と各方向へのグリッド幅(dx, dy)から全頂点を生成</dd>
</dl>

一定幅の直交格子の場合、ORIGIN_DXDYDZが非常に便利です。以下のように起点とグリッド幅を指定します。

```xml:origin_dxdydz.xmf
<Geometry GeometryType="ORIGIN_DXDYDZ">
  <DataItem Format="XML" Dimensions="3">
    0.1 0.2 0.3
  </DataItem>
  <DataItem Format="XML" Dimensions="3">
    0.1 0.2 0.3
  </DataItem>
</Geometry>
```

この場合、Topologyで指定した要素数に従って頂点が自動生成されます。
ただし、（ParaViewでは?）DataItemに入れた要素は[zの起点→yの起点→xの起点]の順で解釈されるようです。（幅の方も同様)
下記なら[0.3, 3.3] x [0.2, 1.2] x [0.1, 0.6]の空間が生成されます。

```xml:origin_dxdydz2.xmf
<Grid GridType="Uniform">
  <Topology TopologyType="3DCoRectMesh" NumberOfElements="5 5 10"/> <!-- 5x5x10の直交格子 -->
  <Geometry GeometryType="ORIGIN_DXDYDZ">
    <DataItem Format="XML" Dimensions="3">
      0.1 0.2 0.3
    </DataItem>
    <DataItem Format="XML" Dimensions="3">
      0.1 0.2 0.3
    </DataItem>
  </Geometry>
</Grid>
```

Geometry内の頂点座標を直接指定する場合、座標指定の順番に従ってノード番号が割り振られます。
UnstructuredなTopologyを指定する際は注意が必要です。

# Attribute
Scalar, Vector, Tensorなどを格納することができます。
Centerアトリビュートで Node, Edge, Face, Cell, Grid のどれを中心にするかを選択することができます。
スカラ値以外の場合、AttributeTypeで指定する必要があります。

1次元, 6頂点に対する値の指定の例を以下に示します。

```xml:ノード上のスカラ値.xmf
<Attribute Name="Node Scalars" Center="Node">
  <DataItem Format="XML" Dimensions="6">
    1 2 3 4 5 6
  </DataItem>
</Attribute>
```

```xml:ノード上のベクトル値.xmf
<Attribute Name="Node Vectors" AttributeType="Vector" Center="Node">
  <DataItem Format="XML" Dimensions="6 3">
    1 2 0
    3 4 0
    5 6 0
    2 4 0
    6 8 0
    10 12 0
  </DataItem>
</Attribute>
```

EdgeやFaceの値を割り当てる場合はCenter="Edge"のように指定できますが、

>Edge and Face centered values are defined, but do not map well to many visualization systems (ParaView, for example, ignores them at present). 

と公式にある通り、ParaViewもVisitもEdgeとFaceの値は無視してしまうようです。

# 要素の割り当て順

前述した通り、DimensionsはKJI-orderで指定するため、対象の要素数の後ろにベクトルやテンソルの要素数を指定することになります。つまり、Dimensions="3 5 4 3"の場合、"3 5 4"が要素数、最後の3がベクトルの成分数です。
3成分持ったベクトルが、4x5x3のXYZ空間の各ノードに割り当てられていきます。

内部の要素は、X成分から順に、つまりDimensionsの後ろ側から詰められていくようです。

```xml:test1.xmf
<?xml version="1.0" ?>
<!DOCTYPE Xdmf SYSTEM "Xdmf.dtd" []>
<Xdmf Version="3.0">
    <Domain Name="Domain 1">
        <Grid Name="Two Quads" GridType="Uniform">
            <Topology Name="topo" TopologyType="2DCORECTMesh" NumberOfElements="3 5"/>
            <Geometry Name="geo" GeometryType="ORIGIN_DXDY">
                <DataItem Format="XML" Dimensions="2">
                    0.0 0.0
                </DataItem>
                <DataItem Format="XML" Dimensions="2">
                    0.5 0.5
                </DataItem>
            </Geometry>
            <Attribute Name="Node Scalar" Center="Node">
                <DataItem Format="XML" Dimensions="3 5">
                    1.0 2.0 3.0 4.0 5.0
                    11.0 12.0 13.0 14.0 15.0
                    20.0 21.0 22.0 23.0 24.0
                </DataItem>
            </Attribute>
        </Grid>
    </Domain>
</Xdmf>
```

上記のように値を割り当てた時、Paraviewで見ると下図のようになりました。（2次元なので、ParaViewだとX座標が落ちてY→Zの順です）
<img width="1039" alt="スクリーンショット 2017-08-17 21.50.45.png" src="https://qiita-image-store.s3.amazonaws.com/0/40906/4823f287-0b07-6537-206a-d15b6dbb7c27.png">
(y, z) = (0.0, 0.0), (0.5, 0.0), (1.0, 0.0), ...という順に値が大きくなり、
6つ目の要素でリセットされて(0.0, 0.5)に11.0が割り当てられています。

ベクトルに変更した場合も同様の順番で、各成分→X方向→Y方向→Z方向という順で割り当てられるようです。

```xml:test2.xmf
<?xml version="1.0" ?>
<!DOCTYPE Xdmf SYSTEM "Xdmf.dtd" []>
<Xdmf Version="3.0">
    <Domain Name="Domain 1">
        <Grid Name="Two Quads" GridType="Uniform">
            <Topology Name="topo" TopologyType="2DCORECTMesh" NumberOfElements="3 5"/>
            <Geometry Name="geo" GeometryType="ORIGIN_DXDY">
                <DataItem Format="XML" Dimensions="2">
                    0.0 0.0
                </DataItem>
                <DataItem Format="XML" Dimensions="2">
                    0.5 0.5
                </DataItem>
            </Geometry>
            <Attribute Name="Node Scalar" Center="Node">
                <DataItem Format="XML" Dimensions="3 5">
                    1.0 2.0 3.0 4.0 5.0
                    11.0 12.0 13.0 14.0 15.0
                    20.0 21.0 22.0 23.0 24.0
                </DataItem>
            </Attribute>
            <Attribute Name="Node Vector" AttributeType="Vector" Center="Node">
                <DataItem Name="X"  Format="XML" Dimensions="3 5 3">
                    1.0 1.0 0.0
                    2.0 1.0 0.0
                    3.0 1.0 0.0
                    4.0 1.0 0.0
                    5.0 1.0 0.0
                    6.0 1.0 0.0
                    7.0 1.0 0.0
                    8.0 1.0 0.0
                    9.0 1.0 0.0
                    10.0 1.0 0.0
                    11.0 1.0 0.0
                    12.0 1.0 0.0
                    13.0 1.0 0.0
                    14.0 1.0 0.0
                    15.0 1.0 0.0
                </DataItem>
            </Attribute>
        </Grid>
    </Domain>
</Xdmf>
```

<img width="1012" alt="スクリーンショット 2017-08-17 22.12.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/40906/7299d7c7-3476-0975-4c5f-591c6e0f165c.png">


# その他の要素

## Set
Node, Edge, Face, CellのようなGrid内の特定の要素について、追加の情報を設定できる要素です。
SetTypeがEdgeまたはFaceの場合は、子に複数のDataItemを持ち、最初の2つはそれぞれ

1. Cellのインデックス
2. Cell毎(Cell-local)なEdgeやFaceのインデックス

を指定するのに使用されます。
公式に示してある以下の例は、Cell1, 2, 3, 4それぞれのFace0に対して、100, 110, 100, 200という値を割り当てていることになります。
AttributeのCenter="Edge"と”Face”は可視化ソフトだと無視されるよ、という話だったので、多分こちらも直接の可視化は無理そうな気がします。

```xml:set.xmf
<Set Name="Ids" SetType="Face">
    <DataItem Format="XML" Dimensions="4" >
        1 2 3 4
    </DataItem>
    <DataItem Format="XML" Dimensions="4" >
        0 0 0 0
    </DataItem> 
    <Attribute Name="Example" Center="Face">
        <DataItem Format="XML" Dimensions="4" >
            100.0 110.0 100.0 200.0
        </DataItem>
    </Attribute>
</Set>
```

## Time
Grid要素の子として存在し、時間に関する情報を格納する要素です。

下記の種類があります。

<dl>
  <dt>Single (デフォルト)</dt>
  <dd>Gridに対して割り当てる単一の時間値</dd>
  <dt>HyperSlab</dt>
  <dd>起点、時間幅、個数によって時間を生成</dd>
  <dt>List</dt>
  <dd>割り当てる時間のリスト</dd>
  <dt>Range</dt>
  <dd>最小値と最大値から生成（幅は？）</dd>  
</dl>

Single以外の場合は、GridTypeがCollectionのような場合（複数の子を持つ場合）の割り当てに使うようです。

それぞれ以下のようになります。Singleの場合はValueアトリビュートが使えます。

```xml:time_single.xmf
<Time Value="1.1" />
```

Single以外の場合はDataItem要素を子に持たせます。

```xml:time_hyperslab.xmf
<Time TimeType="HyperSlab"> <!-- t = [0.0, 0.1, 0.2, ..., 9.9] -->
    <DataItem Format="XML" NumberType="Float" Dimensions="3">
        0.0 0.1 100
    </DataItem>
</Time>
```

時間幅が一定でないような場合はListで。

```xml:time_list.xmf
<Time TimeType="List">
    <DataItem Format="XML" NumberType="Float" Dimensions="7">
        0.0 0.1 0.2 1.0 1.5 15.0 100.5
    </DataItem>
</Time>
```

離散値を取らないような場合（？）はRangeが使えます。

```xml:time_range.xmf
<Time TimeType="Range">
    <DataItem Format="XML" NumberType="Float" Dimensions="2">
        0.0 10.0
    </DataItem>
</Time>
```

> Xdmf3 only supports a single time value for each grid. 
> Older versions allow use of different TimeTypes.

とあり、Xdmf3では現在Singleタイプしかサポートされていないようです。

## Information
個々のアプリケーション向けの情報だったりを格納できます。
Valueアトリビュートの中もしくはInformation要素の子として値を格納できます。

```xml:info.xmf
<Information Name="XBounds" Value="0.0 10.0"/>
<Information Name="Bounds"> 0.0 10.0 100.0 110.0 200.0 210.0 </Information>
```

# HDF5またはバイナリをデータソースとして使う
データが大規模になった場合、XDMFファイルに直接データを埋め込むのではなく、DataItem要素のソースとしてHDF5を指定するのが一般的です。

```xml:data_item_from_hdf5.xmf
<DataItem ItemType="Uniform" Format="HDF" NumberType="Float" Precision="8" Dimensions="64 128 256">
  OutputData.h5:/Results/Iteration 100/Part 2/Pressure
</DataItem>
```
当たり前ですが、HDF5内のデータの要素数と指定したDimensionsが一致する必要があります。

バイナリデータの場合も同様です。

```xml:data_item_from_binary.xmf
<DataItem ItemType="Uniform" Format="Binary" Dimensions="64 128 256">
  PressureFile.bin
</DataItem>
```
# 領域分割した計算データを格納する場合

Domain内に複数のGridを割り当て、頂点座標をズラすとよさそうです。
GeometryTypeをORIGIN_DXDYDZで指定できる場合は非常に楽に指定可能です。

```xml:domain_composition.xmf
<?xml version="1.0" ?>
<!DOCTYPE Xdmf SYSTEM "Xdmf.dtd" []>
<Xdmf Version="3.0">
    <Domain Name="Domain 1">
        <Grid Name="Two Quads" GridType="Uniform">
            <Topology Name="topo" TopologyType="2DCORECTMesh" NumberOfElements="3 5"/>
            <Geometry Name="geo" GeometryType="ORIGIN_DXDY">
                <DataItem Format="XML" Dimensions="2">
                    0.0 0.0
                </DataItem>
                <DataItem Format="XML" Dimensions="2">
                    0.5 0.5
                </DataItem>
            </Geometry>
            <Attribute Name="Node Scalar" Center="Node">
                <DataItem Format="XML" Dimensions="3 5">
                    1.0 2.0 3.0 4.0 5.0
                    11.0 12.0 13.0 14.0 15.0
                    20.0 21.0 22.0 23.0 24.0
                </DataItem>
            </Attribute>
        </Grid>
        <Grid Name="Two Quads2" GridType="Uniform">
            <Topology Name="topo" TopologyType="2DCORECTMesh" NumberOfElements="3 5"/>
            <Geometry Name="geo" GeometryType="ORIGIN_DXDY">
                <DataItem Format="XML" Dimensions="2">
                    1.0 0.0
                </DataItem>
                <DataItem Format="XML" Dimensions="2">
                    0.5 0.5
                </DataItem>
            </Geometry>
            <Attribute Name="Node Scalar" Center="Node">
                <DataItem Format="XML" Dimensions="3 5">
                    -1.0   -2.0  -3.0  -4.0  -5.0
                    -11.0 -12.0 -13.0 -14.0 -15.0
                    -20.0 -21.0 -22.0 -23.0 -24.0
                </DataItem>
            </Attribute>
        </Grid>
    </Domain>
</Xdmf>
```

<img width="976" alt="スクリーンショット 2017-08-17 22.37.34.png" src="https://qiita-image-store.s3.amazonaws.com/0/40906/059c3231-5f6c-5605-e7a2-3de09077c2ed.png">
~~また、AMRなどの階層構造を持っている場合、各GridをTree化していくと良さげです。~~
追記: GridはTree化しても（現状のParaViewなどでは）描画時の階層構造を指定できないため、
サブグリッドを持つ場合には出力時に部分部分のMeshBlockを作って出力するなどして自力対応するしかないようです。
vtk用のリーダーだとAMR対応しているみたいなので、サブグリッド構造を持つ場合にはXDMFよりvtk等を使った方が良さそうです……。

# ヘッダと`<Xdmf>`タグ
ヘッダでxmlバージョンを指定する必要があります。
Xdmfタグには、使用しているXdmfのバージョンを記すことが可能です。

```xml:header.xmf
<?xml version="1.0" ?>
<!DOCTYPE Xdmf SYSTEM "Xdmf.dtd" []>
<Xdmf Version="2.0">
  ...
</Xdmf>
```
>While there exists an Xdmf DTD and a Schema they are only necessary for validating parsers. For performance reasons, validation is typically disabled.

とあるように、SYSTEM "Xdmf.dtd" []部はバリデーション用の記述であるようです。

# XInclude
他のXDMFファイルをincludeすることが出来ます。

```xml:include_other.xmf
<Xdmf Version="2.0" xmlns:xi="[http://www.w3.org/2001/XInclude]">
  <xi:include href="Example3.xmf"/>
</Xdmf>
```

# Xpath
Reference管理のためにパス構造が必要になります。
基本的に上位のタグから'/'区切りで階層構造を表します。

Xdmfが

```xml
<Xdmf>
  <Domain>
    <Grid Name="Grid1">
      ...
    </Grid>
  </Domain>
</Xdmf>
```

という構造になっている場合、Grid1をReferenceアトリビュートで参照するためのXpathは

```
/Xdmf/Domain/Grid
```

もしくは

```
/Xdmf/Domain/Grid[1]
```

という形になります。複数ある場合は1始まりの[]演算子でアクセスできます。10番目なら[10]です。
また、Nameでもアクセスできて、

```xml
/Xdmf/Domain/Grid[@Name="Grid1"]
```

でもOKです。同じ名前のものが複数ある場合は最初のものが参照先になります。
Domainに所属しないDataItemを下記のように格納した場合、

```xml
<Xdmf>
  <DataItem></DataItem>
  <Domain>
    <Grid Name="Grid1">
      ...
    </Grid>
  </Domain>
</Xdmf>
```

Xpathは以下のようになります。

```
/Xdmf/DataItem[1]
```

# Entity
ヘッダ中の

```xml
<!DOCTYPE Xdmf SYSTEM "Xdmf.dtd" []>
```

の[]内でEntityというものを指定可能です。

```xml
<!DOCTYPE Xdmf SYSTEM "Xdmf.dtd" [
　　<!ENTITY cellDimsZYX "45 30 120">
]>
```

この場合、Dimensionsアトリビュートを Dimensions=&cellDimsZXY; と書くことが出来ます。
このあたり、どこからがXMLでどこからがXDMF固有の仕様なのか把握できていません。

# おまけ: Xdmf APIと拙作の宣伝
C++/Python/FortranのAPIがXdmf.orgから提供されています。
http://www.xdmf.org/index.php/XDMF_API
gitで引っ張ってくることが可能です。
http://www.xdmf.org/index.php/Get_Xdmf
cmakeでビルドできるのですが、HDF5とBoostヘッダーのインストールが必要になります。

また、あんまり便利な機能とかHDF5連携は(他のライブラリがあるので)要らないよ、って場合（自分）向けに
上述したXdmfの構造を作る + インデント管理のためだけのヘッダーライブラリを書きました。
https://github.com/hsimyu/SimpleXdmf
この記事で解説したようなXdmfの構造を直に作る + NameアトリビュートベースのReference管理ができます。