Skip to content

Commit

Permalink
Merge pull request #184 from philipwjones/omega/stream-init-fix
Browse files Browse the repository at this point in the history
Added return codes to IOStream for better managing missing/skipped streams
  • Loading branch information
philipwjones authored Dec 11, 2024
2 parents 97f45f8 + 6f51885 commit ee5333c
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 49 deletions.
75 changes: 38 additions & 37 deletions components/omega/src/infra/IOStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -240,17 +240,18 @@ int IOStream::read(
Metadata &ReqMetadata, // [inout] global metadata requested from file
bool ForceRead // [in] optional: read even if not time
) {
int Err = 0; // default return code
int Err = Success; // default return code

// Retrieve stream by name and make sure it exists
auto StreamItr = AllStreams.find(StreamName);
if (StreamItr != AllStreams.end()) {
// Stream found, call the read function
std::shared_ptr<IOStream> ThisStream = StreamItr->second;
Err = ThisStream->readStream(ModelClock, ReqMetadata, ForceRead);
} else { // Stream not found, return error
LOG_ERROR("Unable to read stream {}. Stream not defined", StreamName);
Err = 1;
} else { // Stream not found
// The response to this case must be determined by the calling routine
// since a missing stream might be expected in some cases
Err = Fail;
}

return Err;
Expand All @@ -264,7 +265,7 @@ int IOStream::write(
const Clock *ModelClock, // [in] Model clock needed for time stamps
bool ForceWrite // [in] optional: write even if not time
) {
int Err = 0; // default return code
int Err = Success; // default return code

// Retrieve stream by name and make sure it exists
auto StreamItr = AllStreams.find(StreamName);
Expand All @@ -275,7 +276,7 @@ int IOStream::write(
} else {
// Stream not found, return error
LOG_ERROR("Unable to write stream {}. Stream not defined", StreamName);
Err = 1;
Err = Fail;
}

return Err;
Expand Down Expand Up @@ -303,7 +304,7 @@ int IOStream::writeAll(
}

// check for errors
if (Err1 != 0) {
if (Err1 == Fail) {
++Err;
LOG_ERROR("writeAll error in stream {}", StreamName);
}
Expand Down Expand Up @@ -2314,24 +2315,24 @@ int IOStream::readStream(
Metadata &ReqMetadata, // [inout] global metadata to extract from file
bool ForceRead // [in] optional: read even if not time
) {
int Err = 0; // default return code

int Err; // return code

// First check that this is an input stream
if (Mode != IO::ModeRead) {
LOG_ERROR("IOStream read: cannot read stream defined as output stream");
Err = 1;
return Err;
return Fail;
}

// If it is not time to read, return
if (!ForceRead) {
if (!MyAlarm.isRinging() and !OnStartup)
return Err;
return Skipped;
if (UseStartEnd) { // If time outside interval, return
if (!StartAlarm.isRinging())
return Err;
return Skipped;
if (EndAlarm.isRinging())
return Err;
return Skipped;
}
}

Expand Down Expand Up @@ -2365,7 +2366,7 @@ int IOStream::readStream(
ExistAction);
if (Err != 0) {
LOG_ERROR("Error opening file {} for input", InFileName);
return Err;
return Fail;
}

// Read any requested global metadata
Expand Down Expand Up @@ -2405,12 +2406,12 @@ int IOStream::readStream(
} else {
LOG_ERROR("Metadata read failed: unknown data type for {} in file {}",
MetaName, InFileName);
ErrRead = 2;
ErrRead = Fail;
}

if (ErrRead != 0) {
LOG_ERROR("Error reading metadata {} from file {}", InFileName);
return ErrRead;
return Fail;
}
} // end loop over requested metadata

Expand All @@ -2419,7 +2420,7 @@ int IOStream::readStream(
Err = defineAllDims(InFileID, AllDimIDs);
if (Err != 0) {
LOG_ERROR("Error defining dimensions for file {} ", InFileName);
return Err;
return Fail;
}

// For each field in the contents, define field and read field data
Expand All @@ -2435,7 +2436,7 @@ int IOStream::readStream(
if (Err != 0) {
LOG_ERROR("Error reading field data for Field {} in Stream {}",
FieldName, Name);
return Err;
return Fail;
}

} // End loop over field list
Expand All @@ -2444,13 +2445,13 @@ int IOStream::readStream(
Err = IO::closeFile(InFileID);
if (Err != 0) {
LOG_ERROR("Error closing input file {}", InFileName);
return Err;
return Fail;
}

LOG_INFO("Successfully read stream {} from file {}", Name, InFileName);

// End of routine - return
return Err;
return Success;

} // End read

Expand All @@ -2463,25 +2464,25 @@ int IOStream::writeStream(
bool FinalCall // [in] Optional flag if called from finalize
) {

int Err = 0; // default return code
int Err = Success; // default return code

// First check that this is an output stream
if (Mode != IO::ModeWrite) {
LOG_ERROR("IOStream write: cannot write stream defined as input stream");
Err = 1;
return Err;
return Fail;
}

// If it is not time to write, return
if (!ForceWrite) {
bool StartupShutdown = OnStartup or (OnShutdown and FinalCall);
if (!MyAlarm.isRinging() and !StartupShutdown)
return Err;
return Skipped;
if (UseStartEnd) { // If time outside interval, return
if (!StartAlarm.isRinging())
return Err;
return Skipped;
if (EndAlarm.isRinging())
return Err;
return Skipped;
}
}

Expand Down Expand Up @@ -2520,15 +2521,15 @@ int IOStream::writeStream(
if (Err != 0) {
LOG_ERROR("IOStream::write: error opening file {} for output",
OutFileName);
return Err;
return Fail;
}

// Write Metadata for global metadata (Code and Simulation)
// Always add current simulation time to Simulation metadata
Err = writeFieldMeta(CodeMeta, OutFileID, IO::GlobalID);
if (Err != 0) {
LOG_ERROR("Error writing Code Metadata to file {}", OutFileName);
return Err;
return Fail;
}
std::shared_ptr<Field> SimField = Field::get(SimMeta);
// Add the simulation time - if it was added previously, remove and
Expand All @@ -2538,20 +2539,20 @@ int IOStream::writeStream(
Err = SimField->addMetadata("SimulationTime", SimTimeStr);
if (Err != 0) {
LOG_ERROR("Error adding current sim time to output {}", OutFileName);
return Err;
return Fail;
}
Err = writeFieldMeta(SimMeta, OutFileID, IO::GlobalID);
if (Err != 0) {
LOG_ERROR("Error writing Simulation Metadata to file {}", OutFileName);
return Err;
return Fail;
}

// Assign dimension IDs for all defined dimensions
std::map<std::string, int> AllDimIDs;
Err = defineAllDims(OutFileID, AllDimIDs);
if (Err != 0) {
LOG_ERROR("Error defined dimensions for file {}", OutFileName);
return Err;
return Fail;
}

// Define each field and write field metadata
Expand All @@ -2574,7 +2575,7 @@ int IOStream::writeStream(
if (Err != 0) {
LOG_ERROR("Error retrieving dimension names for Field {}",
FieldName);
return Err;
return Fail;
}
}
// If this is a time-dependent field, we insert the unlimited time
Expand All @@ -2599,7 +2600,7 @@ int IOStream::writeStream(
FieldID);
if (Err != 0) {
LOG_ERROR("Error defining field {} in stream {}", FieldName, Name);
return Err;
return Fail;
}
FieldIDs[FieldName] = FieldID;

Expand All @@ -2608,15 +2609,15 @@ int IOStream::writeStream(
if (Err != 0) {
LOG_ERROR("Error writing field metadata for field {} in stream {}",
FieldName, Name);
return Err;
return Fail;
}
}

// End define mode
Err = IO::endDefinePhase(OutFileID);
if (Err != 0) {
LOG_ERROR("Error ending define phase for stream {}", Name);
return Err;
return Fail;
}

// Now write data arrays for all fields in contents
Expand All @@ -2632,15 +2633,15 @@ int IOStream::writeStream(
if (Err != 0) {
LOG_ERROR("Error writing field data for Field {} in Stream {}",
FieldName, Name);
return Err;
return Fail;
}
}

// Close output file
Err = IO::closeFile(OutFileID);
if (Err != 0) {
LOG_ERROR("Error closing output file {}", OutFileName);
return Err;
return Fail;
}

// If using pointer files for this stream, write the filename to the pointer
Expand All @@ -2654,7 +2655,7 @@ int IOStream::writeStream(
LOG_INFO("Successfully wrote stream {} to file {}", Name, OutFileName);

// End of routine - return
return Err;
return Success;

} // end writeStream

Expand Down
7 changes: 7 additions & 0 deletions components/omega/src/infra/IOStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,13 @@ class IOStream {
);

public:
//---------------------------------------------------------------------------
/// Return codes - these will be removed once Error Handler is completed

static constexpr int Success{0}; ///< Successful read/write completion
static constexpr int Skipped{1}; ///< Normal early return (eg if not time)
static constexpr int Fail{2}; ///< Fail

//---------------------------------------------------------------------------
/// Default empty constructor
IOStream();
Expand Down
19 changes: 10 additions & 9 deletions components/omega/src/ocn/OceanInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,22 +174,23 @@ int initOmegaModules(MPI_Comm Comm) {
std::string SimTimeStr = " "; // create SimulationTime metadata
std::shared_ptr<Field> SimField = Field::get(SimMeta);
SimField->addMetadata("SimulationTime", SimTimeStr);
int Err1 = IOStream::Success;
int Err2 = IOStream::Success;

// read from initial state if this is starting a new simulation
Metadata ReqMeta; // no requested metadata for initial state
Err = IOStream::read("InitialState", ModelClock, ReqMeta);
if (Err != 0) {
LOG_CRITICAL("Error reading the initial state file");
return Err;
}
Err1 = IOStream::read("InitialState", ModelClock, ReqMeta);

// read restart if starting from restart
SimTimeStr = " ";
ReqMeta["SimulationTime"] = SimTimeStr;
Err = IOStream::read("RestartRead", ModelClock, ReqMeta);
if (Err != 0) {
LOG_CRITICAL("Error reading the restart file");
return Err;
Err2 = IOStream::read("RestartRead", ModelClock, ReqMeta);

// One of the above two streams must be successful to initialize the
// state and other fields used in the model
if (Err1 != IOStream::Success and Err2 != IOStream::Success) {
LOG_CRITICAL("Error initializing ocean variables from input streams");
return Err1 + Err2;
}

// If reading from restart, reset the current time to the input time
Expand Down
4 changes: 2 additions & 2 deletions components/omega/test/infra/IOStreamTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ int main(int argc, char **argv) {
// Read restart file for initial temperature and salinity data
Metadata ReqMetadata; // leave empty for now - no required metadata
Err1 = IOStream::read("InitialState", ModelClock, ReqMetadata);
TestEval("Read restart file", Err1, ErrRef, Err);
TestEval("Read restart file", Err1, IOStream::Success, Err);

// Overwrite salinity array with values associated with global cell
// ID to test proper indexing of IO
Expand Down Expand Up @@ -230,7 +230,7 @@ int main(int argc, char **argv) {
std::this_thread::sleep_for(std::chrono::seconds(5));
bool ForceRead = true;
Err1 = IOStream::read("RestartRead", ModelClock, ReqMetadata, ForceRead);
TestEval("Restart force read", Err1, ErrRef, Err);
TestEval("Restart force read", Err1, IOStream::Success, Err);

Err1 = 0;
auto DataReducer = Kokkos::Sum<I4>(Err1);
Expand Down
2 changes: 1 addition & 1 deletion components/omega/test/ocn/StateTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ int initStateTest() {
// Read the state variables from the initial state stream
Metadata ReqMeta; // no global metadata needed for init state read
Err = IOStream::read("InitialState", ModelClock, ReqMeta);
if (!StreamsValid) {
if (Err != IOStream::Success) {
LOG_CRITICAL("ocnInit: Error reading initial state from stream");
return Err;
}
Expand Down

0 comments on commit ee5333c

Please sign in to comment.