3.3. Writing Datasets
[3. Quick Start for Model Developers]

This section is intended to be a quick overview of reading and writing data sets. For more detailed function descriptions see section 4.11. Setting up a model to write datasets to an XMDF file requires more information than is needed for reading geometry. Part of the reason more information is required is because more of the file organization is created by the model. Another source of complexity is that datasets can be written to either new or existing files.

Individual datasets are grouped in special folders that hold all the datasets for a specific geometry. These folders are called multi-dataset groups. Multi-dataset groups may or may not be in the same file as the geometry. In Figure 6 the multi-data group for the mesh has the path 2DMeshModule/mesh/Datasets. Multi-dataset groups store the GUID of the geometry to which they belong. Within a multi-dataset group, generic groups may be used to organize the data sets. In Figure 6 the folder named Solution under the multi-dataset group is an example of using generic groups to organize data sets. These generic groups would be especially useful for stochastic simulations and could be used to organize the datasets belonging to individual runs.

When writing datasets using XMDF the following items of information are necessary:

Inside XMDF there is a function to make it easier for models to set up the paths to begin writing data sets. This function takes for arguments the five items mentioned above and returns the File ID and the ID of the group to begin writing datasets to. This function should always be used to setup a model to begin writing data sets using XMDF because it ensures that everything is setup regardless of whether or not the file or the required paths exist. The function is named xfSetupToWriteDatasets.

Once the file id and group id to start writing datasets has been obtained from xfSetupToWriteDatasets, the following steps are used to add each dataset to the file:

  1. Create the dataset using xfCreateScalarDataset or xfCreateVectorDataset
  2. If desired, use the function xfDatasetReftime to specify the reference time for the dataset. The reference time is the Julian date for time zero for the dataset. Each timestep is treated as an offset from this reference time.
  3. For each timestep, set the data using xfWriteScalarTimestep. If necessary, use xfWriteActivityTimestep to set active element information for each timestep.
  4. Close the dataset using xfCloseGroup.
  5. When all datasets are closed, close the group that all the datasets are written to using xfCloseGroup and close the file using xfCloseFile.

Often steps 1 and 2 will be done together for all of the datasets to be written at the beginning of the model execution. Then when timesteps are computed, step 3 will be performed for each dataset. When all the timesteps are completed steps 4 and 5 are used to close the file and all the resources.

Example:
The example below has a function to write a scalar dataset to an XMDF file. The arguments to the function are those included in the xfSetupToWriteDatasets, a compression level (-1 for none). The number of times, time values, number of values per time step, and the values for the dataset are stored in file globals. The function follows the XMDF convention of using negative values to indicate errors.

C/C++
static int    fg_nTimes;
static double *fg_Times;
static int    fg_nValues;
static float  **fg_Values;
 
int WriteDataset (const char *a_Filename, 
                  const char *a_MultiDatasetsGroupPath,
                  const char *a_SpatialDataObjectGuid,
                  int a_OverwriteOption,
                  int a_Compression)
{
  xid      xFileId, xDsetsId, xScalarId;
  int      iTimestep, iActive;
  double   dTime;
  int      status;
 
  status = xfSetupToWriteDatasets(a_Filename, a_MultiDatasetsGroupPath,
               a_SpatialDataObjectGuid, a_OverwriteOption, &xFileId, &xDsetsId);
  if (status < 0) {
    printf("Error initializing files to write datasets.");
    return status;
  }
 
  // Create the scalar A dataset group
  status = xfCreateScalarDataset(xDsetsId, "Concentration",
                                 "mg/L", TS_HOURS, a_Compression,
                                 &xScalarId);
  if (status < 0) {
    printf("Error creating scalar datasets.");
    xfCloseGroup(xDsetsId);
    xfCloseFile(xFileId);
    return FALSE;
  }
 
  // Loop through timesteps adding them to the file
  for (iTimestep = 0; iTimestep < fg_nTimes; iTimestep++) {
    // We will have an 0.5 hour timestep
    dTime = fg_Times[iTimestep];
 
    // write the dataset array values
    status = xfWriteScalarTimestep(xScalarAId, dTime, fg_nValues,
                                   fg_Values[iTimestep]);
    if (status < 0) {
      xfCloseGroup(xScalarId);
      xfCloseGroup(xDsetsId);
      xfCloseFile(xFileId);
      return status;
    }
  }
 
  // close the dataset
  xfCloseGroup(xScalarId);
  xfCloseGroup(xDsetsId);
  xfCloseFile(xFileId);
 
  return FALSE;
} // tdWriteScalarA

FORTRAN
INTEGER         fg_nTimes;
REAL(DOUBLE), ALLOCATABLE ::  fg_Times(:)
INTEGER         fg_nValues
REAL, ALLOCATABLE ::  fg_Values(:,:)
 
SUBROUTINE WRITE_DATASET (a_Filename, 
                          a_MultiDatasetsGroupPath,
                          a_SpatialDataOjbectGuid,
                          a_OverwriteOption,
                          a_Compression, error)
  CHARACTER(LEN=*), INTENT(IN) :: a_Filename, a_MultiDatasetsGroupPath
  CHARACTER(LEN=*), INTENT(IN) :: a_SpatialDataObjectGuid
  INTEGER, INTENT(IN)          :: a_OverwriteOption, a_Compression
  INTEGER, INTENT(OUT)         :: error
  INTEGER(HID_T)      xFileId, xDsetsId, xScalarId
  INTEGER      iTimestep, iActive
  REAL(DOUBLE) dTime
  REAL, ALLOCATABLE ::         Values(:)
 
  call XF_SETUP_TO_WRITE_DATASETS(a_Filename, a_MultiDatasestsGroupPath, &
                                  a_SpatialDataObjectGuid, a_OverwriteOption, &
                                  xFileId, xScalarId, error)
 
  if (error .LT. 0) then
    WRITE(*,*) 'Error initializing files to write datasets.'
    return
  endif
 
  ! Create the scalar A dataset group
  call XF_CREATE_SCALAR_DATASET(xDsetsId, 'Concentration', 'mg/L', &
              TS_HOURS, a_Compression, xScalarAd, error)
  if (error .LT. 0) then
      ! close the dataset
    call XF_CLOSE_GROUP(xScalarId, error)
    call XF_CLOSE_GROUP(xDsetsId, error)
    call XF_CLOSE_FILE(xFileId, error)
    return 
  endif
 
  ! allocate the values for an individual timestep
  allocate (Values(fg_nValues))  
 
  ! Loop through timesteps adding them to the file
  do iTimestep = 1, fg_nTimes
    ! We will have an 0.5 hour timestep
    dTime = fg_Times(iTimestep)
 
    do iVal = 1, fg_nValues
      Values(iVal) = fg_Values(iTimestep, iVal)
    enddo
 
    ! write the dataset array values
    call XF_WRITE_SCALAR_TIMESTEP(xScalarId, dTime, fg_nValues, &
                                  Values, error)
    if (error .LT. 0) then
      deallocate (Values)
      call XF_CLOSE_GROUP(xScalarAId, error)
      call XF_CLOSE_GROUP(xDsetsId, error)
      call XF_CLOSE_FILE(xFileId, error)
      return
    endif
  enddo
 
  deallocate (Values)
 
  ! close the dataset
  call XF_CLOSE_GROUP(xScalarAId, error)
  call XF_CLOSE_GROUP(xDsetsId, error)
  call XF_CLOSE_FILE(xFileId, error)
 
  return
END SUBROUTINE

Generated on Wed Jun 2 11:55:32 2010 for XMDF by  doxygen 1.5.6