diff --git a/.ci/check_hdf5_docs.sh b/.ci/check_hdf5_docs.sh new file mode 100755 index 00000000..ec458918 --- /dev/null +++ b/.ci/check_hdf5_docs.sh @@ -0,0 +1,18 @@ +# Generate the HDF5 output documentation and check it's up to date +# otherwise tell the user how to update it +hdf5_file="$1" +rst_file="$2" +hdf5_file_basename=`basename "${hdf5_file}"` +full_rst_file="doc/hdf5_properties/${rst_file}" + +scripts/properties_as_list.sh "${TEST_OUTPUTS_DIR}/${TEST_SIM_NAME}/${hdf5_file}" > props.rst +_diff="`diff -Naur "${full_rst_file}" props.rst`" +if [ -n "${_diff}" ]; then + echo "\nThe file ${full_rst_file} is out of date. This probably means that you added a new\n" \ + "dataset to shark's output, but forgot to update the corresponding documentation.\n" \ + "The full difference follows:\n\n${_diff}\n\n" \ + "Please run the script/properties_as_lish.sh script against a ${hdf5_file_basename} file\n" \ + "to re-generate its documentation, then commit your changes. For example:\n\n" \ + "scripts/properties_as_list.sh my-output/model/199/0/${hdf5_file_basename} > ${full_rst_file}" >&2 + exit 1 +fi diff --git a/.ci/compare_galaxies.sh b/.ci/compare_galaxies.sh new file mode 100755 index 00000000..ced8899a --- /dev/null +++ b/.ci/compare_galaxies.sh @@ -0,0 +1,9 @@ +reference_model_name=$1 +shift +this_model_name=$1 +shift + +python scripts/compare_galaxies.py -m \ + "${TEST_OUTPUTS_DIR}/${TEST_SIM_NAME}/${reference_model_name}/199/0/galaxies.hdf5" \ + "${TEST_OUTPUTS_DIR}/${TEST_SIM_NAME}/${this_model_name}/199/0/galaxies.hdf5" \ + $@ diff --git a/.ci/run_shark.sh b/.ci/run_shark.sh new file mode 100755 index 00000000..1589428b --- /dev/null +++ b/.ci/run_shark.sh @@ -0,0 +1,10 @@ +model_name=$1 +shift + +${CI_BUILD_DIR}/shark ci-test.cfg \ + -o execution.output_bh_histories=true -o execution.snapshots_bh_histories=199 \ + -o simulation.redshift_file=${TEST_INPUTS_DIR}/redshifts.txt \ + -o simulation.tree_files_prefix=${TEST_INPUTS_DIR}/tree_199 \ + -o simulation.sim_name=${TEST_SIM_NAME} \ + -o execution.name_model=$model_name \ + $@ diff --git a/.github/workflows/build-and-test.yaml b/.github/workflows/build-and-test.yaml index 5e63bd32..6bc55023 100644 --- a/.github/workflows/build-and-test.yaml +++ b/.github/workflows/build-and-test.yaml @@ -10,31 +10,92 @@ jobs: strategy: matrix: os: [ubuntu-latest, macos-latest] + env: + CI_BUILD_DIR: build + TEST_INPUTS_DIR: inputs + TEST_OUTPUTS_DIR: outputs + TEST_SIM_NAME: mini-SURFS + # libomp is installed as keg-only, so we need to point cmake to it + MACOS_LIBOMP_HOME: /opt/homebrew/opt/libomp steps: - uses: actions/checkout@v3 with: submodules: true - - name: Install dependencies + - name: Install system dependencies (Linux) if: ${{ matrix.os == 'ubuntu-latest' }} run: | - sudo apt install libhdf5-dev hdf5-tools libboost-filesystem-dev libboost-program-options-dev libboost-log-dev cxxtest libgsl-dev + sudo apt install ninja-build libhdf5-dev hdf5-tools libboost-filesystem-dev libboost-program-options-dev libboost-log-dev cxxtest libgsl-dev - - name: Install dependencies + - name: Install system dependencies (MacOS) if: ${{ matrix.os == 'macos-latest' }} run: | - brew install hdf5 boost cxxtest gsl + brew install ninja hdf5 boost cxxtest gsl libomp + + - name: Install Python + uses: actions/setup-python@v4 + with: + python-version: "3.10" + + - name: Install Python dependencies + run: pip install matplotlib h5py scipy - name: Configure # Leaving Werror out for now because there *are* errors # and I don't know what the proper fix is. - run: cmake -B build/ -DSHARK_TEST=ON -DCMAKE_CXX_FLAGS="-Wall" #-Werror + run: cmake -B ${CI_BUILD_DIR} -G Ninja -DSHARK_TEST=ON -DCMAKE_CXX_FLAGS="-Wall" -DCMAKE_PREFIX_PATH="$MACOS_LIBOMP_HOME" #-Werror - name: Build - run: cmake --build build/ + run: cmake --build ${CI_BUILD_DIR} - name: Run unit tests run: | - cd build + cd ${CI_BUILD_DIR} ctest --output-on-failure + + - name: Prepare test dataset + run: | + mkdir -p ${TEST_INPUTS_DIR} + curl -L -o ${TEST_INPUTS_DIR}/redshifts.txt 'https://docs.google.com/uc?export=download&id=1xvNmJB_KmoBHuQz-QzdPnY0HFs7smkUB' + curl -L -o ${TEST_INPUTS_DIR}/tree_199.0.hdf5 'https://docs.google.com/uc?export=download&id=1JDK8ak13bEhzg9H9xt0uE8Fh_2LD3KpZ' + sed " + s|output_directory.*|output_directory = ${TEST_OUTPUTS_DIR}| + s|redshift_file.*|redshift_file = ${TEST_INPUTS_DIR}/redshifts.txt| + s|tree_files_prefix.*|tree_files_prefix = ${TEST_INPUTS_DIR}/tree_199| + s|sim_name.*|sim_name = ${TEST_SIM_NAME}| + " sample.cfg > ci-test.cfg + + - name: Run shark with fixed seed + run: .ci/run_shark.sh my_model -o execution.seed=123456 + + - name: Check output properties' documentation + run: | + .ci/check_hdf5_docs.sh my_model/199/0/galaxies.hdf5 galaxies.rst + .ci/check_hdf5_docs.sh my_model/156/0/star_formation_histories.hdf5 star_formation_histories.rst + .ci/check_hdf5_docs.sh my_model/199/0/black_hole_histories.hdf5 black_hole_histories.rst + + - name: Check fixed seed is reproducible + run: | + .ci/run_shark.sh my_model_same_seed -o execution.seed=123456 + .ci/compare_galaxies.sh my_model my_model_same_seed + + - name: Check fixed seed is reproducible when multithreaded + run: | + # "-t 0" lets shark use the maximum number of OpenMP threads, + # which OpenMP implementations usually constrain to the available hardware + .ci/run_shark.sh my_model_same_seed_parallel -o execution.seed=123456 -t 0 + .ci/compare_galaxies.sh my_model my_model_same_seed_parallel + + - name: Check random seed gives different results + run: | + .ci/run_shark.sh my_model_random_seed -t 0 + .ci/compare_galaxies.sh my_model my_model_random_seed --expect-unequal + + # Currently skipped because there are a few minor problems + # with some plots + - name: Generate all plots + if: false + run: | + echo "backend: Agg" >> matplotlibrc + python standard_plots/all.py -c ci-test.cfg