Source code for hpctestlib.sciapps.amber.nve

# Copyright 2016-2022 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 reframe as rfm
import reframe.utility.sanity as sn

[docs]@rfm.simple_test class amber_nve_check(rfm.RunOnlyRegressionTest, pin_prefix=True): '''Amber NVE test. `Amber <>`__ is a suite of biomolecular simulation programs. It began in the late 1970's, and is maintained by an active development community. This test is parametrized over the benchmark type (see :attr:`benchmark_info`) and the variant of the code (see :attr:`variant`). Each test instance executes the benchmark, validates numerically its output and extracts and reports a performance metric. ''' #: The output file to pass to the Amber executable. #: #: :type: :class:`str` #: :required: No #: :default: ``'amber.out'`` output_file = variable(str, value='amber.out') #: The input file to use. #: #: This is set to ``mdin.CPU`` or ``mdin.GPU`` depending on the test #: variant during initialization. #: #: :type: :class:`str` #: :required: Yes input_file = variable(str) #: Parameter pack encoding the benchmark information. #: #: The first element of the tuple refers to the benchmark name, #: the second is the energy reference and the third is the #: tolerance threshold. #: #: :type: `Tuple[str, float, float]` #: :values: #: .. code-block:: python #: #: [ #: ('Cellulose_production_NVE', -443246.0, 5.0E-05), #: ('FactorIX_production_NVE', -234188.0, 1.0E-04), #: ('JAC_production_NVE_4fs', -44810.0, 1.0E-03), #: ('JAC_production_NVE', -58138.0, 5.0E-04) #: ] benchmark_info = parameter([ ('Cellulose_production_NVE', -443246.0, 5.0E-05), ('FactorIX_production_NVE', -234188.0, 1.0E-04), ('JAC_production_NVE_4fs', -44810.0, 1.0E-03), ('JAC_production_NVE', -58138.0, 5.0E-04) ], fmt=lambda x: x[0]) # Parameter encoding the variant of the test. # # :type:`str` # :values: ``['mpi', 'cuda']`` variant = parameter(['mpi', 'cuda'], loggable=True) # Test tags # # :required: No # :default: ``{'sciapp', 'chemistry'}`` tags = {'sciapp', 'chemistry'} #: See :attr:`~reframe.core.pipeline.RegressionTest.num_tasks`. #: #: The ``mpi`` variant of the test requires ``num_tasks > 1``. #: #: :required: Yes num_tasks = required @loggable @property def bench_name(self): '''The benchmark name. :type: :class:`str` ''' return self.__bench @property def energy_ref(self): '''The energy reference value for this benchmark. :type: :class:`str` ''' return self.__nrg_ref @property def energy_tol(self): '''The energy tolerance value for this benchmark. :type: :class:`str` ''' return self.__nrg_tol @run_after('init') def prepare_test(self): self.__bench, self.__nrg_ref, self.__nrg_tol = self.benchmark_info self.descr = f'Amber NVE {self.bench_name} benchmark ({self.variant})' params = { 'mpi': ('mdin.CPU', 'pmemd.MPI'), 'cuda': ('mdin.GPU', 'pmemd.cuda.MPI') } try: self.input_file, self.executable = params[self.variant] except KeyError: raise ValueError( f'test not set up for platform {self.variant!r}' ) from None self.prerun_cmds = [ f'curl -LJO{self.bench_name}.tar.bz2', # noqa: E501 f'tar xf {self.bench_name}.tar.bz2' ] self.executable_opts = ['-O', '-i', self.input_file, '-o', self.output_file] self.keep_files = [self.output_file]
[docs] @performance_function('ns/day') def perf(self): '''The performance of the benchmark expressed in ``ns/day``.''' return sn.extractsingle(r'ns/day =\s+(?P<perf>\S+)', self.output_file, 'perf', float, item=1)
[docs] @sanity_function def assert_energy_readout(self): '''Assert that the obtained energy meets the required tolerance.''' energy = sn.extractsingle(r' Etot\s+=\s+(?P<energy>\S+)', self.output_file, 'energy', float, item=-2) energy_diff = sn.abs(energy - self.energy_ref) ref_ener_diff = sn.abs(self.energy_ref * self.energy_tol) return sn.all([ sn.assert_found(r'Final Performance Info:', self.output_file), sn.assert_lt(energy_diff, ref_ener_diff) ])