Skip to content

Commit a4a41b3

Browse files
authored
Merge pull request #309 from satishskamath/walberla
Walberla [Ready for testing/merging]
2 parents de02195 + ca7973e commit a4a41b3

File tree

2 files changed

+141
-0
lines changed

2 files changed

+141
-0
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# WARNING: do not remove this file.
2+
# It is needed to autogenerate documentation from this repo.
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
"""
2+
This module tests the binary 05_BackwardFacingStep in available modules containing substring 'waLBerla'.
3+
The test is taken from the existing tutorials within the walberla repository:
4+
https://github.com/lssfau/walberla/tree/master/apps/tutorials/lbm
5+
6+
License information can be found here:
7+
https://github.com/lssfau/walberla/blob/master/COPYING.txt
8+
9+
"""
10+
11+
import reframe as rfm
12+
# added only to make the linter happy
13+
from reframe.core.builtins import deferrable, parameter, run_after, run_before, sanity_function, performance_function
14+
import reframe.utility.sanity as sn
15+
from eessi.testsuite.constants import COMPUTE_UNITS, DEVICE_TYPES, SCALES
16+
from eessi.testsuite.eessi_mixin import EESSI_Mixin
17+
from eessi.testsuite.utils import find_modules
18+
19+
20+
def filter_scales():
21+
"""
22+
Filtering function for filtering scales for the waLBerla test returns all scales from 8 cores to 2 nodes. This is
23+
because this case is testing strong scaling and the number of cells per MPI process become too less typically once
24+
it crosses 2 nodes. Further filtering is done within the test based on MPI tasks. The code is capable of running on
25+
1 to 4 cores as well but it will take about 1 hour to run on a single core.
26+
"""
27+
return [
28+
k for (k, v) in SCALES.items()
29+
if ((v['num_nodes'] <= 2) and (v.get('node_part', 0) != 0)) or (v.get('num_cpus_per_node', 0) > 4)
30+
]
31+
32+
33+
@rfm.simple_test
34+
class EESSI_WALBERLA_BACKWARD_FACING_STEP(rfm.RunOnlyRegressionTest, EESSI_Mixin):
35+
"""
36+
This is the main walberla class for the backward facing step test. The test consists of steps that modify the input
37+
file from the precompiled walberla tutorials binary. These are run as pre-run commands and the main test with the
38+
executable `05_BackwardFacingStep` is measured for performance.
39+
The code will run on one core but will take about an hour to run therefore this test is implemented to execute on
40+
at least 8 cores and at most 384 cores.
41+
"""
42+
executable = '05_BackwardFacingStep'
43+
executable_opts = ['05_BackwardFacingStep.prm']
44+
time_limit = '30m'
45+
readonly_files = ['']
46+
device_type = parameter([DEVICE_TYPES.CPU])
47+
module_name = parameter(find_modules('waLBerla'))
48+
valid_systems = ['*']
49+
scale = parameter(filter_scales())
50+
51+
@run_after('init')
52+
def set_compute_unit(self):
53+
"""
54+
This test is a CPU only test.
55+
Set the compute unit to which tasks will be assigned:
56+
one task per CPU core for CPU runs.
57+
"""
58+
if self.device_type == DEVICE_TYPES.CPU:
59+
self.compute_unit = COMPUTE_UNITS.CPU
60+
else:
61+
msg = f"No mapping of device type {self.device_type} to a COMPUTE_UNITS was specified in this test"
62+
raise NotImplementedError(msg)
63+
64+
def required_mem_per_node(self):
65+
return (400 + self.num_tasks_per_node * 300)
66+
67+
@run_after('setup')
68+
def check_core_count(self):
69+
# The walberla backward facing step test case can run on a max of 384 cores and a minimum of 8 cores to run
70+
# within reasonable time.
71+
if self.num_tasks > 384:
72+
self.skip(msg="The maximum number of cores that the strong scaling can hold for this test is 384. Launch on"
73+
"a scale with a smaller core count.")
74+
elif self.num_tasks < 8:
75+
self.skip(msg="The minimum number of MPI tasks required for this test is 8 to run within reasonable time."
76+
"Launch of scale with larger core count")
77+
78+
@run_before('run')
79+
def prepare_environment(self):
80+
"""
81+
Function:
82+
1. Copying the built binary from the tutorial section of the relevant waLBerla module.
83+
2. Modifying the input prm file to adjust for number of MPI tasks (blocks) and cells per block keeping the
84+
domain size same.
85+
3. Adjusting timesteps since the run need not be that long as in the original input prm file.
86+
"""
87+
# The sed commands below are just editing the input file 05_BackwardFacingStep.prm and only the first parameter
88+
# within blocks and cells per block. The whole idea is to keep the number of cells around the value of 6000 in
89+
# the x direction. Since this is a cartesian system, the default is assigned is one process per block. This is
90+
# as per walberla source code and the runs would crash if there is a mismatch between total number of blocks and
91+
# number of MPI ranks.
92+
# Note: It is also possible to edit the y component or the second parameter of the blocks and cellsPerBlock BUT
93+
# this would vary the viscosity of the of the fluid with the number of MPI processes because this is hardcoded
94+
# within the compiled tutorial source code to use this length to calculate the Reynolds number within the
95+
# channel. For this the source code needs to be modified to include the number of MPI processes so that the
96+
# problem at hand does not change which would in turn need recompilation, therefore only x parameter is varied.
97+
# The last sed command limits the timesteps to 300000 instead of 10000000 because the quasi steady state is
98+
# already reached.
99+
self.prerun_cmds = [
100+
'cp -r ${EBROOTWALBERLA}/build/apps/tutorials/lbm .',
101+
'chmod -R u+w lbm',
102+
'cd lbm',
103+
f"sed -i -r 's/(blocks\\s*)<\\s*1,\\s*1,\\s*1\\s*>/\\1< {self.num_tasks} , 1, 1 >/g'"
104+
" 05_BackwardFacingStep.prm",
105+
f"sed -i -r 's/(cellsPerBlock\\s*)<\\s*6000,\\s*100,\\s*1\\s*>/\\1< {int(6000 / self.num_tasks) + 1} "
106+
", 100, 1 >/g' 05_BackwardFacingStep.prm",
107+
"sed -i -r 's/(timesteps\\s*)10000000/\\1300000/g' 05_BackwardFacingStep.prm "]
108+
109+
@deferrable
110+
def check_files(self):
111+
''' Check for all the log files present. '''
112+
return (sn.path_isfile("./lbm/vtk_05_BackwardFacingStep/fluid_field.pvd")
113+
and sn.path_isfile("./lbm/vtk_05_BackwardFacingStep/flag_field.pvd"))
114+
115+
@deferrable
116+
def assert_completion(self):
117+
''' Checking for completion string within stdout and number of output timesteps within vtk. '''
118+
n_time_steps = sn.count(sn.extractall(
119+
'DataSet timestep="(?P<timestep>[0-9]+)"', "./lbm/vtk_05_BackwardFacingStep/fluid_field.pvd",
120+
tag='timestep'))
121+
return (sn.assert_found("END LOGGING -", self.stdout,
122+
msg="The run did not finish, the logger did not indicate completion. Check for errors.")
123+
and sn.assert_eq(n_time_steps, 15))
124+
125+
@performance_function('s/timestep')
126+
def perf(self):
127+
''' Collecting performance timings within the log and computing average performance time per step. '''
128+
perftimes = sn.extractall(r'[INFO\s*].*\((?P<perf>\S+)\s+sec\)\[(?P<numsteps>.*)\]', self.stdout,
129+
tag=['perf', 'numsteps'], conv=float)
130+
seconds_per_timestep = perftimes[-1][0] / perftimes[-1][1]
131+
return seconds_per_timestep
132+
133+
@sanity_function
134+
def assert_sanity(self):
135+
''' Check all sanity criteria. '''
136+
return sn.all([
137+
self.check_files(),
138+
self.assert_completion(),
139+
])

0 commit comments

Comments
 (0)