From 2026524f2e7d65f0894d9df9f54fd4e195d2bd65 Mon Sep 17 00:00:00 2001 From: Jg_Piccinali <> Date: Wed, 23 Jul 2025 20:28:17 +0200 Subject: [PATCH 1/8] Add dummysph check --- checks/apps/dummysph/dummysph.py | 124 +++++++++++++++++++++++ checks/apps/dummysph/scripts/dummysph.sh | 19 ++++ 2 files changed, 143 insertions(+) create mode 100644 checks/apps/dummysph/dummysph.py create mode 100755 checks/apps/dummysph/scripts/dummysph.sh diff --git a/checks/apps/dummysph/dummysph.py b/checks/apps/dummysph/dummysph.py new file mode 100644 index 000000000..b45008792 --- /dev/null +++ b/checks/apps/dummysph/dummysph.py @@ -0,0 +1,124 @@ +# Copyright 2025 Swiss National Supercomputing Centre (CSCS/ETH Zurich) +# ReFrame Project Developers. See the top-level LICENSE file for details. +# +# SPDX-License-Identifier: BSD-3-Clause +import os + +import reframe as rfm +import reframe.utility.sanity as sn +import uenv + + +@rfm.simple_test +class DummySPH_Uenv_Ascent_Single(rfm.RegressionTest): + descr = "Build and Run Ascent tests with DummySPH" + valid_systems = ['+remote'] + valid_prog_environs = ['+uenv +cuda'] + ascentdir = variable( + str, + value=('/capstor/store/cscs/cscs/csstaff/jfavre/ascent/0.9.4/lib/' + 'cmake/ascent') + ) + # TODO: deploy a uenv with ascent, + # until then using (local install + prgenv-gnu/24.11:v2) + sourcesdir = 'https://github.com/jfavre/DummySPH.git' + tag = variable(str, value='92a06a1') # v0.1 + aos = parameter(['OFF']) # STRIDED_SCALARS: + # ON = struct tipsy (AOS) / OFF = std::vector (SOA) + fp64 = parameter(['OFF', 'ON']) # OFF=, ON= + input_dir = variable( + str, value='/capstor/store/cscs/cscs/csstaff/jfavre/ascent') + tipsy = parameter(['OFF', 'ON']) + tipsy_file = variable(str, value='hr8799_bol_bd1.017300') + # https://jfrog.svc.cscs.ch/artifactory/cscs-reframe-tests/dummysph/ + # -> hr8799_bol_bd1.017300.gz (1.06G) will take ~33 s (39.0MB/s) + h5part = parameter(['OFF', 'ON']) + h5part_file = variable(str, value='dump_wind-shock.h5') + test = parameter(['rendering', 'thresholding', 'compositing', + 'histsampling', 'binning']) + datadump = variable(str, value='OFF') + num_gpus = variable(int, value=4) + build_system = 'CMake' + build_locally = False + executable = './src/bin/dummysph_ascent' + time_limit = '4m' + + @run_after('init') + def skip_test(self): + """ + Unsupported: +STRIDED_SCALARS=ON SPH_DOUBLE=ON CAN_LOAD_TIPSY=ON CAN_LOAD_H5Part=ON +STRIDED_SCALARS=ON SPH_DOUBLE=ON CAN_LOAD_TIPSY=ON CAN_LOAD_H5Part=OFF +STRIDED_SCALARS=ON SPH_DOUBLE=ON CAN_LOAD_TIPSY=OFF CAN_LOAD_H5Part=ON +STRIDED_SCALARS=ON SPH_DOUBLE=OFF CAN_LOAD_TIPSY=ON CAN_LOAD_H5Part=ON +STRIDED_SCALARS=ON SPH_DOUBLE=OFF CAN_LOAD_TIPSY=OFF CAN_LOAD_H5Part=ON +STRIDED_SCALARS=OFF SPH_DOUBLE=ON CAN_LOAD_TIPSY=ON CAN_LOAD_H5Part=ON +STRIDED_SCALARS=OFF SPH_DOUBLE=ON CAN_LOAD_TIPSY=ON CAN_LOAD_H5Part=OFF +STRIDED_SCALARS=OFF SPH_DOUBLE=OFF CAN_LOAD_TIPSY=ON CAN_LOAD_H5Part=ON +STRIDED_SCALARS=OFF SPH_DOUBLE=OFF CAN_LOAD_TIPSY=ON CAN_LOAD_H5Part=OFF + """ + skip = ( + (self.tipsy == "ON" and self.h5part == "ON") or + (self.aos == "ON" and self.h5part == "ON") or + (self.aos == "OFF" and self.tipsy == "ON") or + (self.fp64 == "ON" and self.tipsy == "ON") + ) + self.skip_if(skip, 'skipping unsupported test') + + @run_before('compile') + def set_build_system(self): + self.build_system.max_concurrency = 6 + self.build_system.srcdir = 'src' + self.prebuild_cmds += [ + f"git checkout {self.tag}", + f"git switch -c {self.tag}", + f"touch _{self.aos}_{self.fp64}_{self.tipsy}_{self.h5part}", + f"cd src" + ] + self.build_system.config_opts = [ + # '-DCMAKE_C_COMPILER=mpicc', + # '-DCMAKE_CXX_COMPILER=mpicxx', + '-DCMAKE_BUILD_TYPE=Debug', # Release + f'-DSTRIDED_SCALARS={self.aos}', + f'-DSPH_DOUBLE={self.fp64}', + f'-DCAN_LOAD_TIPSY={self.tipsy}', + f'-DCAN_LOAD_H5Part={self.h5part}', + # f'-DCAN_DATADUMP={self.datadump}', + '-DINSITU=Ascent', + f'-DAscent_DIR={self.ascentdir}', + ] + if uenv.uarch(self.current_partition) == 'gh200': + cmake_arch = '-DCMAKE_CUDA_ARCHITECTURES=90' + self.build_system.config_opts.append(cmake_arch) + + @run_before('run') + def set_executable_tests(self): + self.job.options = [f'--nodes=1'] + self.rpt = 'rpt' + infile = '' + if self.h5part == "ON": + infile = f'--h5part {self.input_dir}/{self.h5part_file}' + elif self.tipsy == "ON": + infile = f'--h5part {self.input_dir}/{self.h5part_file}' + + if self.test == 'binning': + self.executable_opts = [f'--{self.test}', 'rho', infile, '2>&1'] + else: + self.executable_opts = [f'--{self.test}', 'out', infile, '2>&1'] + + @sanity_function + def validate_test(self): + regexes = [ + 'Could not find appropriate cast for array in CastAndCall', + 'Field type unsupported for conversion to blueprint', + 'Execution failed with vtkm: Cast failed: vtkm::cont::ArrayHandle', + 'Segmentation fault (core dumped)', + 'Field: dataset does not contain field', + ] + assert_list = [] + for regex in regexes: + assert_list.append( + sn.assert_not_found( + regex, self.stdout, msg=f'found "{regex}"')) + + return sn.all(assert_list) diff --git a/checks/apps/dummysph/scripts/dummysph.sh b/checks/apps/dummysph/scripts/dummysph.sh new file mode 100755 index 000000000..b2e09a47c --- /dev/null +++ b/checks/apps/dummysph/scripts/dummysph.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +in=$1 + + +ntests=`jq .runs[0].testcases[].job_exitcode $in |wc -l |awk '{print $0-1}'` + +for ii in `seq 0 $ntests` ;do +# for ii in `seq 0 2` ;do + result=`jq -r .runs[0].testcases[$ii].result $in` + aos=`jq -r .runs[0].testcases[$ii].aos $in` + fp64=`jq -r .runs[0].testcases[$ii].fp64 $in` + h5part=`jq -r .runs[0].testcases[$ii].h5part $in` + tipsy=`jq -r .runs[0].testcases[$ii].tipsy $in` + testname=`jq -r .runs[0].testcases[$ii].test $in` + stagedir=`jq -r .runs[0].testcases[$ii].stagedir $in` + + echo "$result $aos $fp64 $h5part $tipsy $testname $stagedir" +done From 2a75215e4d0e69d145e179b1f62461e8ae40bafd Mon Sep 17 00:00:00 2001 From: Jg_Piccinali <> Date: Wed, 23 Jul 2025 20:34:17 +0200 Subject: [PATCH 2/8] typo --- checks/apps/dummysph/dummysph.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checks/apps/dummysph/dummysph.py b/checks/apps/dummysph/dummysph.py index b45008792..f1b1b2b2a 100644 --- a/checks/apps/dummysph/dummysph.py +++ b/checks/apps/dummysph/dummysph.py @@ -99,7 +99,7 @@ def set_executable_tests(self): if self.h5part == "ON": infile = f'--h5part {self.input_dir}/{self.h5part_file}' elif self.tipsy == "ON": - infile = f'--h5part {self.input_dir}/{self.h5part_file}' + infile = f'--tipsy {self.input_dir}/{self.tipsy_file}' if self.test == 'binning': self.executable_opts = [f'--{self.test}', 'rho', infile, '2>&1'] From 388fbd15f7cc224e159e7f0b581901a559289c1c Mon Sep 17 00:00:00 2001 From: Jg_Piccinali <> Date: Wed, 23 Jul 2025 20:36:52 +0200 Subject: [PATCH 3/8] remove os import --- checks/apps/dummysph/dummysph.py | 1 - 1 file changed, 1 deletion(-) diff --git a/checks/apps/dummysph/dummysph.py b/checks/apps/dummysph/dummysph.py index f1b1b2b2a..a5bb27e48 100644 --- a/checks/apps/dummysph/dummysph.py +++ b/checks/apps/dummysph/dummysph.py @@ -2,7 +2,6 @@ # ReFrame Project Developers. See the top-level LICENSE file for details. # # SPDX-License-Identifier: BSD-3-Clause -import os import reframe as rfm import reframe.utility.sanity as sn From 57ba4509dba1c77c7091cf1ecef19dca00a40214 Mon Sep 17 00:00:00 2001 From: Jg_Piccinali <> Date: Thu, 24 Jul 2025 10:47:26 +0200 Subject: [PATCH 4/8] fix --- checks/apps/dummysph/scripts/dummysph.sh | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/checks/apps/dummysph/scripts/dummysph.sh b/checks/apps/dummysph/scripts/dummysph.sh index b2e09a47c..538d7fe41 100755 --- a/checks/apps/dummysph/scripts/dummysph.sh +++ b/checks/apps/dummysph/scripts/dummysph.sh @@ -5,15 +5,19 @@ in=$1 ntests=`jq .runs[0].testcases[].job_exitcode $in |wc -l |awk '{print $0-1}'` +echo "# result aos fp64 h5part tipsy testname reason basename" for ii in `seq 0 $ntests` ;do # for ii in `seq 0 2` ;do result=`jq -r .runs[0].testcases[$ii].result $in` aos=`jq -r .runs[0].testcases[$ii].aos $in` fp64=`jq -r .runs[0].testcases[$ii].fp64 $in` - h5part=`jq -r .runs[0].testcases[$ii].h5part $in` tipsy=`jq -r .runs[0].testcases[$ii].tipsy $in` + h5part=`jq -r .runs[0].testcases[$ii].h5part $in` testname=`jq -r .runs[0].testcases[$ii].test $in` - stagedir=`jq -r .runs[0].testcases[$ii].stagedir $in` + # stagedir=`jq -r .runs[0].testcases[$ii].stagedir $in` + basename=`jq -r .runs[0].testcases[$ii].stagedir $in |xargs basename` + fail_reason=`jq -r .runs[0].testcases[$ii].fail_reason $in` + if [ "$fail_reason" = "null" ] ;then reason=pass ;else reason=$fail_reason ;fi - echo "$result $aos $fp64 $h5part $tipsy $testname $stagedir" + echo "$result $aos $fp64 $tipsy $h5part $testname \"$reason\" $basename" done From d9efb2d931a33492b1f28a77e148b3d8be3b3098 Mon Sep 17 00:00:00 2001 From: Jg_Piccinali <> Date: Fri, 25 Jul 2025 10:26:32 +0200 Subject: [PATCH 5/8] Add expected failures --- checks/apps/dummysph/dummysph.py | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/checks/apps/dummysph/dummysph.py b/checks/apps/dummysph/dummysph.py index a5bb27e48..54a708bdf 100644 --- a/checks/apps/dummysph/dummysph.py +++ b/checks/apps/dummysph/dummysph.py @@ -63,6 +63,22 @@ def skip_test(self): (self.fp64 == "ON" and self.tipsy == "ON") ) self.skip_if(skip, 'skipping unsupported test') + # manage expected failures: + skip = ( + # "Field type unsupported for conversion to blueprint": + (self.aos == "OFF" + and (self.fp64 == "OFF" or self.fp64 == "ON") + and self.tipsy == "OFF" + and self.h5part == "OFF" + and self.test == "compositing") or + # vtkm: Cast failed: vtkm::cont::ArrayHandle": + (self.aos == "OFF" + and self.fp64 == "OFF" + and self.tipsy == "OFF" + and (self.h5part == "OFF" or self.h5part == "ON") + and self.test == "histsampling") + ) + self.skip_if(skip, 'skipping expected failures') @run_before('compile') def set_build_system(self): @@ -75,15 +91,15 @@ def set_build_system(self): f"cd src" ] self.build_system.config_opts = [ + # f'-DCAN_DATADUMP={self.datadump}', # '-DCMAKE_C_COMPILER=mpicc', # '-DCMAKE_CXX_COMPILER=mpicxx', - '-DCMAKE_BUILD_TYPE=Debug', # Release + f'-DCMAKE_BUILD_TYPE=Debug', # Release f'-DSTRIDED_SCALARS={self.aos}', f'-DSPH_DOUBLE={self.fp64}', f'-DCAN_LOAD_TIPSY={self.tipsy}', f'-DCAN_LOAD_H5Part={self.h5part}', - # f'-DCAN_DATADUMP={self.datadump}', - '-DINSITU=Ascent', + f'-DINSITU=Ascent', f'-DAscent_DIR={self.ascentdir}', ] if uenv.uarch(self.current_partition) == 'gh200': From 735d66357f832ac80d9a75bf1e5302747a6c7c5b Mon Sep 17 00:00:00 2001 From: Jg_Piccinali <> Date: Thu, 2 Oct 2025 16:54:41 +0200 Subject: [PATCH 6/8] Update test --- checks/apps/dummysph/dummysph.py | 55 +++++++++++++++++++------------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/checks/apps/dummysph/dummysph.py b/checks/apps/dummysph/dummysph.py index 54a708bdf..f85f67e01 100644 --- a/checks/apps/dummysph/dummysph.py +++ b/checks/apps/dummysph/dummysph.py @@ -1,8 +1,9 @@ -# Copyright 2025 Swiss National Supercomputing Centre (CSCS/ETH Zurich) +# Copyright Swiss National Supercomputing Centre (CSCS/ETH Zurich) # ReFrame Project Developers. See the top-level LICENSE file for details. # # SPDX-License-Identifier: BSD-3-Clause +import os import reframe as rfm import reframe.utility.sanity as sn import uenv @@ -11,37 +12,33 @@ @rfm.simple_test class DummySPH_Uenv_Ascent_Single(rfm.RegressionTest): descr = "Build and Run Ascent tests with DummySPH" - valid_systems = ['+remote'] - valid_prog_environs = ['+uenv +cuda'] - ascentdir = variable( - str, - value=('/capstor/store/cscs/cscs/csstaff/jfavre/ascent/0.9.4/lib/' - 'cmake/ascent') - ) - # TODO: deploy a uenv with ascent, - # until then using (local install + prgenv-gnu/24.11:v2) + valid_systems = ['+uenv'] + valid_prog_environs = ['+ascent +uenv -cpe'] sourcesdir = 'https://github.com/jfavre/DummySPH.git' tag = variable(str, value='92a06a1') # v0.1 - aos = parameter(['OFF']) # STRIDED_SCALARS: - # ON = struct tipsy (AOS) / OFF = std::vector (SOA) + + aos = parameter(['OFF']) # ON=struct tipsy (AOS) / OFF = std::vector (SOA) fp64 = parameter(['OFF', 'ON']) # OFF=, ON= - input_dir = variable( - str, value='/capstor/store/cscs/cscs/csstaff/jfavre/ascent') tipsy = parameter(['OFF', 'ON']) - tipsy_file = variable(str, value='hr8799_bol_bd1.017300') - # https://jfrog.svc.cscs.ch/artifactory/cscs-reframe-tests/dummysph/ - # -> hr8799_bol_bd1.017300.gz (1.06G) will take ~33 s (39.0MB/s) h5part = parameter(['OFF', 'ON']) + test = parameter(['rendering', 'thresholding', 'compositing', 'binning', + 'histsampling']) + + # --- input data: + # In https://jfrog.svc.cscs.ch/artifactory/cscs-reframe-tests/dummysph/ + # but loading ~1G (hr8799_bol_bd1.017300.gz) will take ~33 s (40 MB/s) + # -> using CSCS resourcesdir instead + # -> or /capstor/store/cscs/cscs/csstaff/jfavre/ascent + tipsy_file = variable(str, value='hr8799_bol_bd1.017300') h5part_file = variable(str, value='dump_wind-shock.h5') - test = parameter(['rendering', 'thresholding', 'compositing', - 'histsampling', 'binning']) + datadump = variable(str, value='OFF') - num_gpus = variable(int, value=4) build_system = 'CMake' build_locally = False executable = './src/bin/dummysph_ascent' time_limit = '4m' + # {{{ skip unsupported tests @run_after('init') def skip_test(self): """ @@ -79,6 +76,12 @@ def skip_test(self): and self.test == "histsampling") ) self.skip_if(skip, 'skipping expected failures') + # }}} + + @run_before('compile') + def set_input_dir(self): + self.input_dir = os.path.join(self.current_system.resourcesdir, + 'ascent', 'inputs') @run_before('compile') def set_build_system(self): @@ -88,22 +91,28 @@ def set_build_system(self): f"git checkout {self.tag}", f"git switch -c {self.tag}", f"touch _{self.aos}_{self.fp64}_{self.tipsy}_{self.h5part}", - f"cd src" + f"cd src", + # temporary workaround until new release: + f'cp {self.input_dir}/../CMakeLists.txt .', + f'sed -i "s-CAMP_HAVE_CUDA)-CAMP_HAVE_CUDA) || defined (ASCENT_CUDA_ENABLED)-" cuda_helpers.cpp', ] self.build_system.config_opts = [ # f'-DCAN_DATADUMP={self.datadump}', # '-DCMAKE_C_COMPILER=mpicc', # '-DCMAKE_CXX_COMPILER=mpicxx', f'-DCMAKE_BUILD_TYPE=Debug', # Release + f'-DCMAKE_CUDA_HOST_COMPILER=mpicxx', f'-DSTRIDED_SCALARS={self.aos}', f'-DSPH_DOUBLE={self.fp64}', f'-DCAN_LOAD_TIPSY={self.tipsy}', f'-DCAN_LOAD_H5Part={self.h5part}', f'-DINSITU=Ascent', - f'-DAscent_DIR={self.ascentdir}', + f'-DAscent_DIR=`find /user-tools/ -name ascent |grep ascent- |grep cmake`' # noqa: E402 ] if uenv.uarch(self.current_partition) == 'gh200': - cmake_arch = '-DCMAKE_CUDA_ARCHITECTURES=90' + cmake_arch = ( + '-DCMAKE_CUDA_ARCHITECTURES=90 ' + '-DCMAKE_CUDA_HOST_COMPILER=mpicxx') self.build_system.config_opts.append(cmake_arch) @run_before('run') From 3127b94d20fb72abdb47443d3526c86548b9b9b1 Mon Sep 17 00:00:00 2001 From: Jg_Piccinali <> Date: Mon, 20 Oct 2025 20:52:54 +0200 Subject: [PATCH 7/8] fix for review --- checks/apps/dummysph/dummysph.py | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/checks/apps/dummysph/dummysph.py b/checks/apps/dummysph/dummysph.py index f85f67e01..c1c05ce5e 100644 --- a/checks/apps/dummysph/dummysph.py +++ b/checks/apps/dummysph/dummysph.py @@ -10,13 +10,14 @@ @rfm.simple_test -class DummySPH_Uenv_Ascent_Single(rfm.RegressionTest): +class dummysph_uenv_ascent_single(rfm.RegressionTest): descr = "Build and Run Ascent tests with DummySPH" + maintainers = ['SSA'] valid_systems = ['+uenv'] valid_prog_environs = ['+ascent +uenv -cpe'] sourcesdir = 'https://github.com/jfavre/DummySPH.git' - tag = variable(str, value='92a06a1') # v0.1 - + commit = variable(str, value='92a06a1') # v0.1 + # aos = parameter(['OFF']) # ON=struct tipsy (AOS) / OFF = std::vector (SOA) fp64 = parameter(['OFF', 'ON']) # OFF=, ON= tipsy = parameter(['OFF', 'ON']) @@ -88,13 +89,14 @@ def set_build_system(self): self.build_system.max_concurrency = 6 self.build_system.srcdir = 'src' self.prebuild_cmds += [ - f"git checkout {self.tag}", - f"git switch -c {self.tag}", + f"git checkout {self.commit}", + f"git switch -c {self.commit}", f"touch _{self.aos}_{self.fp64}_{self.tipsy}_{self.h5part}", f"cd src", - # temporary workaround until new release: + # temporary workaround until new release of DummySPH: f'cp {self.input_dir}/../CMakeLists.txt .', - f'sed -i "s-CAMP_HAVE_CUDA)-CAMP_HAVE_CUDA) || defined (ASCENT_CUDA_ENABLED)-" cuda_helpers.cpp', + f'sed -i "s-CAMP_HAVE_CUDA)-CAMP_HAVE_CUDA) || ' + f'defined (ASCENT_CUDA_ENABLED)-" cuda_helpers.cpp', ] self.build_system.config_opts = [ # f'-DCAN_DATADUMP={self.datadump}', @@ -109,11 +111,17 @@ def set_build_system(self): f'-DINSITU=Ascent', f'-DAscent_DIR=`find /user-tools/ -name ascent |grep ascent- |grep cmake`' # noqa: E402 ] + cmake_arch = '' if uenv.uarch(self.current_partition) == 'gh200': cmake_arch = ( '-DCMAKE_CUDA_ARCHITECTURES=90 ' '-DCMAKE_CUDA_HOST_COMPILER=mpicxx') - self.build_system.config_opts.append(cmake_arch) + elif uenv.uarch(self.current_partition) == 'a100': + cmake_arch = ( + '-DCMAKE_CUDA_ARCHITECTURES=80 ' + '-DCMAKE_CUDA_HOST_COMPILER=mpicxx') + + self.build_system.config_opts.append(cmake_arch) @run_before('run') def set_executable_tests(self): From 970f1fad6143dd7b7ecc429f2d35a84a90215d6a Mon Sep 17 00:00:00 2001 From: Jg_Piccinali <> Date: Mon, 20 Oct 2025 21:07:30 +0200 Subject: [PATCH 8/8] fix for review --- checks/apps/dummysph/dummysph.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/checks/apps/dummysph/dummysph.py b/checks/apps/dummysph/dummysph.py index c1c05ce5e..6f5bfb437 100644 --- a/checks/apps/dummysph/dummysph.py +++ b/checks/apps/dummysph/dummysph.py @@ -66,6 +66,7 @@ def skip_test(self): # "Field type unsupported for conversion to blueprint": (self.aos == "OFF" and (self.fp64 == "OFF" or self.fp64 == "ON") + # intentionally redundant and self.tipsy == "OFF" and self.h5part == "OFF" and self.test == "compositing") or @@ -89,6 +90,7 @@ def set_build_system(self): self.build_system.max_concurrency = 6 self.build_system.srcdir = 'src' self.prebuild_cmds += [ + # https://github.com/jfavre/DummySPH/releases/ f"git checkout {self.commit}", f"git switch -c {self.commit}", f"touch _{self.aos}_{self.fp64}_{self.tipsy}_{self.h5part}", @@ -126,7 +128,6 @@ def set_build_system(self): @run_before('run') def set_executable_tests(self): self.job.options = [f'--nodes=1'] - self.rpt = 'rpt' infile = '' if self.h5part == "ON": infile = f'--h5part {self.input_dir}/{self.h5part_file}'