Skip to content

Commit

Permalink
Some further improved reorganization in IoData
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastiangrimberg committed Jul 25, 2023
1 parent 2af80e0 commit 52b410a
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 84 deletions.
168 changes: 88 additions & 80 deletions palace/utils/iodata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
#include <functional>
#include <iostream>
#include <regex>
#include <sstream>
#include <stack>
#include <string>
#include <string_view>
#include <mfem.hpp>
#include <nlohmann/json.hpp>
Expand All @@ -18,82 +20,12 @@
namespace palace
{

using json = nlohmann::json;

IoData::IoData(const char *filename, bool print) : Lc(1.0), tc(1.0), init(false)
namespace
{
// Open configuration file and preprocess: strip whitespace, comments, and expand integer
// ranges.
std::stringstream buffer;
PreprocessFile(filename, buffer);

// Parse the configuration file. Use a callback function to detect and throw errors for
// duplicate keys.
json config;
std::stack<std::set<json>> parse_stack;
json::parser_callback_t check_duplicate_keys =
[&](int, json::parse_event_t event, json &parsed)
{
switch (event)
{
case json::parse_event_t::object_start:
parse_stack.push(std::set<json>());
break;
case json::parse_event_t::object_end:
parse_stack.pop();
break;
case json::parse_event_t::key:
{
const auto result = parse_stack.top().insert(parsed);
if (!result.second)
{
MFEM_ABORT("Error parsing configuration file!\nDuplicate key "
<< parsed << " was already seen in this object!");
return false;
}
}
break;
default:
break;
}
return true;
};
try
{
config = json::parse(buffer, check_duplicate_keys);
}
catch (json::parse_error &e)
{
MFEM_ABORT("Error parsing configuration file!\n " << e.what());
}
if (print)
{
Mpi::Print("\n{}\n", config.dump(2));
}

// Set up configuration option data structures.
problem.SetUp(config);
model.SetUp(config);
domains.SetUp(config);
boundaries.SetUp(config);
solver.SetUp(config);

// Cleanup and error checking.
config.erase("Problem");
config.erase("Model");
config.erase("Domains");
config.erase("Boundaries");
config.erase("Solver");
MFEM_VERIFY(config.empty(), "Found an unsupported configuration file section!\n"
<< config.dump(2));

// Check compatibility of configuration file and problem type.
CheckConfiguration();
}

void IoData::PreprocessFile(const char *filename, std::stringstream &buffer)
std::stringstream PreprocessFile(const char *filename)
{
// Read configuration file into memory.
// Read configuration file into memory and return as a stringstream.
std::string file;
{
std::ifstream fi(filename);
Expand Down Expand Up @@ -133,6 +65,7 @@ void IoData::PreprocessFile(const char *filename, std::stringstream &buffer)
// Perform integer range expansion for arrays ([a - b, c] = [a-b,c] =
// [a,a+1,...,b-1,b,c]). The whole file is now one line and arrays have no spaces after
// whitespace stripping.
std::stringstream output;
auto RangeExpand = [](std::string_view str) -> std::string
{
// Handle the given string which is only numeric with possible hyphens.
Expand Down Expand Up @@ -169,37 +102,112 @@ void IoData::PreprocessFile(const char *filename, std::stringstream &buffer)
// digits, commas, and '-'. Exclude the outer square brackets.
std::string_view str(file.data() + (start - file.cbegin() + 1), it - start - 1);
std::size_t s = 0, pos;
buffer << '[';
output << '[';
while ((pos = str.find(',', s)) != std::string::npos)
{
buffer << RangeExpand(str.substr(s, pos - s)) << ',';
output << RangeExpand(str.substr(s, pos - s)) << ',';
s = pos + 1;
}
buffer << RangeExpand(str.substr(s)) << ']';
output << RangeExpand(str.substr(s)) << ']';
start = it + 1;
inside = false;
}
else if (*it == '[')
{
buffer << std::string(start, it);
output << std::string(start, it);
start = it;
}
else if (range_vals.find(*it) == std::string::npos)
{
buffer << std::string(start, it);
output << std::string(start, it);
start = it;
inside = false;
}
}
else if (*it == '[')
{
buffer << std::string(start, it);
output << std::string(start, it);
start = it;
inside = true;
}
}
buffer << std::string(start, file.end());
output << std::string(start, file.end());
}
return output;
}

} // namespace

using json = nlohmann::json;

IoData::IoData(const char *filename, bool print) : Lc(1.0), tc(1.0), init(false)
{
// Open configuration file and preprocess: strip whitespace, comments, and expand integer
// ranges.
std::stringstream buffer = PreprocessFile(filename);

// Parse the configuration file. Use a callback function to detect and throw errors for
// duplicate keys.
json config;
std::stack<std::set<json>> parse_stack;
json::parser_callback_t check_duplicate_keys =
[&](int, json::parse_event_t event, json &parsed)
{
switch (event)
{
case json::parse_event_t::object_start:
parse_stack.push(std::set<json>());
break;
case json::parse_event_t::object_end:
parse_stack.pop();
break;
case json::parse_event_t::key:
{
const auto result = parse_stack.top().insert(parsed);
if (!result.second)
{
MFEM_ABORT("Error parsing configuration file!\nDuplicate key "
<< parsed << " was already seen in this object!");
return false;
}
}
break;
default:
break;
}
return true;
};
try
{
config = json::parse(buffer, check_duplicate_keys);
}
catch (json::parse_error &e)
{
MFEM_ABORT("Error parsing configuration file!\n " << e.what());
}
if (print)
{
Mpi::Print("\n{}\n", config.dump(2));
}

// Set up configuration option data structures.
problem.SetUp(config);
model.SetUp(config);
domains.SetUp(config);
boundaries.SetUp(config);
solver.SetUp(config);

// Cleanup and error checking.
config.erase("Problem");
config.erase("Model");
config.erase("Domains");
config.erase("Boundaries");
config.erase("Solver");
MFEM_VERIFY(config.empty(), "Found an unsupported configuration file section!\n"
<< config.dump(2));

// Check compatibility of configuration file and problem type.
CheckConfiguration();
}

void IoData::CheckConfiguration()
Expand Down
4 changes: 0 additions & 4 deletions palace/utils/iodata.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#ifndef PALACE_UTILS_IODATA_HPP
#define PALACE_UTILS_IODATA_HPP

#include <sstream>
#include "utils/configfile.hpp"

namespace mfem
Expand Down Expand Up @@ -35,9 +34,6 @@ class IoData
double Lc, tc;
bool init;

// Preprocess the configuration file for parsing.
void PreprocessFile(const char *filename, std::stringstream &buffer);

// Check configuration file options and compatibility with requested problem type.
void CheckConfiguration();

Expand Down

0 comments on commit 52b410a

Please sign in to comment.