Skip to content

Commit

Permalink
Merge pull request #164 from philipwjones/omega/io-non-distrib
Browse files Browse the repository at this point in the history
Adds capability to read/write non-distributed variables in Omega IO
  • Loading branch information
philipwjones authored Nov 25, 2024
2 parents c6eeedb + bad0704 commit 871ea4f
Show file tree
Hide file tree
Showing 4 changed files with 600 additions and 301 deletions.
19 changes: 16 additions & 3 deletions components/omega/doc/devGuide/IO.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,9 @@ with the defaults for each being ``IO::FmtDefault``, and
NetCDF4. Earlier NetCDF formats should be avoided, but are provided in
case an input file is in an earlier format.
Once the file is open, data is read/written using:
Once the file is open, data is read/written using one of two interfaces,
depending on whether the array is decomposed across MPI tasks or not. For
large decomposed arrays, the interface is:
```c++
int Err = IO::readArray (&Array, Size, VariableName, FileID, DecompID, VarID);
int Err = IO::writeArray(&Array, Size, &FillValue, FileID, DecompID, VarID);
Expand All @@ -99,6 +101,16 @@ reading of variable metadata. For writing, a FillValue is supplied to fill
undefined locations in an array and the variable ID must have been assigned
in a prior defineVar call prior to the write as described below.

For arrays or scalars that are not distributed, the non-distributed variable
interface must be used:
```c++
int Err = IO::readNDVar(&Array, VariableName, FileID, VarID);
int Err = IO::writeNDVar(&Array, FileID, VarID);
```
with arguments similar to the distributed array calls above. Note that
when defining dimensions for these fields, the dimensions must be
non-distributed. For scalars, the number of dimensions should be zero.

The IO subsystem must know how the data is laid out in the parallel
decomposition. Both the dimensions of the array and the decomposition
across tasks must be defined. For each dimension, a dimension must be
Expand Down Expand Up @@ -171,8 +183,9 @@ where VarID is the ID assigned to the variable, FileID is the usual ID of
the data file, VarName is a ``std::string`` holding the variable name,
IODataType is the data type described above, NDims are the number of dimensions,
and DimIDs are an integer ``std::vector`` holding the dimension IDs for each
dimension. The variable ID can then be used in all IO calls related to this
variable.
dimension. For scalar variables, NDims should be set to zero and a null pointer
should be used in place of the DimID argument. Once defined, the variable ID
is used in all IO calls related to this variable.

In addition to data in a file, we can also read and write metadata. As with
the data itself, metadata is typically managed by the IOStreams and Metadata
Expand Down
49 changes: 49 additions & 0 deletions components/omega/src/base/IO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,34 @@ int readArray(void *Array, // [out] array to be read

} // End IOReadArray

//------------------------------------------------------------------------------
// Reads a non-distributed variable. Uses a void pointer for generic interface.
// All arrays are assumed to be in contiguous storage.
int readNDVar(void *Variable, // [out] array to be read
const std::string &VarName, // [in] name of variable to read
int FileID, // [in] ID of open file to read from
int &VarID // [out] Id assigned to variable for later use
) {

int Err = 0; // default return code

// Find variable ID from file
Err = PIOc_inq_varid(FileID, VarName.c_str(), &VarID);
if (Err != PIO_NOERR) {
LOG_ERROR("IO::readArray: Error finding varid for variable {}", VarName);
return Err;
}

// PIO Read array call to read the distributed array
Err = PIOc_get_var(FileID, VarID, Variable);
if (Err != PIO_NOERR)
LOG_ERROR("IO::readNDVar: Error in SCORPIO get_var for variable {}",
VarName);

return Err;

} // End IOReadNDVar

//------------------------------------------------------------------------------
// Writes a distributed array. This generic interface uses void pointers.
// All arrays are assumed to be in contiguous storage and the variable
Expand Down Expand Up @@ -751,6 +779,27 @@ int writeArray(void *Array, // [in] array to be written

} // end writeArray

//------------------------------------------------------------------------------
// Writes a non-distributed variable. This generic interface uses void pointers.
// All arrays are assumed to be in contiguous storage and the variable
// must have a valid ID assigned by the defineVar function.

int writeNDVar(void *Variable, // [in] variable to be written
int FileID, // [in] ID of open file to write to
int VarID // [in] variable ID assigned by defineVar
) {
int Err = 0;

Err = PIOc_put_var(FileID, VarID, Variable);
if (Err != PIO_NOERR) {
LOG_ERROR("Error in PIO writing non-distributed variable");
return Err;
}

return Err;

} // end writeNDVar

//------------------------------------------------------------------------------

} // end namespace IO
Expand Down
20 changes: 20 additions & 0 deletions components/omega/src/base/IO.h
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,17 @@ int readArray(void *Array, ///< [out] array to be read
int &VarID ///< [out] variable ID in case metadata needed
);

/// Reads a non-distributed variable. We use a void pointer here to create
/// a generic interface for all types. Arrays are assumed to be in contiguous
/// storage so the arrays of any dimension are treated as a 1-d array with
/// the full local size. The routine returns the variable as well as the id
/// assigned to the variable should that be needed later.
int readNDVar(void *Variable, ///< [out] variable to be read
const std::string &VarName, ///< [in] name of variable to read
int FileID, ///< [in] ID of open file to read from
int &VarID ///< [out] variable ID in case metadata needed
);

/// Writes a distributed array. A void pointer is used to create a generic
/// interface. Arrays are assumed to be in contiguous storage and the variable
/// must have a valid ID assigned by the defineVar function. A void pointer
Expand All @@ -287,6 +298,15 @@ int writeArray(void *Array, ///< [in] array to be written
int VarID ///< [in] variable ID assigned by defineVar
);

/// Writes a non-distributed variable. A void pointer is used for a generic
/// interface. Arrays are assumed to be in contiguous storage and the variable
/// must have a valid ID assigned by the defineVar function. A void pointer
/// to a scalar FillValue is also required to fill missing values.
int writeNDVar(void *Variable, ///< [in] variable to be written
int FileID, ///< [in] ID of open file to write to
int VarID ///< [in] variable ID assigned by defineVar
);

} // end namespace IO
} // end namespace OMEGA

Expand Down
Loading

0 comments on commit 871ea4f

Please sign in to comment.