-
Notifications
You must be signed in to change notification settings - Fork 80
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #431 from tjotaha/catalyst_api_2_structured_blocks
Catalyst API 2 IOSS Full Implementation
- Loading branch information
Showing
26 changed files
with
4,769 additions
and
263 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
201 changes: 201 additions & 0 deletions
201
packages/seacas/libraries/ioss/src/catalyst/Iocatalyst_CatalystLogging.C
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,201 @@ | ||
// Copyright(C) 1999-2021 National Technology & Engineering Solutions | ||
// of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with | ||
// NTESS, the U.S. Government retains certain rights in this software. | ||
// | ||
// See packages/seacas/LICENSE for details | ||
|
||
#include <Ioss_Utils.h> | ||
#include <fstream> | ||
#include <iostream> | ||
#include <time.h> | ||
#include <catalyst/Iocatalyst_CatalystLogging.h> | ||
|
||
namespace Iocatalyst { | ||
|
||
CatalystLogging::CatalystLogging() { initializeDefaults(); } | ||
|
||
void CatalystLogging::initializeDefaults() | ||
{ | ||
catalystLoggingEnabled = false; | ||
logFileName = getDefaultLogFileName(); | ||
logOutputDirectoryPath = getDefaultLogOutputDirectoryPath(); | ||
properties = nullptr; | ||
} | ||
|
||
void CatalystLogging::setProperties(const Ioss::PropertyManager *my_properties) | ||
{ | ||
initializeDefaults(); | ||
this->properties = my_properties; | ||
if (this->properties) { | ||
if (this->properties->exists(enabledProp)) { | ||
catalystLoggingEnabled = this->properties->get(enabledProp).get_int(); | ||
} | ||
if (this->properties->exists(fileNameProp)) { | ||
logFileName = this->properties->get(fileNameProp).get_string(); | ||
} | ||
if (this->properties->exists(directoryPathProp)) { | ||
logOutputDirectoryPath = this->properties->get(directoryPathProp).get_string(); | ||
} | ||
} | ||
} | ||
|
||
std::vector<std::string> CatalystLogging::writeToLogFile() | ||
{ | ||
std::vector<std::string> logLine; | ||
if (properties) { | ||
std::fstream logFile; | ||
logFile.open(getLogFilePath(), std::ios::out | std::ios::app); | ||
if (!logFile) { | ||
std::ostringstream errmsg; | ||
errmsg << "Unable to open Catalyst log file: " << getLogFilePath() << "\n"; | ||
IOSS_ERROR(errmsg); | ||
} | ||
else { | ||
std::vector<std::string> headers = getLogFileHeaders(); | ||
if (isLogFileEmpty()) { | ||
writeVectorWithDelimeter(logFile, headers, getDelimeter()); | ||
} | ||
logLine = getLogOutputFromProps(headers); | ||
writeVectorWithDelimeter(logFile, logLine, getDelimeter()); | ||
logFile.close(); | ||
} | ||
} | ||
return logLine; | ||
} | ||
|
||
std::vector<std::string> CatalystLogging::getLogFileHeaders() | ||
{ | ||
std::vector<std::string> headers; | ||
if (properties) { | ||
Ioss::NameList names = properties->describe(); | ||
for (auto &name : names) { | ||
if (isCatalystLoggingProp(name)) { | ||
if (isSupportedPropType(name) && !isReservedPropName(name)) { | ||
headers.push_back(getHeaderNameFromPropName(name)); | ||
} | ||
} | ||
} | ||
} | ||
std::sort(headers.begin(), headers.end()); | ||
return headers; | ||
} | ||
|
||
bool CatalystLogging::isLogFileEmpty() | ||
{ | ||
std::ifstream logFile; | ||
logFile.open(getLogFilePath()); | ||
bool result = logFile.peek() == std::ifstream::traits_type::eof(); | ||
logFile.close(); | ||
return result; | ||
} | ||
|
||
void CatalystLogging::writeVectorWithDelimeter(std::fstream &file, | ||
const std::vector<std::string> &string_vector, | ||
char delimeter) | ||
{ | ||
if (string_vector.empty()) { | ||
return; | ||
} | ||
for (size_t i = 0; i < string_vector.size(); i++) { | ||
file << string_vector[i]; | ||
if (i < string_vector.size() - 1) { | ||
file << delimeter; | ||
} | ||
} | ||
file << "\n"; | ||
} | ||
|
||
std::vector<std::vector<std::string>> CatalystLogging::readLogFile() | ||
{ | ||
return readLogFile(getLogFilePath()); | ||
} | ||
|
||
std::vector<std::vector<std::string>> CatalystLogging::readLogFile(const std::string &logFilePath) | ||
{ | ||
std::vector<std::vector<std::string>> result; | ||
std::fstream logFile; | ||
logFile.open(logFilePath); | ||
if (logFile) { | ||
std::string line; | ||
while (getline(logFile, line)) { | ||
result.push_back( | ||
CatalystLogging::splitStringWithDelimeter(line, CatalystLogging::getDelimeter())); | ||
} | ||
logFile.close(); | ||
} | ||
return result; | ||
} | ||
|
||
std::vector<std::string> CatalystLogging::splitStringWithDelimeter(const std::string &input, | ||
char delimeter) | ||
{ | ||
std::string buffer = ""; | ||
std::vector<std::string> result; | ||
enum ParseState { UNQUOTED, QUOTED, QUOTEDQUOTE }; | ||
ParseState state = UNQUOTED; | ||
for (size_t i = 0; i < input.size(); i++) { | ||
switch (state) { | ||
case UNQUOTED: | ||
if (input[i] == delimeter) { | ||
result.push_back(buffer); | ||
buffer.clear(); | ||
} | ||
else if (input[i] == '"') { | ||
state = QUOTED; | ||
buffer += "\""; | ||
} | ||
else { | ||
buffer += input[i]; | ||
} | ||
break; | ||
case QUOTED: | ||
if (input[i] == '"') { | ||
state = UNQUOTED; | ||
buffer += "\""; | ||
} | ||
else { | ||
buffer += input[i]; | ||
} | ||
break; | ||
case QUOTEDQUOTE: | ||
if (input[i] == delimeter) { | ||
state = UNQUOTED; | ||
result.push_back(buffer); | ||
buffer.clear(); | ||
} | ||
else if (input[i] == '"') { | ||
state = QUOTED; | ||
buffer += "\""; | ||
} | ||
else { | ||
state = UNQUOTED; | ||
buffer += input[i]; | ||
} | ||
break; | ||
} | ||
} | ||
if (!buffer.empty()) { | ||
result.push_back(buffer); | ||
} | ||
return result; | ||
} | ||
|
||
std::vector<std::string> CatalystLogging::getLogOutputFromProps(std::vector<std::string> &headers) | ||
{ | ||
std::vector<std::string> logOutput; | ||
if (properties) { | ||
for (auto &header : headers) { | ||
std::string propName = getPropNameFromHeaderName(header); | ||
Ioss::Property prop = properties->get(propName); | ||
switch (prop.get_type()) { | ||
case Ioss::Property::REAL: logOutput.push_back(std::to_string(prop.get_real())); break; | ||
case Ioss::Property::INTEGER: logOutput.push_back(std::to_string(prop.get_int())); break; | ||
case Ioss::Property::STRING: logOutput.push_back(prop.get_string()); break; | ||
default: logOutput.push_back("Unsupported property type for " + propName); | ||
} | ||
} | ||
} | ||
return logOutput; | ||
} | ||
|
||
} // namespace Iocatalyst |
144 changes: 144 additions & 0 deletions
144
packages/seacas/libraries/ioss/src/catalyst/Iocatalyst_CatalystLogging.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
// Copyright(C) 1999-2021 National Technology & Engineering Solutions | ||
// of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with | ||
// NTESS, the U.S. Government retains certain rights in this software. | ||
// | ||
// See packages/seacas/LICENSE for details | ||
|
||
#ifndef IOSS_IOVS_CATALYST_LOGGING_H | ||
#define IOSS_IOVS_CATALYST_LOGGING_H | ||
|
||
#include "iocatalyst_export.h" | ||
|
||
#include <Ioss_CodeTypes.h> | ||
#include <Ioss_PropertyManager.h> | ||
#include <string> | ||
#include <vector> | ||
|
||
namespace Iocatalyst { | ||
|
||
class IOCATALYST_EXPORT CatalystLogging | ||
{ | ||
// Enables Catalyst log output from IOSS when Catalyst CGNS or | ||
// Exodus IOSS databases are created. Rank 0 of the application | ||
// writes an entry to a CSV (comma separted value) log file upon | ||
// IOSS database creation. Log output is controlled through | ||
// IOSS properties. IOSS properties that control logging must be | ||
// prepened with the string "CATALYST_LOGGING_". | ||
// | ||
// There are three reserved IOSS property names for logging. | ||
// | ||
// "CATALYST_LOGGING_ENABLED" : enables Catalyst log output when passed | ||
// an argument of "true or a non-zero integer". Default is "false". | ||
// | ||
// "CATALYST_LOGGING_FILE_NAME" : string specifying the log file output | ||
// name. Default is "catalyst_log.csv". | ||
// | ||
// "CATALYST_LOGGING_OUTPUT_DIRECTORY_PATH" : string specifying an absolute | ||
// or relative path to the log file. Default is current working directory, "". | ||
// | ||
// Real, Integer, and String IOSS properties prepended by the string | ||
// "CATALYST_LOGGING_" are used to specify output for the log line in the CSV | ||
// output log file. The logger will remove the prepended string and create | ||
// a header line in the CSV file sorted by name. | ||
// | ||
// Example application code creating a Catalyst IOSS database with logging: | ||
// | ||
// Ioss::PropertyManager *p; | ||
// p->add(Ioss::Property("CATALYST_LOGGING_ENABLED", true)); | ||
// p->add(Ioss::Property("CATALYST_LOGGING_FILE_NAME", "app_log.csv")); | ||
// p->add(Ioss::Property("CATALYST_LOGGING_OUTPUT_DIRECTORY_PATH, "/etc/logs/")); | ||
// p->add(Ioss::Property("CATALYST_LOGGING_NUM_RANKS", getNumRanks())); | ||
// p->add(Ioss::Property("CATALYST_LOGGING_DATE", getDate())); | ||
// p->add(Ioss::Property("CATALYST_LOGGING_USER", getUser())); | ||
// p->add(Ioss::Property("CATALYST_LOGGING_APP_NAME", getAppName())); | ||
// | ||
// The IOSS properties contained in *p are passed to the IOSS | ||
// Ioss::IOFactory::create(). A log entry will be appended to the log file | ||
// at "/etc/logs/app_log_.csv" every time a Catalyst database is created by | ||
// a running instance of the application. The CSV log file will have the following | ||
// format, which can be easily read by Python. | ||
// | ||
// APP_NAME,DATE,NUM_RANKS,USER | ||
// goo,November 10th,16,joe | ||
// bar,December 12th,8,stan | ||
// | ||
// If an IOSS string property contains commas, these need to be quoted. | ||
// | ||
// p->add(Ioss::Property("CATALYST_LOGGING_ADDRESS", "\"123 main, PO 4, ND, 34422\"")) | ||
// | ||
// Quotes inside strings must also be quoted. | ||
// | ||
// p->add(Ioss::Property("CATALYST_LOGGING_QUOTE", "I am \"\"Dave\"\"")) | ||
|
||
public: | ||
CatalystLogging(); | ||
|
||
bool isCatalystLoggingON() { return catalystLoggingEnabled; }; | ||
std::string getLogFileName() { return logFileName; }; | ||
static std::string getDefaultLogFileName() { return "catalyst_log.csv"; }; | ||
std::string getLogOutputDirectoryPath() { return logOutputDirectoryPath; }; | ||
std::string getDefaultLogOutputDirectoryPath() { return ""; }; | ||
void setProperties(const Ioss::PropertyManager *properties); | ||
std::vector<std::string> getLogFileHeaders(); | ||
std::vector<std::string> writeToLogFile(); | ||
std::vector<std::vector<std::string>> readLogFile(); | ||
static std::vector<std::vector<std::string>> readLogFile(const std::string &logFilePath); | ||
std::string getLogFilePath() | ||
{ | ||
if (logOutputDirectoryPath.empty()) { | ||
return getLogFileName(); | ||
} | ||
else { | ||
std::string opath = getLogOutputDirectoryPath(); | ||
if (opath.back() != '/') { | ||
opath += '/'; | ||
} | ||
return opath + getLogFileName(); | ||
} | ||
}; | ||
static char getDelimeter() { return ','; }; | ||
bool isCatalystLoggingProp(std::string &propName) { return propName.rfind(logPrefix, 0) == 0; }; | ||
std::string getHeaderNameFromPropName(std::string &propName) | ||
{ | ||
return propName.substr(logPrefix.length()); | ||
}; | ||
std::string getPropNameFromHeaderName(std::string &headerName) | ||
{ | ||
return logPrefix + headerName; | ||
}; | ||
bool isReservedPropName(std::string &propName) | ||
{ | ||
return propName == enabledProp || propName == fileNameProp || propName == directoryPathProp; | ||
}; | ||
bool isSupportedPropType(std::string &propName) | ||
{ | ||
bool retVal = false; | ||
if (properties && properties->exists(propName)) { | ||
Ioss::Property::BasicType type = properties->get(propName).get_type(); | ||
retVal = (type == Ioss::Property::INTEGER || type == Ioss::Property::REAL || | ||
type == Ioss::Property::STRING); | ||
} | ||
return retVal; | ||
}; | ||
|
||
private: | ||
bool catalystLoggingEnabled; | ||
std::string logFileName; | ||
std::string logOutputDirectoryPath; | ||
const Ioss::PropertyManager *properties; | ||
std::string logPrefix = "CATALYST_LOGGING_"; | ||
std::string enabledProp = logPrefix + "ENABLED"; | ||
std::string fileNameProp = logPrefix + "FILE_NAME"; | ||
std::string directoryPathProp = logPrefix + "OUTPUT_DIRECTORY_PATH"; | ||
void initializeDefaults(); | ||
void writeVectorWithDelimeter(std::fstream &file, const std::vector<std::string> &string_vector, | ||
char delimeter); | ||
static std::vector<std::string> splitStringWithDelimeter(const std::string &input, | ||
char delimeter); | ||
bool isLogFileEmpty(); | ||
std::vector<std::string> getLogOutputFromProps(std::vector<std::string> &headers); | ||
}; | ||
|
||
} // namespace Iocatalyst | ||
|
||
#endif |
Oops, something went wrong.