Skip to content

Commit e73ce82

Browse files
authored
Base IO changes to eliminate excessive error messages and shift parameters to run-time configuration
This is a large cleanup of the base IO layer, primarily to reduce the spurious/misleading error messages. Changes include: - moving the IO configuration from hardwired options to config file options - removing most return codes from routines in favor of immediate aborts - adopted new error handler for those routines that do require a return code - updated user guide with the config options - updated dev guide with the interface changes
2 parents 41e25a4 + bb80737 commit e73ce82

28 files changed

+981
-2113
lines changed

components/omega/configs/Default.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ Omega:
1111
Decomp:
1212
HaloWidth: 3
1313
DecompMethod: MetisKWay
14+
IO:
15+
IOTasks: 1
16+
IOStride: 1
17+
IOBaseTask: 0
18+
IORearranger: box
19+
IODefaultFormat: NetCDF4
1420
State:
1521
NTimeLevels: 2
1622
Advection:

components/omega/doc/devGuide/IO.md

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ the IO routines within the Omega and IO namespaces.
3131
Before using any IO functions, the parallel IO system must be initialized
3232
using:
3333
```c++
34-
int Err = IO::init(Comm);
34+
IO::init(Comm);
3535
```
3636
where Comm is an MPI communicator and should in most cases be the communicator
3737
from the Omega default MachEnv (see [MachEnv](#omega-dev-mach-env)). This
@@ -44,13 +44,13 @@ As mentioned above, most I/O operations will take place within the IOStreams
4444
module, but the base IO functions can be accessed directly. To open and close
4545
files for reading/writing, use:
4646
```c++
47-
int Err = IO::openFile(FileID, Filename, Mode);
48-
Err = IO::closeFile(FileID);
47+
IO::openFile(FileID, Filename, Mode);
48+
IO::closeFile(FileID);
4949
```
5050
or
5151
```c++
52-
int Err = IO::openFile(FileID, Filename, Mode, Format, IfExists);
53-
Err = IO::closeFile(FileID);
52+
IO::openFile(FileID, Filename, Mode, Format, IfExists);
53+
IO::closeFile(FileID);
5454
```
5555
In both case, an integer FileID is assigned to the open file which is then
5656
used by all subsequent operations. The Filename is a ``std::string`` that
@@ -89,8 +89,8 @@ Once the file is open, data is read/written using one of two interfaces,
8989
depending on whether the array is decomposed across MPI tasks or not. For
9090
large decomposed arrays, the interface is:
9191
```c++
92-
int Err = IO::readArray (&Array, Size, VariableName, FileID, DecompID, VarID);
93-
int Err = IO::writeArray(&Array, Size, &FillValue, FileID, DecompID, VarID);
92+
Error Err = IO::readArray (&Array, Size, VariableName, FileID, DecompID, VarID);
93+
IO::writeArray(&Array, Size, &FillValue, FileID, DecompID, VarID);
9494
```
9595
where the pointer to the data array is passed and data is assumed to be
9696
contiguous with the full local size of the array passed as Size. The FileID is
@@ -99,21 +99,25 @@ as described below. For reading, the variable name (as a ``std::string``) is
9999
supplied and the variable ID (VarID) is returned in case it is needed for
100100
reading of variable metadata. For writing, a FillValue is supplied to fill
101101
undefined locations in an array and the variable ID must have been assigned
102-
in a prior defineVar call prior to the write as described below.
102+
in a prior defineVar call prior to the write as described below. The readArray
103+
returns an error code so that the calling routine can re-try the read. This
104+
is used in Omega to manage name changes between Omega and the earlier MPAS
105+
names.
103106
104107
Writing or reading multiple time slices (where there in an unlimited time
105108
dimension) is also possible and an additional optional Frame argument
106109
specifies the time index along that dimension that should be read/written:
107110
```c++
108-
int Err = IO::readArray (&Array, Size, VariableName, FileID, DecompID, VarID, Frame);
109-
int Err = IO::writeArray(&Array, Size, &FillValue, FileID, DecompID, VarID, Frame);
111+
Error Err = IO::readArray (&Array, Size, VariableName, FileID, DecompID,
112+
VarID, Frame);
113+
IO::writeArray(&Array, Size, &FillValue, FileID, DecompID, VarID, Frame);
110114
```
111115

112116
For arrays or scalars that are not distributed, the non-distributed variable
113117
interface must be used:
114118
```c++
115-
int Err = IO::readNDVar(&Array, VariableName, FileID, VarID);
116-
int Err = IO::writeNDVar(&Array, FileID, VarID);
119+
Error Err = IO::readNDVar(&Array, VariableName, FileID, VarID);
120+
IO::writeNDVar(&Array, FileID, VarID);
117121
```
118122
with arguments similar to the distributed array calls above. Note that
119123
when defining dimensions for these fields, the dimensions must be
@@ -124,8 +128,8 @@ Frame (index of the time slice) must be provided. In addition, a vector
124128
``std::vector<int> DimLengths`` containing the length of the non-time
125129
dimensions must be provided:
126130
```c++
127-
int Err = IO::readNDVar(&Array, VariableName, FileID, VarID, Frame, DimLengths);
128-
int Err = IO::writeNDVar(&Array, FileID, VarID, Frame, DimLengths);
131+
Error Err = IO::readNDVar(&Array, VariableName, FileID, VarID, Frame, DimLengths);
132+
IO::writeNDVar(&Array, FileID, VarID, Frame, DimLengths);
129133
```
130134
Note that the full arrays in this case are written so if any masking or
131135
pruning of points is required, it should be performed before the call.
@@ -135,24 +139,24 @@ decomposition. Both the dimensions of the array and the decomposition
135139
across tasks must be defined. For each dimension, a dimension must be
136140
defined using:
137141
```c++
138-
int Err = IO::defineDim(FileID, DimName, Length, DimID);
142+
int DimID = IO::defineDim(FileID, DimName, Length);
139143
```
140144
where FileID is the ID of an open file, the DimName is a ``std::string``
141145
with the dimension name (eg NCells, NEdges, NVertices, NVertLevels or
142146
NTracers), length is the length of the full global array and DimID is
143147
the ID assigned to this dimension. Note that for reading a file, we
144148
supply the function:
145149
```c++
146-
int Err = IO::getDimFromFile(FileID, DimName, DimID, DimLength);
150+
Error Err = IO::getDimFromFile(FileID, DimName, DimID, DimLength);
147151
```
148152
that can be used to inquire about the dimension length and retrieve the
149153
dimension ID from the file.
150154

151155
Once the dimensions are defined, the decomposition of an array must
152156
be defined using:
153157
```c++
154-
int Err = createDecomp(DecompID, IODataType, NDims, DimLengths,
155-
Size, GlobalIndx, Rearr);
158+
int DecompID = createDecomp(IODataType, NDims, DimLengths,
159+
Size, GlobalIndx, Rearr);
156160
```
157161
where DecompID is the ID assigned to the newly created decomposition,
158162
NDims is the number of dimensions for the array, DimLengths is an
@@ -196,7 +200,7 @@ for an Omega I4 data type.
196200
Now that dimensions and decompositions have been defined, a variable can
197201
be defined (this is required for writing only) using:
198202
```c++
199-
int Err = IO::defineVar(FileID, VarName, IODataType, NDims, DimIDs, VarID);
203+
int VarID = IO::defineVar(FileID, VarName, IODataType, NDims, DimIDs);
200204
```
201205
where VarID is the ID assigned to the variable, FileID is the usual ID of
202206
the data file, VarName is a ``std::string`` holding the variable name,
@@ -212,8 +216,8 @@ interfaces, but the base IO module contains interfaces for reading and
212216
writing metadata associated with either an array or the file or simulation
213217
itself. To read/write metadata, use:
214218
```c++
215-
int Err = IO::writeMeta(MetaName, MetaValue, FileID, VarID);
216-
int Err = IO::readMeta (MetaName, MetaValue, FileID, VarID);
219+
IO::writeMeta(MetaName, MetaValue, FileID, VarID);
220+
Error Err = IO::readMeta (MetaName, MetaValue, FileID, VarID);
217221
```
218222
where MetaName is a ``std::string`` holding the name of the metadata and
219223
the MetaValue is the value of the MetaData. All supported Omega data types are

components/omega/doc/userGuide/IO.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,20 @@ There are some general parameters that must be set for IO performance and
2323
formatting via the input configuration file. These are:
2424
```yaml
2525
IO:
26-
IOTasks: 1
27-
IOStride: 1
28-
IORearranger: box
29-
IODefaultFormat: NetCDF4
26+
IOTasks: 1
27+
IOStride: 1
28+
IOBaseTask: 0
29+
IORearranger: box
30+
IODefaultFormat: NetCDF4
3031
```
3132
where ``IOTasks`` is the total number of IOTasks to assign to reading
3233
and writing. The default is 1 (serial IO) for safety but this number
3334
should be set appropriately for the underlying hardware. A simple
3435
starting point might be one IOTask per node or socket. The ``IOStride``
3536
is set to spread the IOTasks across the total number of MPI tasks so
36-
that every IOStride task (starting with the root task) is an IOTask.
37-
The product of IOTasks and IOStride should equal the total number of
38-
MPI Tasks.
37+
that every IOStride task (starting with the root task IOBaseTask) is an
38+
IOTask. The product of IOTasks and IOStride should equal the total number
39+
of MPI Tasks.
3940
4041
When using parallel IO, the data must be rearranged to match the IO task
4142
decomposition. There are two algorithms for rearranging data available

0 commit comments

Comments
 (0)