MfixReader User Guide

For MfixReader 3.0 released April 14, 2004

Pittsburgh Supercomputing Center
4400 Fifth Avenue, Pittsburgh, PA 15213
www.psc.edu -> (SC)2 -> (SC)2 Projects > MFIX Support


This user guide describes how the MfixReader library can be used to read MFIX datasets. This library is not a complete program but can be used to create programs that need to read MFIX data. Please send questions and comments to eschenbe@psc.edu

Table of Contents

1. Introduction
2. Usage
3. Managing and Opening Instances
4. Setting Parameters
5. Requesting Metadata
6. Requesting Coordinates
7. Requesting Data

1. Introduction

This library of subroutines, written in the C language, can read MFIX data sets. It uses the MFIX format version, embedded in the restart file, so that it can correctly read many versions of MFIX files.


Data is not read into memory when a dataset is first opened. Instead, only basic metadata (data about the data) is gathered at that time. Later, the application may make any number of "requests" where each request returns one or more variables at a single time step. Other requests return the coordinates and lists of available variables.


A modest number of integrity checks are made to detect corrupt datasets. For example, if the final array of data for a variable is incomplete, the library quietly ignores that array; all previous arrays (i.e., previous time steps) are available.


See sc-2.psc.edu/mfix/index.php to download the library.


Most of the code for the library is in the file MfixReader.c. Additional code for the conversion of binary data is in the file libbio.c. The file kLib.c contains general support for C routines including a special debugging system. Each of these files has an associated header file that defines variables, enumerated types and data structures. All are included in the download.


Please contact Kent Eschenberg with any questions or comments at eschenbe@psc.edu.

2. Usage

An application that uses the MfixReader library will proceed in stages. At each stage, the library will provide information that can help the application (and the user, if the application is interactive) decide what to do next. For example, the libary can provide a list of variables after the dataset is opened but before any data is read.


An application may also wish to work with several sets of data. The library supports this by internally creating multiple "instances" of its information about a dataset. Each call to the library to return metadata, coordinates, or variables must include the "handle" (a simple integer) that identifies the instance. Each instance retains knowledge of the files, byte offsets and other metadata for each open dataset. The operations on one instance are completely independent of operations on other instances.


As an example, let's imagine an interactive application that wishes to compare a user-selected variable from two MFIX datasets. The application could use the MfixReader library functions in this order:



The above example could use the library in many other ways to accomplish the same result.


Many of the routines in this library will return pointers to arrays. The application does not need to provide these arrays, and should never modify the arrays in any way. The library will free the memory used by the arrays at the appropriate time (i.e., at the close or destroy operation).

3. Managing and Opening Instances

These four routines create and destroy instances of the reader, and open and close datasets. Note that most parameters that affect how a dataset is opened (next section) must be set after an instance is created but before it is opened.

3.1 Create An Instance

int MfixReaderCreate(
 int *handle
)


Create an instance. The integer pointed to by handle will be set to a semi-random number. This handle must be used in all future references to this instance.

3.2 Destroy An Instance

int MfixReaderDestroy(
 int *handle
)


Eliminates an instance and frees associated memory. The handle is set to 0.

3.3 Open An Instance

int MfixReaderOpen(
 int handle
)


Opens the dataset referenced by the handle and gathers metadata. This includes reading the restart file and reading just enough of the data files to discover the number of time steps in each.

Most of the parameters that affect how a dataset is read must be set before this routine is used.


A modest number of memory arrays are also allocated for passing data back to the application. Later, if needed, additional memory arrays may be created.

3.4 Close An Instance

int MfixReaderClose(
 int handle
)


Closes the dataset and frees associated memory. The memory freed here includes the potentially large arrays used to return data to the application.

4. Setting Parameters

Most of these routines must be called after a reader instance has been created but before the dataset has been opened. The one exception is MfixReaderSetTimeRules which can be called repeatedly at any time.

4.1 Set Filename

int MfixReaderSetFileName(
 int handle,
 char *name
)


Sets the name of a file in the dataset. May include path information. The file extension in this name is ignored; instead, the program tries all file extensions (.res, .sp1, .sp2, ...).

For each extension, the program also tries various combinations of upper and lower case.

For example, let's say that the filename was set to be myData.sp1. The program then begins with the restart file, trying each file on the following list until one is found:



The same process is applied to all the other file extensions.

4.2 Set Record Length

int MfixReaderSetRecordLength(
 int handle,
 int length
)


Sets the record length of the MFIX files, in bytes. The default is 512.

4.3 Set Endian Type

int MfixReaderSetInputEndian(
 int handle,
 int endian
)


Sets the endian type of the binary data in the MFIX files where the choices are 0 (small endian) or 1 (big endian, the default).

4.4 Set Space Filter

int MfixReaderSetLocationFilter(
 int handle,
 int skip[6]
)


Sets the number of cells at the ends of the coordinate axes that will be discarded. There are 6 parameters, one for the 2 ends of each of the 3 axes. Note that this option select the number of cells, not vertices, to be discarded.


When the MFIX coordinate system is cylindrical, some border cells must be removed using this filter for sensible results. The first cell in X (radius) as well as the first and last cells along Z (angle) should be removed. This corresponds to a skip array of [1,0,0,0,1,1].


When this parameter is not set, the default for each value is 0. In other words, by default, no cells are eliminated.

4.5 Set Data Time Tolerance

int MfixReaderSetDataTimeTolerance(
 int handle,
 float tol
)


Sets the data time tolerance. The default is 0.000001.

The times in each MFIX data file should be monotonically increasing, i.e., each time in the file time2 should be greater than or equal to the previous time in the file time1. The actual test is


 time1 - tolerance <= time2


If this test fails, the reader will issue an error message and quit.

However, when an MFIX simulation is restarted, the times in a data file after the restart may repeat one or more times already stored in the file. For such a data file to be accepted, the tolerance should be set to a larger number. A value equal to 3 times the internal MFIX time step, for example, will often be sufficent.

4.6 Set Time Rules

int MfixReaderSetTimeRules(
 int handle,
 float tolerance,
 enum MfixReaderExtrapolation extrapRule,
 enum MfixReaderInterpolation interpRule
)


Sets the rules used for missing times. The defaults are 0.000001, MRE_nearest_any and MRI_linear, in that order.


The program attempts to provide requested variables at the requested time. Some variables, however, may not be given in the data file at a time "equal" to the requested time. Two times are considered equal if they are closer than the time tolerance set by this routine.


When a variable is not in the data file at the requested time, it is said to be "missing" at that time. Two rules control the action taken when a variable is missing. The interpolation rule is applied when the missing time falls between two other times for that variable. Otherwise, the extrapolation rule is applied.


The interpolation rule can be set to one of these values defined in the reader's header file:


MRI_never
return no data (not recommended)
MRI_nearest_any
use data from the time nearest to the current time
MRI_nearest_prev
like MRI_nearest_any but limited to times before the current time
MRI_nearest_next
like MRI_nearest_any but limited to times after the current time
MRI_linear
estimate the value using the two nearest times and linear interpolation


The extrapolation rule can be set to one of these values defined in the reader's header file:


MRE_never
return no data (not recommended)
MRE_nearest_any
use data from the time nearest to the current time

5. Requesting Metadata

An application should obtain metadata rather than making assumptions about the nature of an MFIX dataset. With proper use of the metadata, an application will continue to work correctly even as the MFIX datasets develop and change.

5.1 Overall Metadata

Once a dataset has been opened, metadata that applies to the entire dataset can be obtained using


int MfixReaderGetInfo(
 int handle,
 int *nInfo,
 struct MfixReaderInfo **info
)


The information is returned as an array of data structures where the array is of length nInfo.

5.1.1 Dataset Metadata Structure

Each item of metadata is returned using a structure designed to accomodate a wide range of information:


struct MfixReaderInfo {
 char *keyword;
 enum MfixReaderDataType dataType;
 int nValues;
 int *iValue;
 float *fValue;
 char **cValue;
}


Each item contains one type of data indicated by the parameter dataType which can be



One of the three data pointers will point to an array of the appropriate type. The other pointers will be zero.


Each metadata item is returned in an array of length nValues. Currently, all arrays are of length 1, 2 or 3 but that may change in the future. Note that items that are one value are still returned as an array (of length 1).

5.1.2 Keywords

The current version of the MFIX reader library returns information for the following keywords. Future versions of the library may extend this list.

dims
An array of 3 integers giving the size of the data arrays after the space filter, i.e., the size of the arrays returned when data is requested. These integers will always be at least one.
dimsoriginal
An array of 3 integers giving the size of the data arrays before the space filter
ntimes
An integer giving the number of time steps. Equal to the maximum of the number of time steps for each variable.
timespan
An array of 2 floats giving the first and last time, in seconds. Calculated using all variables.
date
An array of 3 integers giving the month, day and year when the dataset was created.
time
An array of 3 integers giving the hour, minute and seconds when the dataset was created.
version
An array of 2 integers giving the major and minor MFIX dataset version.
name
An array containing pointers to two strings containing the two run names provided in the restart file.
type
A string giving the type of MFIX run.
description
A string describing the MFIX run.
units
A string giving the units (example: CGS).
coord
An integer indicating the coordinate system: MRC_cartesian (1) or MRC_cylindrical (2).
ngasspecies
An integer giving the number of gas species.
nsolidphases
An integer giving the number of solid phases.
nsolidspecies
An integer array of length nsolidphases where each element of the array gives the number of solid species for one solid phase.
nscalars
An integer giving the number of scalars
nreactionrates
An integer giving the number of reaction rates

5.2 Metadata for Variables

Metadata for every variable in any open dataset can be obtained using


int MfixReaderGetDataChoices(
 int handle,
 int *nChoices,
 struct MfixReaderDataChoice **choices
)


The information is returned as an array of data structures where the array is of length nChoices.

The metadata for each variable is returned using a structure :


struct struct MfixReaderDataChoice {
 char *variableName;
 char *variableDesc;
 char *primaryName;
 int primaryCount
 char *secondaryName;
 int *secondaryCount;
 char *units;
 enum MfixReaderDataType dataType;
 enum MfixReaderAttach attach;
 int veclen;
 int nTimes;
 float *times;
 int available;
}


The current variable names for an MFIX dataset, along with their variants (if any), are:



Note that the exact name of a variable must be used when making a request for data (see section 8).


The descriptions are 1 to 4 word phrases such as "void fraction" and "solid species mass fraction."


The primary and secondary variant names are "species" and/or "phase". A variable may have no variants; only primary variants; or both. A variable will never have only secondary variants.


When a variant is not used, the pointer to the variant name will be null and the associated count will be zero. Otherwise, the count is the number of variants. Note that secondaryCount is an array of integers where each element of the array is the number of secondary variants for the corresponding primary variant.


The data type can be



All MFIX data is cell-based; however, for generality, the type of data attachment can be



The vector length, veclen, for MFIX data is always 1 or 3.


The number of times, nTimes, applies to that specific variable and excludes time steps where the full data array is not found in the file (i.e., where the program exited prematurely).


The available flag is somewhat redundant but can be used to quickly determine whether a particular variable (and its associated file) was found when the dataset was opened. When set to 0 (not available), certain other data (e.g., the number of time steps) are of course meaningless.

6. Requesting Coordinates

The coordinates, after the space filter has been applied, can be obtained for any open dataset using


int MfixReaderGetCoordinates(
 int handle,
 enum MfixReaderFormat format,
 char **units,
 int *dims[3],
 float **xyz
)


The format can be used to select between two sets of coordinates:

MRF_cell or MRF_node_average
coordinates for the standard grid are returned
MRF_node_center
coordinates for a grid with vertices at the centers of the cells are returned

The grid for the cell centers will be smaller by 1 along each axis than the standard grid. Therefore, the cell-center grid should not be requested when the standard grid is less than 2 cells along any coordinate.


The returned array xyz contains the cartesian coordinates where the components of the vertex (X,Y,Z) change fastest and Z changes slowest. If the original MFIX coordinate system is cylindrical, it is converted to cartesian.

7. Requesting Data

One or more variables at a single time in any open dataset can be obtained using


int MfixReaderGetData(
 int handle,
 float dataTime,
 int nRequests,
 struct MfixReaderDataRequest *requests
)


The time is given in seconds. As described elsewhere, variables not available in the file for the requested time are generated using the interpolation or extrapolation rules and parameters.


The number of variables obtained by a particular call to this routine is set by nRequests. Requests for variables that are not available do not cause errors.


During any particular call to this routine, the requested variable(s) are read from the files in the optimum order, not necessarily in the order in which they are requested. For example, if two requested variables are stored in the same file, the variable found first in the file will be read first. This means that slightly better performance will result if a single call to this routine is used instead of multiple calls, for a given time step.

7.1 Request Structure

The following data structure is used to both make the request and to return the results:


struct MfixReaderDataRequest {
 char *variableName;
 int primaryNum;
 int secondaryNum;
 int component;
 enum MfixReaderFormat format;
 char *units;
 enum MfixReaderDataType dataType;
 enum MfixReaderAttach attach;
 int veclen;
 int interpolated;
 float dataTime[2];
 int *dims;
 int *dataInt;
 float *dataFloat;
}


The first five items in this structure define the data request and are not changed by the routine. The remaining items are information returned by this routine and will be zero when a variable cannot be found.


The units, dataType, and attach parameters returned in the structure are copies of the metadata for the variable.

7.2 Variable Selection

The variable name in the request must be an exact match to an available variable.


The request includes the primary and secondary variant indices, primaryNum and secondaryNum. If the variable has no variants, these are ignored. Otherwise, they should be a zero-based index into the list of variants for the variable. A negative variant index is treated as if it was zero.


If the variable uses primary variants (even if there is only 1), the requested primary variant index must be in range (i.e., it must be no more than one less than the number of variants). Otherwise, the variable is considered to be unavailable.


If the variable also uses secondary variants (even if there is only 1), the requested secondary variant index must be in range; otherwise, the variable is considered to be unavailable.

7.3 Vectors

The requested component is ignored if the variable is a scalar. Otherwise, this value indicates the component index (0, 1 or 2). All components are returned if this value is negative or greater than 2. The length of the vector is returned in veclen.

7.4 Format Selection

The format parameter selects one of three data formats:

MRF_cell
cell data defined for the standard grid
MRF_node_average
node data defined for the standard grid
MRF_node_center
node data defined for the cell-centered grid

Node data for the standard grid is calculated by taking the average of the cell values around the node. Cells are included in the average only if they are of type 1 (fluid).


When the MFIX coordinate system is cylindrical, the average correctly uses cells on both sides of the cut plane (at the zero angle) and around the central axis. Often, general graphics libraries fail to convert cylindrical MFIX cell data to the node data required for, say, isosurfaces.


Node data for the cell-centered grid is actually the original cell data - only the grid is changed. This data must be used, of course, with the cell-centerd coordinates obtained using MfixReaderGetCoordinates.


The greatest advantage of cell-centered option will occur when the visualization method requires node data (e.g., an isosurface) and the variable changes significantly from position to position. In this case, averaging can cause a noticeable change in the result (see Figure 7.1).


The main disadvantage in using a cell-centered grid is that it stops half a cell from the boundary of the standard grid (see Figure 7.2).

7.5 Time Selection

If the data that is returned was interpolated, the interpolated flag is 1 and the two times used for the interpolation are returned in dataTime.


When interpolation is not used, the flag is 0 and the times returned are both set to the time used.


When a time that is compatible with the requested time and the time rules cannot be found, the variable is considered to be unavailable. This can happen if, for example, the extrapolation rule is set to "never" and the requested time is greater than the greatest time for which the variable is available.

7.6 Order of the Data

The data is stored in the returned arrays in this order:




Figure 7.1   Isosurfaces using averaged node
data (left) and cell-centered node data (right).

Figure 7.2   Cell-centered grid stops half a cell
from the boundary of the standard grid.

© Pittsburgh Supercomputing Center (PSC), SuperComputing Science Consortium