Skip to content

Commit

Permalink
Merge pull request #6287 from knelli2/reduce_cce_options
Browse files Browse the repository at this point in the history
Change ReduceCceWorldtube to use options
  • Loading branch information
nilsdeppe authored Oct 5, 2024
2 parents c013448 + e17305c commit 298623c
Show file tree
Hide file tree
Showing 7 changed files with 229 additions and 54 deletions.
39 changes: 27 additions & 12 deletions .github/workflows/DeployStaticExecutables.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,35 +53,50 @@ jobs:
gdown \
"https://drive.google.com/uc?id=1uaESVdylNmcHwpZwogX4TVrNs8JbWNF1"
gdown \
"https://drive.google.com/uc?id=1rfzjtXtrP9pQE2az3935uN0z_5aSF1hy"
"https://drive.google.com/uc?id=1yYMM4PVUec9pIjKTxI4aCpo0Umqconr8"
- name: Copy CCE executables from the container
run: >
mkdir CceExecutables
mkdir CceExecutables;
mkdir ./CceExecutables/ReduceCceWorldtube;
mkdir ./CceExecutables/Tests;
cp ./tests/InputFiles/Cce/CharacteristicExtract.yaml
./CceExecutables/CharacteristicExtract.yaml
for i in CharacteristicExtract ReduceCceWorldtube; do
docker cp static-execs:/work/spectre/build/bin/$i ./CceExecutables;
done
cp ./tests/InputFiles/ReduceCceWorldtube/ReduceCceWorldtube.yaml
./CceExecutables/ReduceCceWorldtube/ReduceCceWorldtube.yaml
docker cp
static-execs:/work/spectre/build/bin/CharacteristicExtract
./CceExecutables/
docker cp static-execs:/work/spectre/build/bin/ReduceCceWorldtube
./CceExecutables/ReduceCceWorldtube/
- name: Test CCE executable outside of container
run: |
sed -i 's/CceR0257/BondiSachsCceR0200/g' \
mv BondiSachsCceR0200.h5 ./CceExecutables/Tests/
mv CheckCceOutput.py ./CceExecutables/Tests/
mv CharacteristicExtractReduction_Expected.h5 \
./CceExecutables/Tests/
sed -i 's/CceR0257/Tests\/BondiSachsCceR0200/g' \
./CceExecutables/CharacteristicExtract.yaml
sed -i 's/H5IsBondiData: False/H5IsBondiData: True/g' \
./CceExecutables/CharacteristicExtract.yaml
./CceExecutables/CharacteristicExtract \
--input-file ./CceExecutables/CharacteristicExtract.yaml
python ./CheckCceOutput.py
cd ./CceExecutables/
./CharacteristicExtract \
--input-file ./CharacteristicExtract.yaml
python ./Tests/CheckCceOutput.py
rm CharacteristicExtractReduction.h5
cd ../
- name: Create CCE executables release asset
# Note: We use xz compression since it's much better than gzip, even
# though it's a decent bit slower. Specifically, xz is two thirds the
# size of gzip.
run: |
mv BondiSachsCceR0200.h5 ./CceExecutables/
mv CharacteristicExtractReduction_Expected.h5 ./CceExecutables/
mv CheckCceOutput.py ./CceExecutables/
tar cJf CceExecutables.tar.xz CceExecutables
- name: Upload to release
uses: softprops/action-gh-release@v2
Expand Down
18 changes: 15 additions & 3 deletions cmake/AddInputFileTests.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,20 @@ function(add_single_input_file_test INPUT_FILE EXECUTABLE COMMAND_LINE_ARGS
endfunction()

# Searches the directory INPUT_FILE_DIR for .yaml files and adds a test for each
# one. See `WritingTests.md` for details on controlling input file tests.
function(add_input_file_tests INPUT_FILE_DIR)
# one. See `WritingTests.md` for details on controlling input file tests. Add
# input files to the whitelist at the bottom of this file to ignore those tests
function(add_input_file_tests INPUT_FILE_DIR INPUT_FILE_WHITELIST)
set(INPUT_FILE_LIST "")
file(GLOB_RECURSE INPUT_FILE_LIST ${INPUT_FILE_DIR} "${INPUT_FILE_DIR}*.yaml")
set(TIMEOUT 2)
list(TRANSFORM INPUT_FILE_WHITELIST PREPEND ${INPUT_FILE_DIR})

foreach(INPUT_FILE ${INPUT_FILE_LIST})
# Only parse the input file if we are allowed to
if (${INPUT_FILE} IN_LIST INPUT_FILE_WHITELIST)
continue()
endif()

file(READ ${INPUT_FILE} INPUT_FILE_CONTENTS)

# Read the priority of the test specified in input file, empty is accepted.
Expand Down Expand Up @@ -239,4 +246,9 @@ configure_file(
${PROJECT_BINARY_DIR}/tmp/RunInputFileTest.sh
@ONLY)

add_input_file_tests("${CMAKE_SOURCE_DIR}/tests/InputFiles/")
# These paths should be relative to the input file directory passed to
# `add_input_file_tests`
set(INPUT_FILE_WHITELIST
"ReduceCceWorldtube/ReduceCceWorldtube.yaml")

add_input_file_tests("${CMAKE_SOURCE_DIR}/tests/InputFiles/" ${INPUT_FILE_WHITELIST})
4 changes: 3 additions & 1 deletion docs/DevGuide/WritingTests.md
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,9 @@ namespace.
We have a suite of input file tests in addition to unit tests. Every input file
in the `tests/InputFiles/` directory is added to the test suite automatically.
The input file must specify the `Executable` it should run with in the input
If you don't want your input file tested at all, add the relative input file
path to the whitelist in `cmake/AddInputFileTests.cmake`. If the input file is
being tested, it must specify the `Executable` it should run with in the input
file metadata (above the `---` marker in the input file). Properties of the test
are controlled by the `Testing` section in the input file metadata. The
following properties are available:
Expand Down
30 changes: 19 additions & 11 deletions docs/Tutorials/CCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,16 @@ of the release (there may be a lot of text detailing what's been updated in this
release). Inside this tarball is

- the CCE executable `CharacteristicExtract`
- an example set of Bondi-Sachs worldtube data (see
[Input worldtube data formats](#input_worldtube_data_formats) section)
- an example YAML input file
- example output from CCE
- a `ReduceCceWorldtube` executable for converting between
[worldtube data formats](#input_worldtube_data_formats)
- an example set of Bondi-Sachs worldtube data in the `Tests/` directory (see
[Input worldtube data formats](#input_worldtube_data_formats) section)
- example output from CCE in the `Tests/` directory
- a `ReduceCceWorldtube` executable and YAML file for converting between
[worldtube data formats](#input_worldtube_data_formats) in the
`ReduceCceWorldtube/` diretory
- a python script `CheckCceOutput.py` (meant to be run from the root of the
tarball and after you run the example YAML input file also in the root of the
tarball) that will check if the example output is correct

\note The tarball is `.xz` so use `tar -xf TarName.tar.xz` to extract. The `-z`
flag to use gzip will cause an error.
Expand Down Expand Up @@ -198,18 +202,22 @@ SpECTRE provides a separate executable for converting from the
The `ReduceCceWorldtube` executable should be run on a
[cartesian_metric](#cartesian_metric_and_derivatives) worldtube file, and will
produce a corresponding 'reduced' Bondi-Sachs worldtube file.
The basic command-line arguments for the executable are:
This executable works similarly to our other executables by accepting a YAML
input file:

```
ReduceCceWorldtube --input-file CceR0050.h5 --output-file BondiCceR0050.h5\
--lmax_factor 3
ReduceCceWorldtube --input-file ReduceCceWorldtube.yaml
```

The argument `--lmax_factor` determines the factor by which the resolution of
with a YAML file

\snippet ReduceCceWorldtube.yaml reduce_cce_worldtube_yaml_doxygen_example

The option `LMaxFactor` determines the factor by which the resolution of
the boundary computation that is run will exceed the resolution of the
input and output files.
Empirically, we have found that `lmax_factor` of 3 is sufficient to achieve
roundoff precision in all boundary data we have attempted, and an `lmax_factor`
Empirically, we have found that `LMaxFactor` of 3 is sufficient to achieve
roundoff precision in all boundary data we have attempted, and an `LMaxFactor`
of 2 is usually sufficient to vastly exceed the precision of the simulation that
provided the boundary dataset.

Expand Down
2 changes: 2 additions & 0 deletions src/Executables/ReduceCceWorldtube/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ target_link_libraries(
Cce
GeneralRelativity
Informer
Options
Parallel
Printf
Spectral
SpinWeightedSphericalHarmonics
Expand Down
178 changes: 151 additions & 27 deletions src/Executables/ReduceCceWorldtube/ReduceCceWorldtube.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@

#include <boost/program_options.hpp>
#include <cstddef>
#include <exception>
#include <string>

#include "DataStructures/ComplexModalVector.hpp"
#include "DataStructures/DataBox/DataBox.hpp"
#include "DataStructures/DataBox/Tag.hpp"
#include "DataStructures/DataVector.hpp"
#include "DataStructures/SpinWeighted.hpp"
#include "DataStructures/Variables.hpp"
Expand All @@ -18,9 +20,14 @@
#include "Evolution/Systems/Cce/WorldtubeBufferUpdater.hpp"
#include "NumericalAlgorithms/SpinWeightedSphericalHarmonics/SwshCoefficients.hpp"
#include "NumericalAlgorithms/SpinWeightedSphericalHarmonics/SwshCollocation.hpp"
#include "Options/Auto.hpp"
#include "Options/ParseOptions.hpp"
#include "Options/String.hpp"
#include "Parallel/CreateFromOptions.hpp"
#include "Parallel/Printf/Printf.hpp"
#include "Utilities/Gsl.hpp"
#include "Utilities/TMPL.hpp"
#include "Utilities/TaggedTuple.hpp"

// Charm looks for this function but since we build without a main function or
// main module we just have it be empty
Expand Down Expand Up @@ -275,6 +282,107 @@ void perform_cce_worldtube_reduction(
}
Parallel::printf("\n");
}

namespace OptionTags {
struct InputH5File {
using type = std::string;
static constexpr Options::String help =
"Name of the H5 worldtube file. A '.h5' extension will be added if "
"needed.";
};

struct OutputH5File {
using type = std::string;
static constexpr Options::String help =
"Name of output H5 file. A '.h5' extension will be added if needed.";
};

struct FixSpecNormalization {
using type = bool;
static constexpr Options::String help =
"Apply corrections associated with documented SpEC worldtube file "
"errors. If you are using worldtube data from SpECTRE or from another NR "
"code but in the SpECTRE format, then this option must be 'False'";
};

struct BufferDepth {
using type = Options::Auto<size_t>;
static constexpr Options::String help =
"Number of time steps to load during each call to the file-accessing "
"routines. Higher values mean fewer, larger loads from file into RAM. "
"Set to 'Auto' to use a default value (2000).";
};

struct LMaxFactor {
using type = Options::Auto<size_t>;
static constexpr Options::String help =
"The boundary computations will be performed at a resolution that is "
"'LMaxFactor' times the input file LMax to avoid aliasing. Set to 'Auto' "
"to use a default value (2).";
};
} // namespace OptionTags

using option_tags =
tmpl::list<OptionTags::InputH5File, OptionTags::OutputH5File,
OptionTags::FixSpecNormalization, OptionTags::BufferDepth,
OptionTags::LMaxFactor>;
using OptionTuple = tuples::tagged_tuple_from_typelist<option_tags>;

namespace ReduceCceTags {
struct InputH5File : db::SimpleTag {
using type = std::string;
using option_tags = tmpl::list<OptionTags::InputH5File>;
static constexpr bool pass_metavariables = false;
static type create_from_options(std::string option) {
if (not option.ends_with(".h5")) {
option += ".h5";
}
return option;
}
};

struct OutputH5File : db::SimpleTag {
using type = std::string;
using option_tags = tmpl::list<OptionTags::OutputH5File>;
static constexpr bool pass_metavariables = false;
static type create_from_options(std::string option) {
if (not option.ends_with(".h5")) {
option += ".h5";
}
return option;
}
};

struct FixSpecNormalization : db::SimpleTag {
using type = bool;
using option_tags = tmpl::list<OptionTags::FixSpecNormalization>;
static constexpr bool pass_metavariables = false;
static type create_from_options(const bool option) { return option; }
};

struct BufferDepth : db::SimpleTag {
using type = size_t;
using option_tags = tmpl::list<OptionTags::BufferDepth>;
static constexpr bool pass_metavariables = false;
static type create_from_options(const std::optional<size_t>& option) {
return option.value_or(2000);
}
};

struct LMaxFactor : db::SimpleTag {
using type = size_t;
using option_tags = tmpl::list<OptionTags::BufferDepth>;
static constexpr bool pass_metavariables = false;
static type create_from_options(const std::optional<size_t>& option) {
return option.value_or(2);
}
};
} // namespace ReduceCceTags

using tags = tmpl::list<ReduceCceTags::InputH5File, ReduceCceTags::OutputH5File,
ReduceCceTags::FixSpecNormalization,
ReduceCceTags::BufferDepth, ReduceCceTags::LMaxFactor>;
using TagsTuple = tuples::tagged_tuple_from_typelist<tags>;
} // namespace

/*
Expand All @@ -283,44 +391,60 @@ void perform_cce_worldtube_reduction(
* storing the worldtube scalars that are required as input for CCE.
*/
int main(int argc, char** argv) {
boost::program_options::positional_options_description pos_desc;
pos_desc.add("old_spec_cce_file", 1).add("output_file", 1);

// Boost options for the input yaml and --help flag
boost::program_options::options_description desc("Options");
desc.add_options()("help,h,", "show this help message")(
"input_file", boost::program_options::value<std::string>()->required(),
"name of old CCE data file")(
"output_file", boost::program_options::value<std::string>()->required(),
"output filename")(
"fix_spec_normalization",
"Apply corrections associated with documented SpEC "
"worldtube file errors")(
"buffer_depth",
boost::program_options::value<size_t>()->default_value(2000),
"number of time steps to load during each call to the file-accessing "
"routines. Higher values mean fewer, larger loads from file into RAM.")(
"lmax_factor", boost::program_options::value<size_t>()->default_value(2),
"the boundary computations will be performed at a resolution that is "
"lmax_factor times the input file lmax to avoid aliasing");
"input-file", boost::program_options::value<std::string>()->required(),
"Name of YAML input file to use.");

boost::program_options::variables_map vars;

boost::program_options::store(
boost::program_options::command_line_parser(argc, argv)
.positional(pos_desc)
.options(desc)
.run(),
vars);

if (vars.count("help") != 0u or vars.count("input_file") == 0u or
vars.count("output_file") == 0u) {
Parallel::printf("%s\n", desc);
// Option parser for all the actual options
Options::Parser<option_tags> parser{
"This executable is used for converting the unnecessarily large metric "
"worldtube data format into a smaller representation (roughly a factor "
"of 4) just storing the worldtube scalars that are required as "
"input for CCE."};

// Help is a successful return
if (vars.contains("help")) {
Parallel::printf("%s\n%s", desc, parser.help());
return 0;
}

perform_cce_worldtube_reduction(vars["input_file"].as<std::string>(),
vars["output_file"].as<std::string>(),
vars["buffer_depth"].as<size_t>(),
vars["lmax_factor"].as<size_t>(),
vars.count("fix_spec_normalization") != 0u);
// Not specifying an input file is an error
if (not vars.contains("input-file")) {
Parallel::printf("Missing input file. Pass '--input-file'");
return 1;
}

// Wrap in try-catch to print nice errors and terminate gracefully
try {
const std::string input_yaml = vars["input-file"].as<std::string>();

// Actually parse the yaml. This does a check if it exists.
parser.parse_file(input_yaml);

// First create option tags, and then actual tags.
const OptionTuple options = parser.template apply<option_tags>(
[](auto... args) { return OptionTuple(std::move(args)...); });
const TagsTuple inputs =
Parallel::create_from_options<void>(options, tags{});

// Do the reduction
perform_cce_worldtube_reduction(
tuples::get<ReduceCceTags::InputH5File>(inputs),
tuples::get<ReduceCceTags::OutputH5File>(inputs),
tuples::get<ReduceCceTags::BufferDepth>(inputs),
tuples::get<ReduceCceTags::BufferDepth>(inputs),
tuples::get<ReduceCceTags::FixSpecNormalization>(inputs));
} catch (const std::exception& exception) {
Parallel::printf("%s\n", exception.what());
return 1;
}
}
Loading

0 comments on commit 298623c

Please sign in to comment.