Example #1
0
def readre2(fname):
    """A function for reading .re2 files for nek5000

	Parameters
	----------
	fname : str
		file name
	"""
    #
    try:
        infile = open(fname, 'rb')
    except OSError as e:
        logger.critical(f'I/O error ({e.errno}): {e.strerror}')
        return -1
    # the header for re2 files is 80 ASCII bytes, something like
    # #v002    18669  2    18669 this is the hdr                                      %
    header = infile.read(80).split()
    nel = int(header[1])
    ndim = int(header[2])
    # always double precision
    wdsz = 8
    realtype = 'd'

    # detect endianness
    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):
        logger.debug('Reading little-endian file\n')
        emode = '<'
        endian = 'little'
    elif (etagB == 6.54321):
        logger.debug('Reading big-endian file\n')
        emode = '>'
        endian = 'big'
    else:
        logger.error('Could not interpret endianness')
        return -3
    #
    # there are no GLL points here, only quad/hex vertices
    lr1 = [2, 2, ndim - 1]
    npel = 2**ndim
    # the file only contains geometry
    var = [ndim, 0, 0, 0, 0]
    # allocate structure
    data = exdat.exadata(ndim, nel, lr1, var, 1)
    #
    # some metadata
    data.wdsz = wdsz
    data.endian = endian
    #
    # read the whole geometry into a buffer
    # for some reason each element is prefixed with 8 bytes of zeros, it's not clear to me why.
    # This is the reason for the +1 here, then the first number is ignored.
    buf = infile.read((ndim * npel + 1) * wdsz * nel)
    elem_shape = [ndim, ndim - 1, 2, 2]  # nvar, lz, ly, lx
    for (iel, el) in enumerate(data.elem):
        fi = np.frombuffer(buf,
                           dtype=emode + realtype,
                           count=ndim * npel + 1,
                           offset=(ndim * npel + 1) * wdsz * iel)
        # the data is stored in the following order (2D|3D):
        # x1, x2, x4, x3; | x5, x6, x8, x7;
        # y1, y2, y4, y3; | y5, y6, y8, y7;
        # ----------------
        # z1, z2, z4, z3; z5, z6, z8, z7;
        # where 1-8 is the ordering of the points in memory
        for idim in range(ndim):  # x, y, [z]
            for iz in range(
                    ndim - 1
            ):  # this does only one iteration in 2D, and in 3D does one iteration for 1-4 and one for 5-8
                el.pos[idim, iz, 0, 0] = fi[npel * idim + 4 * iz + 1]
                el.pos[idim, iz, 0, 1] = fi[npel * idim + 4 * iz + 2]
                el.pos[idim, iz, 1, 1] = fi[npel * idim + 4 * iz + 3]
                el.pos[idim, iz, 1, 0] = fi[npel * idim + 4 * iz + 4]
    #
    # read curved sides
    # the number of curved sides is stored as a double,
    # then each curved side is 64 bytes:
    # iel iface p1 p2 p3 p4 p5 ctype
    # where p1-5 are f64 parameters and ctype is the type of curvature in ASCII
    ncparam = 8
    buf = infile.read(wdsz)
    ncurv = int(np.frombuffer(buf)[0])
    logger.debug(f'Found {ncurv} curved sides')
    data.ncurv = ncurv
    buf = infile.read(wdsz * (ncparam * ncurv))
    for icurv in range(ncurv):
        # interpret the data
        curv = np.frombuffer(buf,
                             dtype=emode + realtype,
                             count=ncparam,
                             offset=icurv * ncparam * wdsz)
        iel = int(curv[0]) - 1
        iedge = int(curv[1]) - 1
        cparams = curv[2:7]
        # select only the first byte, because it turns out the later bytes may contain garbage.
        # typically, it's b'C\x00\x00\x00\x00\x00\x00\x00' or b'C\x00\x00\x00\x00\x00\xe0?'.
        # AFAIK the curvature types are always one character long anyway.
        ctype = curv[7].tobytes()[:1].decode('utf-8')
        # fill in the data structure
        data.elem[iel].curv[iedge, :] = cparams
        data.elem[iel].ccurv[iedge] = ctype
    #
    # read boundary conditions
    # there can be more than one field, and we won't know until we'vre reached the end
    nbcparam = 8
    buf = infile.read(wdsz)
    ifield = 0
    while buf != b'':
        # the data is initialized with one BC field, we might need to allocate another
        if ifield > 0:
            data.nbc = data.nbc + 1
            for el in data.elem:
                empty_bcs = np.zeros(el.bcs[:1, :].shape, dtype=el.bcs.dtype)
                el.bcs = np.concatenate((el.bcs, empty_bcs))
        nbclines = int(np.frombuffer(buf)[0])
        logger.debug(
            f'Found {nbclines} external boundary conditions for field {ifield}'
        )
        buf = infile.read(wdsz * (nbcparam * nbclines))
        for ibc in range(nbclines):
            # interpret the data
            bc = np.frombuffer(buf,
                               dtype=emode + realtype,
                               count=nbcparam,
                               offset=ibc * nbcparam * wdsz)
            iel = int(bc[0]) - 1
            iface = int(bc[1]) - 1
            bcparams = bc[2:7]
            bctype = bc[7].tobytes().decode(
                'utf-8').rstrip()  # remove trailing spaces
            # fill in the data structure
            data.elem[iel].bcs[ifield, iface][0] = bctype
            data.elem[iel].bcs[ifield, iface][1] = iel + 1
            data.elem[iel].bcs[ifield, iface][2] = iface + 1
            for ipar in range(5):
                data.elem[iel].bcs[ifield, iface][3 + ipar] = bcparams[ipar]
        ifield = ifield + 1
        # try reading the number of conditions in the next field
        buf = infile.read(wdsz)
    infile.close()
    return data
Example #2
0
def readnek(fname):
    """A function for reading binary data from the nek5000 binary format

	Parameters
	----------
	fname : str
		file name
	"""
    #
    try:
        infile = open(fname, 'rb')
    except OSError as e:
        logger.critical(f'I/O error ({e.errno}): {e.strerror}')
        return -1
    #
    #---------------------------------------------------------------------------
    # READ HEADER
    #---------------------------------------------------------------------------
    #
    # read header
    header = infile.read(132).split()
    logger.debug('Header: {}'.format(b' '.join(header).decode('utf-8')))

    # get word size: single or double precision
    wdsz = int(header[1])
    if (wdsz == 4):
        realtype = 'f'
    elif (wdsz == 8):
        realtype = 'd'
    else:
        logger.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 physical 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 [XUPTS[01-99]]
    variables = header[11].decode('utf-8')
    logger.debug(f"Variables: {variables}")
    var = [0 for i in range(5)]
    for v in variables:
        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'):
            # For example: variables = 'XS44'
            index_s = variables.index('S')
            nb_scalars = int(variables[index_s + 1:])
            var[4] = nb_scalars
    #
    # 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):
        logger.debug('Reading little-endian file\n')
        emode = '<'
    elif (etagB == 6.54321):
        logger.debug('Reading big-endian file\n')
        emode = '>'
    else:
        logger.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, 0)
    data.time = time
    data.istep = istep
    data.wdsz = wdsz
    data.elmap = np.array(elmap, dtype=np.int32)
    if (emode == '<'):
        data.endian = 'little'
    elif (emode == '>'):
        data.endian = 'big'
    #
    def read_file_into_data(data_var, index_var):
        """Read binary file into an array attribute of ``data.elem``"""
        fi = infile.read(npel * wdsz)
        fi = np.frombuffer(fi, dtype=emode + realtype, count=npel)

        # Replace elem array in-place with
        # array read from file after reshaping as
        elem_shape = lr1[::-1]  # lz, ly, lx
        data_var[index_var, ...] = fi.reshape(elem_shape)

    #
    # read geometry
    for iel in elmap:
        el = data.elem[iel - 1]
        for idim in range(var[0]):  # if var[0] == 0, geometry is not read
            read_file_into_data(el.pos, idim)
    #
    # read velocity
    for iel in elmap:
        el = data.elem[iel - 1]
        for idim in range(var[1]):  # if var[1] == 0, velocity is not read
            read_file_into_data(el.vel, idim)
    #
    # read pressure
    for iel in elmap:
        el = data.elem[iel - 1]
        for ivar in range(var[2]):  # if var[2] == 0, pressure is not read
            read_file_into_data(el.pres, ivar)
    #
    # read temperature
    for iel in elmap:
        el = data.elem[iel - 1]
        for ivar in range(var[3]):  # if var[3] == 0, temperature is not read
            read_file_into_data(el.temp, ivar)
    #
    # read scalar fields
    #
    # NOTE: This is not a bug!
    # Unlike other variables, scalars are in the outer loop and elements
    # are in the inner loop
    #
    for ivar in range(var[4]):  # if var[4] == 0, scalars are not read
        for iel in elmap:
            el = data.elem[iel - 1]
            read_file_into_data(el.scal, ivar)
    #
    #
    # close file
    infile.close()
    #
    # output
    return data
Example #3
0
def readrea(fname):
    """A function for reading .rea files for nek5000

	Parameters
	----------
	fname : str
		file name
	"""
    #
    try:
        infile = open(fname)
    except OSError as e:
        logger.critical(f'I/O error ({e.errno}): {e.strerror}')
        #return -1
    #
    #---------------------------------------------------------------------------
    # count the number of boundary conditions
    # (it's too dangerous to infer it from the header)
    #---------------------------------------------------------------------------
    #
    nbc = 0
    for line in infile:
        line_split = line.split()
        if 'BOUNDARY' in line_split[2:] and not 'NO' in line_split:
            nbc = nbc + 1

    infile.seek(0)
    #
    #---------------------------------------------------------------------------
    # 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_data = int(infile.readline().split()[0])
    for ipscal in range(npscal_data):
        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, nbc)
    #
    # read geometry
    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][0] = float(line[6:20])
            data.elem[iel].curv[iedge][1] = float(line[20:34])
            data.elem[iel].curv[iedge][2] = float(line[34:48])
            data.elem[iel].curv[iedge][3] = float(line[48:62])
            data.elem[iel].curv[iedge][4] = float(line[62:76])
            data.elem[iel].ccurv[iedge] = line[76:79].split()[0]
        elif (nel < 1e6):
            iedge = int(line[0:2]) - 1
            iel = int(line[2:8]) - 1
            data.elem[iel].curv[iedge][0] = float(line[8:22])
            data.elem[iel].curv[iedge][1] = float(line[22:36])
            data.elem[iel].curv[iedge][2] = float(line[36:50])
            data.elem[iel].curv[iedge][3] = float(line[50:64])
            data.elem[iel].curv[iedge][4] = float(line[64:78])
            data.elem[iel].ccurv[iedge] = line[78:81].split()[0]
        else:
            iedge = int(line[0:2]) - 1
            iel = int(line[2:12]) - 1
            data.elem[iel].curv[iedge][0] = float(line[12:26])
            data.elem[iel].curv[iedge][1] = float(line[26:40])
            data.elem[iel].curv[iedge][2] = float(line[40:54])
            data.elem[iel].curv[iedge][3] = float(line[54:68])
            data.elem[iel].curv[iedge][4] = float(line[68:82])
            data.elem[iel].ccurv[iedge] = line[82:85].split()[0]
    #
    #---------------------------------------------------------------------------
    # BOUNDARY CONDITIONS
    #---------------------------------------------------------------------------
    #
    infile.readline()  # ***** BOUNDARY CONDITIONS *****
    for ibc in range(nbc):
        infile.readline(
        )  # ***** FLUID   BOUNDARY CONDITIONS ***** [or similar]
        for iel in range(nel):
            for iface in range(nface):
                line = infile.readline()
                if (nel < 1e3):
                    data.elem[iel].bcs[ibc, iface][0] = line[1:3].strip()
                    data.elem[iel].bcs[ibc, iface][1] = int(line[4:7])
                    data.elem[iel].bcs[ibc, iface][2] = int(line[7:10])
                    data.elem[iel].bcs[ibc, iface][3] = float(line[10:24])
                    data.elem[iel].bcs[ibc, iface][4] = float(line[24:38])
                    data.elem[iel].bcs[ibc, iface][5] = float(line[38:52])
                    data.elem[iel].bcs[ibc, iface][6] = float(line[52:66])
                    data.elem[iel].bcs[ibc, iface][7] = float(line[66:80])
                elif (nel < 1e6):
                    data.elem[iel].bcs[ibc, iface][0] = line[1:3].strip()
                    data.elem[iel].bcs[ibc, iface][1] = iel + 1
                    data.elem[iel].bcs[ibc, iface][2] = iface + 1
                    data.elem[iel].bcs[ibc, iface][3] = float(line[10:24])
                    data.elem[iel].bcs[ibc, iface][4] = float(line[24:38])
                    data.elem[iel].bcs[ibc, iface][5] = float(line[38:52])
                    data.elem[iel].bcs[ibc, iface][6] = float(line[52:66])
                    data.elem[iel].bcs[ibc, iface][7] = float(line[66:80])
                else:
                    data.elem[iel].bcs[ibc, iface][0] = line[1:3].strip()
                    data.elem[iel].bcs[ibc, iface][1] = int(line[4:15])
                    data.elem[iel].bcs[ibc, iface][2] = int(line[15:16])
                    data.elem[iel].bcs[ibc, iface][3] = float(line[16:34])
                    data.elem[iel].bcs[ibc, iface][4] = float(line[34:52])
                    data.elem[iel].bcs[ibc, iface][5] = float(line[52:70])
                    data.elem[iel].bcs[ibc, iface][6] = float(line[70:88])
                    data.elem[iel].bcs[ibc, iface][7] = float(line[88:106])
                # ignore some invalid internal 'E' conditions.
                # They are typically written this way by re2torea and Nek5000 ignores them.
                if data.elem[iel].bcs[ibc,
                                      iface][0] == 'E' and data.elem[iel].bcs[
                                          ibc, iface][3] == 0.:
                    data.elem[iel].bcs[ibc, iface][0] = ''
                    for j in range(1, 8):
                        data.elem[iel].bcs[ibc, iface][j] = 0
        ibc = ibc + 1
    #
    #---------------------------------------------------------------------------
    # FORGET ABOUT WHAT FOLLOWS
    #---------------------------------------------------------------------------
    #
    #
    # close file
    infile.close()
    #
    # output
    return data
Example #4
0
def readdns(fname):
    """A function for reading binary data from the SIMSON binary format

    Parameters
    ----------
    fname : str
            file name
    """
    #
    try:
        infile = open(fname, "rb")
    except OSError as e:
        print(f"I/O error ({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)  # noqa: F841  # required for reading
        #
        # 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