Exemplo n.º 1
0
def readdns(fname):
	"""
	    readdns(fname)
	    A function for reading binary data from the SIMSON binary format

	    input variable:
	    fname : file name
	"""
	#
	try:
		infile = open(fname, 'rb')
	except IOError as e:
		print('I/O error ({0}): {1}'.format(e.errno, e.strerror))
		return -1
	#
	#---------------------------------------------------------------------------
	# READ HEADER
	#---------------------------------------------------------------------------
	wdsz = 8
	realtype = 'd'
	#
	# identify endian encoding (and number passive scalar)
	etagb = infile.read(4)
	etagL = struct.unpack('<i', etagb)[0]
	etagB = struct.unpack('>i', etagb)[0]
	# 1644 = 44 + (2*8) * 100 means a maximum of 100 passive scalars
	if ((etagL >= 44) & (etagL <= 1644)):
		# print('Reading little-endian file\n')
		emode = '<'
		nscal = int((etagL-44)/(2*wdsz))
	elif ((etagB >= 44) & (etagB <= 1644)):
		# print('Reading big-endian file\n')
		emode = '>'
		nscal = int((etagB-44)/(2*wdsz))
	else:
		print('ERROR: could not initerpret endianness')
		return -3
	#
	# Reynolds Number
	Re = infile.read(wdsz)
	Re = struct.unpack(emode+realtype,Re)[0]
	#
	# Poiseuille/Couette flag [deprecated]
	PouCou = infile.read(4)
	PouCou = struct.unpack(emode+'i',PouCou)[0]
	#
	# physical box size (here x and z only)
	boxsz = [0 for i in range(3)]
	dum = infile.read(2*wdsz)
	dum = list(struct.unpack(emode+2*realtype,dum))
	boxsz[0] = dum[0]; boxsz[2] = dum[1]
	#
	# time
	time = infile.read(wdsz)
	time = struct.unpack(emode+realtype,time)[0]
	#
	# dummy variable
	dum = infile.read(wdsz)
	#
	# passive scalar(s) (not tested)
	pr = np.zeros(nscal)
	m  = np.zeros(nscal)
	for i in range(nscal):
		pr[i] = infile.read(wdsz)
		pr[i] = struct.unpack(emode+realtype,pr[i])[0]
		m[i] = infile.read(wdsz)
		m[i] = struct.unpack(emode+realtype,m[i])[0]
	#
	# end-of-line
	eol = infile.read(8)
	#
	# box size
	lr1 = infile.read(3*4)
	lr1 = list(struct.unpack(emode+3*'i',lr1))
	#
	# nfzsym (z-symmetry flag)
	nfzsym = infile.read(4)
	nfzsym = list(struct.unpack(emode+'i',nfzsym))[0]
	#
	# end-of-line
	eol = infile.read(8)
	#
	# compute total number of points per element
	npel = lr1[0] * lr1[1] * lr1[2]
	#
	# get number of pysical dimensions
	ndim = 2 + (lr1[2]>1)
	#
	# flow type
	fltype = infile.read(4)
	fltype = struct.unpack(emode+'i',fltype)[0]
	#
	# delta star (and boxsz along y-direction)
	dstar = infile.read(wdsz)
	dstar = struct.unpack(emode+realtype,dstar)[0]
	boxsz[1] = 2/dstar
	#
	# end-of-line
	eol = infile.read(8)
	#
	# flow-type dependent quantities
	#
	if (fltype == -1):
		rlam = infile.read(wdsz)
		rlam = struct.unpack(emode+realtype,rlam)[0]
		eol = infile.read(8)
	if (fltype == -2):
		rlam = infile.read(wdsz)
		rlam = struct.unpack(emode+realtype,rlam)[0]
		spanv = infile.read(wdsz)
		spanv = struct.unpack(emode+realtype,spanv)[0]
		eol = infile.read(8)
	if ((fltype == 4) or (fltype == 5)):
		bstart = infile.read(wdsz)
		bstart = struct.unpack(emode+realtype,bstart)[0]
		blength = infile.read(wdsz)
		blength = struct.unpack(emode+realtype,blength)[0]
		eol = infile.read(8)
	if ((fltype >=4) and (fltype <= 9)):
		bstart = infile.read(wdsz)
		bstart = struct.unpack(emode+realtype,bstart)[0]
		blength = infile.read(wdsz)
		blength = struct.unpack(emode+realtype,blength)[0]
		rlam = infile.read(wdsz)
		rlam = struct.unpack(emode+realtype,rlam)[0]
		spanv = infile.read(wdsz)
		spanv = struct.unpack(emode+realtype,spanv)[0]
		eol = infile.read(8)
	if (abs(fltype) == 20):
		gr = infile.read(nscal*wdsz)
		gr = struct.unpack(emode+nscal*realtype, gr)
		eol = infile.read(8)
	#
	# get variables
	var = [0 for i in range(5)]
	var[0] = ndim  # position
	var[1] = ndim  # velocity
	var[2] = 0     # pressure is not saved (SIMSON) 
	var[3] = 0     # temperature is treated like a scalar (SIMSON)
	var[4] = nscal # scalars
	#
	#---------------------------------------------------------------------------
	# READ DATA
	#---------------------------------------------------------------------------
	#
	# number of points
	npel = lr1[0]*lr1[1]*lr1[2]
	#
	# number of points per plane
	nppl = lr1[0]*lr1[2]
	#
	# reading buffer in fourier space
	fou =    np.zeros((lr1[2],lr1[1],lr1[0]/2+1)) + \
	      1j*np.zeros((lr1[2],lr1[1],lr1[0]/2+1))
	#
	# initialize data structure
	data = exdat.exadata(ndim, 1, lr1, var)
	data.time   = time
	data.wdsz   = wdsz
	if (emode == '<'):
		data.endian = 'little'
	elif (emode == '>'):
		data.endian = 'big'
	#
	# generate geometry
	# - x-direction
	dx = boxsz[0]/lr1[0]
	for ix in range(lr1[0]):
		data.elem[0].pos[0,:,:,ix] = dx * ix
	# - y-direction
	dy = np.arccos(-1.0)/(lr1[1]-1)
	for iy in range(lr1[1]):
		data.elem[0].pos[1,:,iy,:] = boxsz[1] * (1-np.cos(dy*iy))/2
	# - z-direction
	dz = boxsz[2]/lr1[2]
	for iz in range(lr1[2]):
		data.elem[0].pos[2,iz,:,:] = dz * (iz-lr1[2]/2)
	#
	# read velocity and transform in physical space
	for idim in range(3):
		for iz in range(lr1[2]):
			if (iz <= lr1[2]/2):
				izf = iz
			else:
				izf = lr1[2]/2 * 3 - (iz+1)
			for iy in range(lr1[1]):
				fi = infile.read(lr1[0]*wdsz)
				fi = list(struct.unpack(emode+lr1[0]*realtype, fi))
				ip = 0
				for ix in range(int(lr1[0]/2)):
					fou[izf,iy,ix] = (fi[ip] + 1j*fi[ip+1]) * nppl * (-1)**idim
					ip += 2
				# end-of-line
				eol = infile.read(8)
		#
		# back to physical space
		data.elem[0].vel[idim,:,:,:] = np.fft.irfft2(fou,(lr1[0],lr1[2]),(2,0))
	#
	# read scalars and transform in physical space
	for ivar in range(var[4]):
		for iz in range(lr1[2]):
			if (iz <= lr1[2]/2):
				izf = iz
			else:
				izf = lr1[2]/2 * 3 - (iz+1)
			for iy in range(lr1[1]):
				fi = infile.read(lr1[0]*wdsz)
				fi = list(struct.unpack(emode+lr1[0]*realtype, fi))
				ip = 0
				for ix in range(int(lr1[0]/2)):
					fou[izf,iy,ix] = (fi[ip] + 1j*fi[ip+1]) * nppl
					ip += 2
				# end-of-line
				eol = infile.read(8)
		#
		# back to physical space
		data.elem[0].scal[ivar,:,:,:] = np.fft.irfft2(fou,(lr1[0],lr1[2]),(2,0))
	#
	#---------------------------------------------------------------------------
	# CLOSE FILE 
	#---------------------------------------------------------------------------
	#
	# close file
	infile.close()
	#
	# output
	return data
Exemplo n.º 2
0
def readrea(fname):
	"""
	    readrea
	    A function for reading .rea files for nek5000

	    input variable:
	    fname : file name
	"""
	#
	try:
		infile = open(fname, 'r')
	except IOError as e:
		print('I/O error ({0}): {1}'.format(e.errno, e.strerror))
		#return -1
	#
	#---------------------------------------------------------------------------
	# READ HEADER (2 lines) + ndim + number of parameters
	#---------------------------------------------------------------------------
	#
	infile.readline()
	infile.readline()
	ndim = int(infile.readline().split()[0])
	npar = int(infile.readline().split()[0])
	#
	nface = 2*ndim
	#
	#---------------------------------------------------------------------------
	# READ parameters
	#---------------------------------------------------------------------------
	#
	param = np.zeros((npar,1))
	for ipar in range(npar):
		param[ipar] = float(infile.readline().split()[0])
	#
	#---------------------------------------------------------------------------
	# skip passive scalars
	#---------------------------------------------------------------------------
	#
	npscal = int(infile.readline().split()[0])
	for ipscal in range(npscal):
		infile.readline()
	#
	#---------------------------------------------------------------------------
	# skip logical switches
	#---------------------------------------------------------------------------
	#
	nswitch = int(infile.readline().split()[0])
	for iswitch in range(nswitch):
		infile.readline()
	#
	#---------------------------------------------------------------------------
	# skip XFAC,YFAC,XZERO,YZERO
	#---------------------------------------------------------------------------
	#
	infile.readline()
	#
	#---------------------------------------------------------------------------
	# READ MESH
	#---------------------------------------------------------------------------
	#
	infile.readline()
	nel = int(infile.readline().split()[0])
	#
	# initialize data structure
	lr1 = [2, 2, ndim-1]
	var = [ndim, 0, 0, 0, 0]
	#
	data = exdat.exadata(ndim, nel, lr1, var)
	#
	# read geometry
	data.lims.pos[:,0] =  float('inf')
	data.lims.pos[:,1] = -float('inf')
	for iel in range(nel):
		# skip element number and group
		infile.readline()
		for idim in range(var[0]-1): # if ndim == 3 do this twice
			for jdim in range(var[0]):
				fi = infile.readline().split()
				data.elem[iel].pos[jdim,idim,0,0] = float(fi[0])
				data.elem[iel].pos[jdim,idim,0,1] = float(fi[1])
				data.elem[iel].pos[jdim,idim,1,0] = float(fi[2])
				data.elem[iel].pos[jdim,idim,1,1] = float(fi[3])
	#
	#---------------------------------------------------------------------------
	# CURVED SIDE DATA
	#---------------------------------------------------------------------------
	#
	infile.readline()
	ncurved = int(infile.readline().split()[0])
	for icurved in range(ncurved):
		line = infile.readline()
		if (nel < 1e3):
			iedge = int(line[0:3])-1
			iel   = int(line[3:6])-1
			data.elem[iel].curv[iedge] = float(line[6:16])
		elif (nel < 1e6):
			iedge = int(line[0:2])-1
			iel   = int(line[2:8])-1
			data.elem[iel].curv[iedge] = float(line[8:18])
		else:
			iedge = int(line[0:2])-1
			iel   = int(line[2:12])-1
			data.elem[iel].curv[iedge] = float(line[12:22])
	#
	#---------------------------------------------------------------------------
	# BOUNDARY CONDITIONS (skip everything)
	#---------------------------------------------------------------------------
	#
	infile.readline()
	infile.readline()
	for iel in range(nel):
		for iface in range(nface):
			infile.readline()
	#
	#---------------------------------------------------------------------------
	# FORGET ABOUT WHAT FOLLOWS
	#---------------------------------------------------------------------------	
	#
	#
	# close file
	infile.close()
	#
	# output
	return data
Exemplo n.º 3
0
def readrea(fname):
    """
	    readrea
	    A function for reading .rea files for nek5000

	    input variable:
	    fname : file name
	"""
    #
    try:
        infile = open(fname, 'r')
    except IOError as e:
        print('I/O error ({0}): {1}'.format(e.errno, e.strerror))
        #return -1
    #
    #---------------------------------------------------------------------------
    # READ HEADER (2 lines) + ndim + number of parameters
    #---------------------------------------------------------------------------
    #
    infile.readline()
    infile.readline()
    ndim = int(infile.readline().split()[0])
    npar = int(infile.readline().split()[0])
    #
    nface = 2 * ndim
    #
    #---------------------------------------------------------------------------
    # READ parameters
    #---------------------------------------------------------------------------
    #
    param = np.zeros((npar, 1))
    for ipar in range(npar):
        param[ipar] = float(infile.readline().split()[0])
    #
    #---------------------------------------------------------------------------
    # skip passive scalars
    #---------------------------------------------------------------------------
    #
    npscal = int(infile.readline().split()[0])
    for ipscal in range(npscal):
        infile.readline()
    #
    #---------------------------------------------------------------------------
    # skip logical switches
    #---------------------------------------------------------------------------
    #
    nswitch = int(infile.readline().split()[0])
    for iswitch in range(nswitch):
        infile.readline()
    #
    #---------------------------------------------------------------------------
    # skip XFAC,YFAC,XZERO,YZERO
    #---------------------------------------------------------------------------
    #
    infile.readline()
    #
    #---------------------------------------------------------------------------
    # READ MESH
    #---------------------------------------------------------------------------
    #
    infile.readline()
    nel = int(infile.readline().split()[0])
    #
    # initialize data structure
    lr1 = [2, 2, ndim - 1]
    var = [ndim, 0, 0, 0, 0]
    #
    data = exdat.exadata(ndim, nel, lr1, var)
    #
    # read geometry
    data.lims.pos[:, 0] = float('inf')
    data.lims.pos[:, 1] = -float('inf')
    for iel in range(nel):
        # skip element number and group
        infile.readline()
        for idim in range(var[0] - 1):  # if ndim == 3 do this twice
            for jdim in range(var[0]):
                fi = infile.readline().split()
                data.elem[iel].pos[jdim, idim, 0, 0] = float(fi[0])
                data.elem[iel].pos[jdim, idim, 0, 1] = float(fi[1])
                data.elem[iel].pos[jdim, idim, 1, 1] = float(fi[2])
                data.elem[iel].pos[jdim, idim, 1, 0] = float(fi[3])
    #
    #---------------------------------------------------------------------------
    # CURVED SIDE DATA
    #---------------------------------------------------------------------------
    #
    infile.readline()
    ncurved = int(infile.readline().split()[0])
    data.ncurv = ncurved
    for icurved in range(ncurved):
        line = infile.readline()
        if (nel < 1e3):
            iedge = int(line[0:3]) - 1
            iel = int(line[3:6]) - 1
            data.elem[iel].curv[iedge] = float(line[6:16])
        elif (nel < 1e6):
            iedge = int(line[0:2]) - 1
            iel = int(line[2:8]) - 1
            data.elem[iel].curv[iedge] = float(line[8:18])
        else:
            iedge = int(line[0:2]) - 1
            iel = int(line[2:12]) - 1
            data.elem[iel].curv[iedge] = float(line[12:22])
    #
    #---------------------------------------------------------------------------
    # BOUNDARY CONDITIONS
    #---------------------------------------------------------------------------
    #
    infile.readline()
    infile.readline()
    for iel in range(nel):
        for iface in range(nface):
            line = infile.readline()
            if (nel < 1e3):
                data.elem[iel].bcs[iface][0] = line[1:3].strip()
                data.elem[iel].bcs[iface][1] = int(line[4:7])
                data.elem[iel].bcs[iface][2] = int(line[7:10])
                data.elem[iel].bcs[iface][3] = float(line[10:24])
                data.elem[iel].bcs[iface][4] = float(line[24:38])
                data.elem[iel].bcs[iface][5] = float(line[38:52])
                data.elem[iel].bcs[iface][6] = float(line[52:66])
                data.elem[iel].bcs[iface][7] = float(line[66:80])
            elif (nel < 1e5):
                data.elem[iel].bcs[iface][0] = line[1:3].strip()
                data.elem[iel].bcs[iface][1] = int(line[4:10])
                data.elem[iel].bcs[iface][2] = iface + 1
                data.elem[iel].bcs[iface][3] = float(line[10:24])
                data.elem[iel].bcs[iface][4] = float(line[24:38])
                data.elem[iel].bcs[iface][5] = float(line[38:52])
                data.elem[iel].bcs[iface][6] = float(line[52:66])
                data.elem[iel].bcs[iface][7] = float(line[66:80])
            elif (nel < 1e6):
                data.elem[iel].bcs[iface][0] = line[1:3].strip()
                data.elem[iel].bcs[iface][1] = int(line[4:10])
                data.elem[iel].bcs[iface][2] = iface + 1
                data.elem[iel].bcs[iface][3] = float(line[10:24])
                data.elem[iel].bcs[iface][4] = float(line[24:38])
                data.elem[iel].bcs[iface][5] = float(line[38:52])
                data.elem[iel].bcs[iface][6] = float(line[52:66])
                data.elem[iel].bcs[iface][7] = float(line[66:80])
            else:
                data.elem[iel].bcs[iface][0] = line[1:3].strip()
                data.elem[iel].bcs[iface][1] = int(line[4:15])
                data.elem[iel].bcs[iface][2] = int(line[15:16])
                data.elem[iel].bcs[iface][3] = float(line[16:34])
                data.elem[iel].bcs[iface][4] = float(line[34:52])
                data.elem[iel].bcs[iface][5] = float(line[52:70])
                data.elem[iel].bcs[iface][6] = float(line[70:88])
                data.elem[iel].bcs[iface][7] = float(line[88:106])
    #
    #---------------------------------------------------------------------------
    # FORGET ABOUT WHAT FOLLOWS
    #---------------------------------------------------------------------------
    #
    #
    # close file
    infile.close()
    #
    # output
    return data
Exemplo n.º 4
0
def readnek(fname):
	"""
	    readnek
	    A function for reading binary data from the nek5000 binary format

	    input variable:
	    fname : file name
	"""
	#
	try:
		infile = open(fname, 'rb')
	except IOError as e:
		print('I/O error ({0}): {1}'.format(e.errno, e.strerror))
		return -1
	#
	#---------------------------------------------------------------------------
	# READ HEADER
	#---------------------------------------------------------------------------
	#
	# read header
	header = infile.read(132).split()
	#
	# get word size
	wdsz = int(header[1])
	if (wdsz == 4):
		realtype = 'f'
	elif (wdsz == 8):
		realtype = 'd'
	else:
		print('ERROR: could not interpret real type (wdsz = %i)' %(wdsz))
		return -2
	#
	# get polynomial order
	lr1 = [int(header[2]), 
	       int(header[3]),
	       int(header[4])]
	#
	# compute total number of points per element
	npel = lr1[0] * lr1[1] * lr1[2]
	#
	# get number of pysical dimensions
	ndim = 2 + (lr1[2]>1)
	#
	# get number of elements
	nel = int(header[5])
	#
	# get number of elements in the file
	nelf = int(header[6])
	#
	# get current time
	time = float(header[7])
	#
	# get current time step
	istep = int(header[8])
	#
	# get file id
	fid = int(header[9])
	#
	# get tot number of files
	nf = int(header[10])
	#
	# get variables [XUPT]
	vars = header[-1].decode('utf-8')
	var = [0 for i in range(5)]
	for v in vars:
		if (v == 'X'):
			var[0] = ndim
		elif (v == 'U'):
			var[1] = ndim
		elif (v == 'P'):
			var[2] = 1
		elif (v == 'T'):
			var[3] = 1
		elif (v == 'S'):
			var[4] = 1 # TODO: need to know how this works
	#
	# compute number of scalar fields
	nfields = sum(var)
	#
	# identify endian encoding
	etagb = infile.read(4)
	etagL = struct.unpack('<f', etagb)[0]; etagL = int(etagL*1e5)/1e5
	etagB = struct.unpack('>f', etagb)[0]; etagB = int(etagB*1e5)/1e5
	if (etagL == 6.54321):
		# print('Reading little-endian file\n')
		emode = '<'
	elif (etagB == 6.54321):
		# print('Reading big-endian file\n')
		emode = '>'
	else:
		print('ERROR: could not interpret endianness')
		return -3
	#
	# read element map for the file
	elmap = infile.read(4*nelf)
	elmap = list(struct.unpack(emode+nelf*'i', elmap))
	#
	#---------------------------------------------------------------------------
	# READ DATA
	#---------------------------------------------------------------------------
	#
	# initialize data structure
	data = exdat.exadata(ndim, nel, lr1, var)
	data.time   = time
	data.istep  = istep
	data.wdsz   = wdsz
	if (emode == '<'):
		data.endian = 'little'
	elif (emode == '>'):
		data.endian = 'big'
	#
	# read geometry
	data.lims.pos[:,0] =  float('inf')
	data.lims.pos[:,1] = -float('inf')
	for iel in elmap:
		for idim in range(var[0]): # if var[0] == 0, geometry is not read
			fi = infile.read(npel*wdsz)
			fi = list(struct.unpack(emode+npel*realtype, fi))
			ip = 0
			for iz in range(lr1[2]):
				for iy in range(lr1[1]):
					data.elem[iel-1].pos[idim,iz,iy,:] = fi[ip:ip+lr1[0]]
					ip += lr1[0]
			data.lims.pos[idim,0] = min([data.lims.pos[idim,0]]+fi)
			data.lims.pos[idim,1] = max([data.lims.pos[idim,1]]+fi)
	#
	# read velocity
	data.lims.vel[:,0] =  float('inf')
	data.lims.vel[:,1] = -float('inf')
	for iel in elmap:
		for idim in range(var[1]): # if var[1] == 0, velocity is not read
			fi = infile.read(npel*wdsz)
			fi = list(struct.unpack(emode+npel*realtype, fi))
			ip = 0
			for iz in range(lr1[2]):
				for iy in range(lr1[1]):
					data.elem[iel-1].vel[idim,iz,iy,:] = fi[ip:ip+lr1[0]]
					ip += lr1[0]
			data.lims.vel[idim,0] = min([data.lims.vel[idim,0]]+fi)
			data.lims.vel[idim,1] = max([data.lims.vel[idim,1]]+fi)
	#
	# read pressure 
	data.lims.pres[:,0] =  float('inf')
	data.lims.pres[:,1] = -float('inf')
	for iel in elmap:
		for ivar in range(var[2]): # if var[2] == 0, pressure is not read
			fi = infile.read(npel*wdsz)
			fi = list(struct.unpack(emode+npel*realtype, fi))
			ip = 0
			for iz in range(lr1[2]):
				for iy in range(lr1[1]):
					data.elem[iel-1].pres[ivar,iz,iy,:] = fi[ip:ip+lr1[0]]
					ip += lr1[0]
			data.lims.pres[ivar,0] = min([data.lims.pres[ivar,0]]+fi)
			data.lims.pres[ivar,1] = max([data.lims.pres[ivar,1]]+fi)
	#
	# read temperature
	data.lims.temp[:,0] =  float('inf')
	data.lims.temp[:,1] = -float('inf')
	for iel in elmap:
		for ivar in range(var[3]): # if var[3] == 0, temperature is not read
			fi = infile.read(npel*wdsz)
			fi = list(struct.unpack(emode+npel*realtype, fi))
			ip = 0
			for iz in range(lr1[2]):
				for iy in range(lr1[1]):
					data.elem[iel-1].temp[ivar,iz,iy,:] = fi[ip:ip+lr1[0]]
					ip += lr1[0]
			data.lims.temp[ivar,0] = min([data.lims.temp[ivar,0]]+fi)
			data.lims.temp[ivar,1] = max([data.lims.temp[ivar,1]]+fi)
	#
	# read scalar fields
	data.lims.scal[:,0] =  float('inf')
	data.lims.scal[:,1] = -float('inf')
	for iel in elmap:
		for ivar in range(var[4]): # if var[4] == 0, scalars are not read
			fi = infile.read(npel*wdsz)
			fi = list(struct.unpack(emode+npel*realtype, fi))
			ip = 0
			for iz in range(lr1[2]):
				for iy in range(lr1[1]):
					data.elem[iel-1].scal[ivar,iz,iy,:] = fi[ip:ip+lr1[0]]
					ip += lr1[0]
			data.lims.scal[ivar,0] = min([data.lims.scal[ivar,0]]+fi)
			data.lims.scal[ivar,1] = max([data.lims.scal[ivar,1]]+fi)
	#
	#
	# close file
	infile.close()
	#
	# output
	return data
Exemplo n.º 5
0
def readnek(fname):
    """
	    readnek
	    A function for reading binary data from the nek5000 binary format

	    input variable:
	    fname : file name
	"""
    #
    try:
        infile = open(fname, 'rb')
    except IOError as e:
        print('I/O error ({0}): {1}'.format(e.errno, e.strerror))
        return -1
    #
    #---------------------------------------------------------------------------
    # READ HEADER
    #---------------------------------------------------------------------------
    #
    # read header
    header = infile.read(132).split()
    #
    # get word size
    wdsz = int(header[1])
    if (wdsz == 4):
        realtype = 'f'
    elif (wdsz == 8):
        realtype = 'd'
    else:
        print('ERROR: could not interpret real type (wdsz = %i)' % (wdsz))
        return -2
    #
    # get polynomial order
    lr1 = [int(header[2]), int(header[3]), int(header[4])]
    #
    # compute total number of points per element
    npel = lr1[0] * lr1[1] * lr1[2]
    #
    # get number of pysical dimensions
    ndim = 2 + (lr1[2] > 1)
    #
    # get number of elements
    nel = int(header[5])
    #
    # get number of elements in the file
    nelf = int(header[6])
    #
    # get current time
    time = float(header[7])
    #
    # get current time step
    istep = int(header[8])
    #
    # get file id
    fid = int(header[9])
    #
    # get tot number of files
    nf = int(header[10])
    #
    # get variables [XUPT]
    vars = header[11].decode('utf-8')
    var = [0 for i in range(5)]
    for v in vars:
        if (v == 'X'):
            var[0] = ndim
        elif (v == 'U'):
            var[1] = ndim
        elif (v == 'P'):
            var[2] = 1
        elif (v == 'T'):
            var[3] = 1
        elif (v == 'S'):
            var[4] = 0  # TODO: need to know how this works
    #
    # compute number of scalar fields
    nfields = sum(var)
    #
    # identify endian encoding
    etagb = infile.read(4)
    etagL = struct.unpack('<f', etagb)[0]
    etagL = int(etagL * 1e5) / 1e5
    etagB = struct.unpack('>f', etagb)[0]
    etagB = int(etagB * 1e5) / 1e5
    if (etagL == 6.54321):
        # print('Reading little-endian file\n')
        emode = '<'
    elif (etagB == 6.54321):
        # print('Reading big-endian file\n')
        emode = '>'
    else:
        print('ERROR: could not interpret endianness')
        return -3
    #
    # read element map for the file
    elmap = infile.read(4 * nelf)
    elmap = list(struct.unpack(emode + nelf * 'i', elmap))
    #
    #---------------------------------------------------------------------------
    # READ DATA
    #---------------------------------------------------------------------------
    #
    # initialize data structure
    data = exdat.exadata(ndim, nel, lr1, var)
    data.time = time
    data.istep = istep
    data.wdsz = wdsz
    if (emode == '<'):
        data.endian = 'little'
    elif (emode == '>'):
        data.endian = 'big'
    #
    # read geometry
    data.lims.pos[:, 0] = float('inf')
    data.lims.pos[:, 1] = -float('inf')
    for iel in elmap:
        for idim in range(var[0]):  # if var[0] == 0, geometry is not read
            fi = infile.read(npel * wdsz)
            fi = list(struct.unpack(emode + npel * realtype, fi))
            ip = 0
            for iz in range(lr1[2]):
                for iy in range(lr1[1]):
                    data.elem[iel - 1].pos[idim, iz,
                                           iy, :] = fi[ip:ip + lr1[0]]
                    ip += lr1[0]
            data.lims.pos[idim, 0] = min([data.lims.pos[idim, 0]] + fi)
            data.lims.pos[idim, 1] = max([data.lims.pos[idim, 1]] + fi)
    #
    # read velocity
    data.lims.vel[:, 0] = float('inf')
    data.lims.vel[:, 1] = -float('inf')
    for iel in elmap:
        for idim in range(var[1]):  # if var[1] == 0, velocity is not read
            fi = infile.read(npel * wdsz)
            fi = list(struct.unpack(emode + npel * realtype, fi))
            ip = 0
            for iz in range(lr1[2]):
                for iy in range(lr1[1]):
                    data.elem[iel - 1].vel[idim, iz,
                                           iy, :] = fi[ip:ip + lr1[0]]
                    ip += lr1[0]
            data.lims.vel[idim, 0] = min([data.lims.vel[idim, 0]] + fi)
            data.lims.vel[idim, 1] = max([data.lims.vel[idim, 1]] + fi)
    #
    # read pressure
    data.lims.pres[:, 0] = float('inf')
    data.lims.pres[:, 1] = -float('inf')
    for iel in elmap:
        for ivar in range(var[2]):  # if var[2] == 0, pressure is not read
            fi = infile.read(npel * wdsz)
            fi = list(struct.unpack(emode + npel * realtype, fi))
            ip = 0
            for iz in range(lr1[2]):
                for iy in range(lr1[1]):
                    data.elem[iel - 1].pres[ivar, iz,
                                            iy, :] = fi[ip:ip + lr1[0]]
                    ip += lr1[0]
            data.lims.pres[ivar, 0] = min([data.lims.pres[ivar, 0]] + fi)
            data.lims.pres[ivar, 1] = max([data.lims.pres[ivar, 1]] + fi)
    #
    # read temperature
    data.lims.temp[:, 0] = float('inf')
    data.lims.temp[:, 1] = -float('inf')
    for iel in elmap:
        for ivar in range(var[3]):  # if var[3] == 0, temperature is not read
            fi = infile.read(npel * wdsz)
            fi = list(struct.unpack(emode + npel * realtype, fi))
            ip = 0
            for iz in range(lr1[2]):
                for iy in range(lr1[1]):
                    data.elem[iel - 1].temp[ivar, iz,
                                            iy, :] = fi[ip:ip + lr1[0]]
                    ip += lr1[0]
            data.lims.temp[ivar, 0] = min([data.lims.temp[ivar, 0]] + fi)
            data.lims.temp[ivar, 1] = max([data.lims.temp[ivar, 1]] + fi)
    #
    # read scalar fields
    data.lims.scal[:, 0] = float('inf')
    data.lims.scal[:, 1] = -float('inf')
    for iel in elmap:
        for ivar in range(var[4]):  # if var[4] == 0, scalars are not read
            fi = infile.read(npel * wdsz)
            fi = list(struct.unpack(emode + npel * realtype, fi))
            ip = 0
            for iz in range(lr1[2]):
                for iy in range(lr1[1]):
                    data.elem[iel - 1].scal[ivar, iz,
                                            iy, :] = fi[ip:ip + lr1[0]]
                    ip += lr1[0]
            data.lims.scal[ivar, 0] = min([data.lims.scal[ivar, 0]] + fi)
            data.lims.scal[ivar, 1] = max([data.lims.scal[ivar, 1]] + fi)
    #
    #
    # close file
    infile.close()
    #
    # output
    return data