summaryrefslogtreecommitdiff
path: root/simdata.py
blob: dd5398e4dc2b3f34e59038e9e41e4724fe1c16c4 (plain)
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
"""
This module provides a wrapper around a Cactus simulation output, i.e. a directory of HDF5 files.
"""

import os

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 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

    "A dictionary of all the { gridfunction : [datafiles it is located in] } pairs for this set of data"
    gf = None

    # per-refinement level parameters
    rl = None

    _df = None

    def __init__(self, dirname):
        self.dirname = os.path.abspath(dirname)
        self.df = {}
        self.gf = {}

        # open all the hdf5 files in the dir
        for f in os.listdir(dirname):
            if (not f.endswith('.h5') or f.startswith('checkpoint') or f.endswith('.d.h5')):
                continue

            self.df[f[:-3]] = datafile.DataFile('%s/%s' % (dirname, f))
        if len(self.df) == 0:
            raise ValueError('No HDF5 data files in the directory.')

        for df in self.df.values():
            for ds in df.datasets:
                if ds.name in self.gf:
                    self.gf[ds.name].append(df)
                self.gf[ds.name] = [df]

        # 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)))