1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
|
"""
This module provides a wrapper around a Cactus simulation output, i.e. a directory of HDF5 files.
"""
import os
import collections
from . import datafile
class _RefinedSlice(object):
# simulation time on this slice
time = -1
# simulation iteration on this slice
it = -1
# a list of arrays of coordinate points along each direction [x, y, z]
c = None
# arrays of coordinate points along each direction
x = None
y = None
z = None
rl = None
# private
_sd = None
_rl = None
def __init__(self, sd, rl, time = -1, iteration = -1):
self._sd = sd
self._rl = rl
self.rl = rl
if time < 0 and iteration < 0:
raise TypeError('Neither time nor iteration provided')
if time >= 0:
self.it = sd._df._iter_from_time(time)
else:
self.it = iteration
try:
s = sd._df.slice(it = self.it, rl = rl.n)
self.time = s.time
except KeyError:
if time < 0:
raise IndexError('No such iteration: ' + str(iteration))
else:
raise IndexError('No such time: ' + str(time))
# pick a representative datafile and get the grid properties from it
if 'H' in self._sd.df:
df = self._sd.df['H']
else:
df = None
for key in self._sd.df:
if '.' in key:
continue
df = self._sd.df[key]
break
if df is None:
raise IndexError
ds = df.slice(self.it, rl = rl.n)
self.c = ds.layout.coords
self.x, self.y, self.z = self.c
def __getitem__(self, key):
if key in self._sd.df:
return self._sd.df[key].slice(self.it, rl = self._rl.n)
raise IndexError
class _RefinementLevel(object):
# refinement level number
n = -1
# private
_sd = None
def __init__(self, sd, n):
self._sd = sd
self.n = n
def slice(self, iteration = -1, time = -1):
return _RefinedSlice(self._sd, self, time, iteration)
class _DataDir(collections.MutableMapping):
_files = None
_paths = None
def __init__(self):
self._files = {}
self._paths = {}
def __setitem__(self, key, val):
if key in self._files:
raise ValueError
self._files[key] = None
self._paths[key] = val
def __delitem__(self, key):
if self._files[key]:
self._files[key].close()
del self._files[key]
del self._paths[key]
def __getitem__(self, key):
if not key in self._paths:
raise KeyError
elif self._files[key] is None:
self._files[key] = datafile.DataFile(self._paths[key])
return self._files[key]
def __len__(self):
return len(self._paths)
def __iter__(self):
for it in self._paths:
yield it
def close(self):
for f in self._files.values():
if f is not None:
f.close()
self._files.clear()
self._paths.clear()
class SimulationData(object):
"The full path to the simulation directory"
dirname = None
"A dictionary of { basename : DataFile } items representing the data files. The basename is the file name without the .h5 extension"
df = None
# per-refinement level parameters
rl = None
_df = None
def __init__(self, dirname):
self.dirname = os.path.abspath(dirname)
self.df = _DataDir()
# open all the hdf5 files in the dir
for f in os.listdir(self.dirname):
if (not f.endswith('.h5') or f.startswith('checkpoint') or f.endswith('.d.h5')):
continue
self.df[f[:-3]] = '%s/%s' % (self.dirname, f)
if len(self.df) == 0:
raise ValueError('No HDF5 data files in the directory.')
# pick a representative datafile and get the grid properties from it
if 'H' in self.df:
df = self.df['H']
else:
df = self.df.values()[0]
self._df = df
# get the refinement levels, iterations and times
self.rl = []
for rl in df.rl:
self.rl.append(_RefinementLevel(self, len(self.rl)))
|