#
# This file is part of postpic.
#
# postpic is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# postpic is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with postpic. If not, see <http://www.gnu.org/licenses/>.
#
# Georg Wittig, Stephan Kuschel 2014
'''
Reader for HDF5 File format written by the VSim Code:
http://www.txcorp.com/support/vsim-support-menu/vsim-documentation
Dependecies:
h5py The Python actual reader for hdf5 file format.
Georg Wittig, Stephan Kuschel 2014
'''
from __future__ import absolute_import, division, print_function, unicode_literals
from . import Dumpreader_ifc
from . import Simulationreader_ifc
from .. import helper
import h5py
import numpy as np
import os
__all__ = ['Hdf5reader', 'VSimReader']
[docs]class Hdf5reader(Dumpreader_ifc):
'''
The Reader implementation for HDF5 Data written by the VSim Code.
as argument h5file can be any *.h5 file of the dump of consideration.
'''
def __init__(self, h5file, **kwargs):
'''
Initializes the Hdf5reader for a specific h5file.
'''
super(self.__class__, self).__init__(h5file, **kwargs)
if not os.path.isfile(h5file):
raise IOError('File "' + str(h5file) + '" doesnt exist.')
pathname = os.path.abspath(os.path.dirname(h5file))
filelist = [os.path.join(pathname, f) for f in os.listdir(pathname) if f.endswith(".h5")]
self._time = h5py.File(h5file)["time"].attrs["vsTime"]
# all dumped h5 files at the same time
self._dumplist = [f for f in filelist
if self._time == h5py.File(f)["time"].attrs["vsTime"]]
[docs] def keys(self):
keys = []
for f in self._dumplist:
for a in h5py.File(f):
if a not in keys:
keys.append(a)
return keys
[docs] def __getitem__(self, key):
''' delivers one dataset with the key key.'''
for f in self._dumplist:
for a in h5py.File(f):
if a == key:
return h5py.File(f)[key]
# print " couldn't find key ", key
return None
[docs] def timestep(self):
return self["time"].attrs['vsStep']
[docs] def time(self):
return self._time
[docs] def simdimensions(self):
return self["compGridGlobal"].attrs["vsNumCells"].shape[0]
[docs] def dataE(self, axis, **kwargs):
# x, y, z, px, py, pz same as in sdf. weigt and ID not included.
axis = helper.axesidentify[axis]
try:
return np.float64(self["ElecMultiField"][..., axis])
except(KeyError):
return None
[docs] def dataB(self, axis, **kwargs):
# x, y, z, px, py, pz same as in sdf. wweigt and ID not included.
axis = helper.axesidentify[axis]
try:
return np.float64(self["MagMultiField"][..., axis])
except(KeyError):
return None
[docs] def grid(self, axis):
''' returns the array of the positions of all cells on axis = axis. '''
# x, y, z, px, py, pz same as in sdf. weigt and ID not included.
axis = helper.axesidentify[axis]
temp = self["compGridGlobal"]
return np.linspace(temp.attrs["vsLowerBounds"][axis],
temp.attrs["vsUpperBounds"][axis], temp.attrs["vsNumCells"][axis])
[docs] def listSpecies(self):
''' returns all h5 dumps that have a attribute "mass" '''
specieslist = []
for f in self._dumplist:
h5 = h5py.File(f)
for key in h5:
if 'mass' in h5[key].attrs:
specieslist.append(key)
return specieslist
[docs] def getSpecies(self, species, attrib):
'''
Returns one of the attributes out of (x,y,z,px,py,pz,weight,ID) of
this particle species.
Valid Scalar attributes are (mass, charge).
'''
# x, y, z, px, py, pz same as in sdf. weigt and ID not included.
attrib = helper.attribidentify[attrib]
attrib = {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 9: 'numPtclsInMacro',
11: 'mass', 12: 'charge'}[attrib]
if isinstance(attrib, int):
ret = np.float64(self[species])[:, attrib]
# VSim dumps gamma*v = p/m0, so multiply by mass if px, pz or pz requested
if attrib > 2:
ret = ret * self.getSpecies(species, 'mass')
return ret
else:
return np.float64(self[species].attrs[attrib])
[docs] def getderived(self):
'''
Returns all Keys starting with "Derived/".
'''
pass
def __str__(self):
return '<Hdf5reader at "' + str(self.dumpidentifier) + '">'
[docs]class VSimReader(Simulationreader_ifc):
'''
Represents a full Simulation ( = Series of Dumps with equal output). The VSimReader must be
initialized with the path to a folder containing all the dumps. It will then walk through
all available .h5 files in this directory to identify the available timesteps of the
simulation.
'''
def __init__(self, path, **kwargs):
super(self.__class__, self).__init__(path, **kwargs)
self.path = path
import os.path
if not os.path.isdir(path):
raise IOError('Path "' + str(path) + '" is no directory.')
# check every .h5 file in directory path
self._filelist = [os.path.join(path, f) for f in os.listdir(path) if f.endswith(".h5")]
# only use dumps with time > 0
h5s = [h5py.File(f) for f in self._filelist]
boollist = [h5['time'].attrs['vsTime'] > 0 for h5 in h5s]
self._filelist = [self._filelist[i] for i in range(len(self._filelist)) if boollist[i]]
h5s = [h5s[i] for i in range(len(h5s)) if boollist[i]]
# find all possible timesteps
self._steplist = [h5['time'].attrs['vsStep'] for h5 in h5s]
self._stepsdumped = list(set(self._steplist))
self._stepsdumped.sort()
def __len__(self):
return len(self._stepsdumped)
[docs] def getDumpreader(self, index):
fileindex = self._steplist.index(self._stepsdumped[index])
return Hdf5reader(self._filelist[fileindex])
def __str__(self):
return '<VSimReader at "' + str(self.path) + '">'