Skip to content

Commit

Permalink
Allow in memory manipulation of nalu yaml files (#51)
Browse files Browse the repository at this point in the history
* Adjust nalu to construct with yaml

* Add logfile naming option

* Add test case that shows syntax

* Style

* Add comments and parallel check for file writing

* Style

* Fix logic error

* Subtle fix for being careles with what I renamed in nalu
  • Loading branch information
psakievich authored Jul 25, 2023
1 parent 1ac5d55 commit 20610d1
Show file tree
Hide file tree
Showing 9 changed files with 466 additions and 16 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
.DS_Store
spack*
compile_commands.json
.cache
61 changes: 57 additions & 4 deletions app/exawind/exawind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "OversetSimulation.h"
#include "MPIUtilities.h"
#include "mpi.h"
#include "yaml-editor.h"
#ifdef EXAWIND_HAS_STD_FILESYSTEM
#include <filesystem>
#endif
Expand Down Expand Up @@ -88,8 +89,10 @@ int main(int argc, char** argv)
#endif
std::ofstream out;

const auto nalu_inps = node["nalu_wind_inp"].as<std::vector<std::string>>();
const int num_nwsolvers = nalu_inps.size();
YAML::Node nalu_node = node["nalu_wind_inp"];
// make sure it is a list for now
assert(nalu_node.IsSequence());
const int num_nwsolvers = nalu_node.size();
if (num_nwind_ranks < num_nwsolvers) {
throw std::runtime_error(
"Number of Nalu-Wind ranks is less than the number of Nalu-Wind "
Expand Down Expand Up @@ -181,10 +184,60 @@ int main(int argc, char** argv)
? node["nonlinear_iterations"].as<int>()
: 1;

const YAML::Node yaml_replace_all = node["nalu_replace_all"];
for (int i = 0; i < num_nwsolvers; i++) {
if (nalu_comms.at(i) != MPI_COMM_NULL)
if (nalu_comms.at(i) != MPI_COMM_NULL) {
YAML::Node yaml_replace_instance;
YAML::Node this_instance = nalu_node[i];

std::string nalu_inpfile, logfile;
bool write_final_yaml_to_disk = false;
if (this_instance.IsMap()) {
yaml_replace_instance = this_instance["replace"];
nalu_inpfile =
this_instance["base_input_file"].as<std::string>();
// deal with the logfile name
if (this_instance["logfile"]) {
logfile = this_instance["logfile"].as<std::string>();
} else {
logfile = exawind::NaluWind::change_file_name_suffix(
nalu_inpfile, ".log", i);
}
if (this_instance["write_final_yaml_to_disk"]) {
write_final_yaml_to_disk =
this_instance["write_final_yaml_to_disk"].as<bool>();
}

} else {
nalu_inpfile = this_instance.as<std::string>();
logfile = exawind::NaluWind::change_file_name_suffix(
nalu_inpfile, ".log");
}

YAML::Node nalu_yaml = YAML::LoadFile(nalu_inpfile);
// replace in order so instance can overwrite all
if (yaml_replace_all) {
YEDIT::find_and_replace(nalu_yaml, yaml_replace_all);
}
if (yaml_replace_instance) {
YEDIT::find_and_replace(nalu_yaml, yaml_replace_instance);
}

// only the first rank of the comm should write the file
int comm_rank = -1;
MPI_Comm_rank(nalu_comms.at(i), &comm_rank);
if (write_final_yaml_to_disk && comm_rank == 0) {
auto new_ifile_name =
exawind::NaluWind::change_file_name_suffix(
logfile, ".yaml");
std::ofstream fout(new_ifile_name);
fout << nalu_yaml;
fout.close();
}

sim.register_solver<exawind::NaluWind>(
i + 1, nalu_comms.at(i), nalu_inps.at(i), nalu_vars);
i + 1, nalu_comms.at(i), nalu_yaml, logfile, nalu_vars);
}
}

if (amr_comm != MPI_COMM_NULL) {
Expand Down
14 changes: 3 additions & 11 deletions src/NaluWind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,11 @@ void NaluWind::finalize()
NaluWind::NaluWind(
int id,
stk::ParallelMachine comm,
const std::string& inpfile,
const YAML::Node& inp_yaml,
const std::string& logfile,
const std::vector<std::string>& fnames,
TIOGA::tioga& tg)
: m_id(id)
, m_comm(comm)
, m_doc(YAML::LoadFile(inpfile))
, m_fnames(fnames)
, m_sim(m_doc)
: m_id(id), m_comm(comm), m_doc(inp_yaml), m_fnames(fnames), m_sim(m_doc)
{
auto& env = sierra::nalu::NaluEnv::self();
env.parallelCommunicator_ = comm;
Expand All @@ -48,11 +45,6 @@ NaluWind::NaluWind(

::tioga_nalu::TiogaRef::self(&tg);

int extloc = inpfile.rfind(".");
std::string logfile = inpfile;
if (extloc != std::string::npos) {
logfile = inpfile.substr(0, extloc) + ".log";
}
env.set_log_file_stream(logfile);
}

Expand Down
16 changes: 15 additions & 1 deletion src/NaluWind.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,24 @@ class NaluWind : public ExawindSolver
public:
static void initialize();
static void finalize();
static std::string change_file_name_suffix(
std::string inpfile, std::string suffix, int index = -1)
{
int extloc = inpfile.rfind(".");
std::string logfile = inpfile;
if (index >= 0) {
suffix = "_" + std::to_string(index) + suffix;
}
if (extloc != std::string::npos) {
logfile = inpfile.substr(0, extloc) + suffix;
}
return logfile;
}
explicit NaluWind(
int id,
stk::ParallelMachine comm,
const std::string& inp_file,
const YAML::Node& inp_yaml,
const std::string& logfile,
const std::vector<std::string>& fnames,
TIOGA::tioga& tg);
~NaluWind();
Expand Down
97 changes: 97 additions & 0 deletions src/yaml-editor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#include "yaml-cpp/yaml.h"
#include <stdexcept>
#include <iostream>

namespace YEDIT {

/* Exception if the graph is not formatted correctly
* This exception is designed to reproduce the failing portion of the YAML graph
* when called recursively so it can be echo'd to the user
*/
class YamlNodeMatchException : public std::exception
{
public:
YamlNodeMatchException(
std::string currentNode, std::string accumulatedPath = "")
: std::exception()
{
std::string extra =
accumulatedPath.empty() ? "" : ":" + accumulatedPath;
graphPath_ = currentNode + extra;
}
const char* what() const noexcept override { return graphPath_.c_str(); }

private:
std::string graphPath_;
};

namespace {
/* A function that will traverse the src node based on the key node
* The two nodes must be identical until the final leaf values and then the
* values of the key will override the src values. If the two graphs don't match
* at any point prior to the leaves then it will trigger a
* YamlNodeMatchException.
*/
inline void impl_find_and_replace(YAML::Node src, YAML::Node key)
{
switch (key.Type()) {
case YAML::NodeType::Map:
// case 1: it's a map
//- pass the contents of the map recursively
for (auto n : key) {
std::string k = static_cast<std::string>(n.first.Scalar());
try {
impl_find_and_replace(src[k], key[k]);
} catch (YamlNodeMatchException& e) {
throw YamlNodeMatchException(k, std::string(e.what()));
}
}
break;
case YAML::NodeType::Sequence:
// case 2: it's a list
//- pass the contents of the list recursively (order matters when
// looking for a match)
for (int i = 0; i < key.size(); ++i) {
try {
impl_find_and_replace(src[i], key[i]);
} catch (YamlNodeMatchException& e) {
throw YamlNodeMatchException(
"[" + std::to_string(i) + "]", std::string(e.what()));
}
}
break;
case YAML::NodeType::Scalar: {
// case 3: it's a scalar
//- replace value
if (src.Type() != key.Type()) {
// we have a invalid path in the key
throw YamlNodeMatchException(key.as<std::string>());
}
src = key;
break;
}
default:
break;
}
}
} // namespace

/* The accessible version of impl_find_and_replace that collects the final
* error and makes it more readable
*/
inline void find_and_replace(YAML::Node src, YAML::Node key)
{
try {
impl_find_and_replace(src, key);
} catch (YamlNodeMatchException& e) {
auto failingPath = static_cast<std::string>(e.what());
std::string message =
"\nFailure trying to replace YAML\nFailing Graph:\n\t";
message += failingPath + "\n";
message +=
"Please double check and make sure this matches the source YAML";
throw std::runtime_error(message);
}
}

} // namespace YEDIT
1 change: 1 addition & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,4 @@ add_test_r(nalu-nalu-cylinder)
add_test_r(amr-nalu-cylinder)
add_test_r(nalu-nalu-cylinder-motion)
add_test_r(amr-nalu-cylinder-motion)
add_test_r(hybrid-multi-cylinder)
62 changes: 62 additions & 0 deletions test/test_files/hybrid-multi-cylinder/cylinder-amr.inp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#
# SIMULATION STOP #
#.......................................#
time.stop_time = 22000.0 # Max (#
tim.max_step = -1
time.fixed_dt = 0.15
time.cfl = 1.0
time.plot_interval = 10
time.checkpoint_interval = -10
io.plot_file = out/plt
io.check_file = out/chk
# PHYSICS #
#.......................................#
incflo.gravity = 0. 0. 0.0 # Gravitational force (3D)

incflo.use_godunov = 1
incflo.do_initial_proj = 0
incflo.initial_iterations = 0
transport.viscosity = 0.005
turbulence.model = Laminar


incflo.physics = FreeStream
incflo.velocity = 1.0 0.0 0.0
incflo.density = 1.0

amr.n_cell = 160 56 4 # Grid cells at coarsest AMRlevel
amr.max_level = 0 # Max AMR level in hierarchy
amr.blocking_factor_z = 4
amr.blocking_factor_x = 8
amr.blocking_factor_y = 8
amr.max_grid_size_z = 4
amr.max_grid_size_x = 16
amr.max_grid_size_y = 16

geometry.prob_lo = -15 -5.0 -0.375 # Lo corner coordinates
geometry.prob_hi = 7.5 5.0 0.375 # Hi corner coordinates
geometry.is_periodic = 0 0 1 # Periodicity x y z (0/1)


# Boundary conditions
xlo.type = "mass_inflow"
xlo.velocity = 1.0 0.0 0.0
xlo.density = 1.0
xhi.type = "pressure_outflow"
xhi.pressure = 0.0
ylo.type = "slip_wall"
yhi.type = "slip_wall"
#zlo.type = "slip_wall"
#zhi.type = "slip_wall"

incflo.verbose = 0 # incflo_level
amrex.fpe_trap_invalid = 0 # Trap NaNs
amrex.throw_exception = 1
amrex.signal_handling = 0

mac_proj.verbose = 0
nodal_proj.verbose = 0
nodal_proj.mg_rtol = 1.0e-6
nodal_proj.mg_atol = 1.0e-10
nodal_proj.num_pre_smooth = 10
nodal_proj.num_post_smooth = 10
Loading

0 comments on commit 20610d1

Please sign in to comment.