forked from easybuilders/easybuild-easyblocks
-
Notifications
You must be signed in to change notification settings - Fork 0
Update GROMACS easyblock #28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
d293c4f
GROMACS: new build-option 'mpi_only'
ostueker 17ad339
support 'X86-64-V?' style Microarchitecture levels in optarch
ostueker a4e7650
EB_GROMACS: fix linter
ostueker 1d0f8e8
EB_GROMACS: more control over building gmxapi Python package
ostueker 49e82b1
EB_GROMACS: finer control over PLUMED support (internal or patching)
ostueker 9fe6942
GROMACS: improve PLUMED patching logic
ostueker 5aabcf9
remove print statements added for debugging
ostueker 1677da6
GROMACS: add option plumed = 'native'
ostueker 83647f5
use native PLUMED by default with GROMACS 2026+
ostueker 5f7317b
GROMACS: fix native PLUMED support instead of patching
ostueker File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -70,10 +70,15 @@ def extra_options(): | |
| 'mpisuffix': ['_mpi', "Suffix to append to MPI-enabled executables (only for GROMACS < 4.6)", CUSTOM], | ||
| 'mpiexec': ['mpirun', "MPI executable to use when running tests", CUSTOM], | ||
| 'mpiexec_numproc_flag': ['-np', "Flag to introduce the number of MPI tasks when running tests", CUSTOM], | ||
| 'mpi_only': [False, "Only build for MPI and skip nompi.", CUSTOM], | ||
| 'mpi_numprocs': [0, "Number of MPI tasks to use when running tests", CUSTOM], | ||
| 'python_pkg': [None, "Build gmxapi Python package. None (default) is auto-detect." + | ||
| "True or False forces behaviour.", CUSTOM], | ||
| 'ignore_plumed_version_check': [False, "Ignore the version compatibility check for PLUMED", CUSTOM], | ||
| 'plumed': [None, "Try to apply PLUMED patches. None (default) is auto-detect. " + | ||
| "True or False forces behaviour.", CUSTOM], | ||
| 'plumed': [None, "Try to enable PLUMED support. None (default) is auto-detect. " + | ||
| "'native' enables native PLUMED support for GROMACS 2025 and newer." + | ||
| "'patch' (or True) applies PLUMED patches." + | ||
| "False disables PLUMED support.", CUSTOM], | ||
| }) | ||
| return extra_vars | ||
|
|
||
|
|
@@ -117,13 +122,13 @@ def get_gromacs_arch(self): | |
| # http://manual.gromacs.org/documentation/2018/install-guide/index.html#simd-support | ||
| if 'MIC-AVX512' in optarch and LooseVersion(self.version) >= LooseVersion('2016'): | ||
| res = 'AVX_512_KNL' | ||
| elif 'AVX512' in optarch and LooseVersion(self.version) >= LooseVersion('2016'): | ||
| elif ('AVX512' in optarch or 'X86-64-V4' in optarch) and LooseVersion(self.version) >= LooseVersion('2016'): | ||
| res = 'AVX_512' | ||
| elif 'AVX2' in optarch and LooseVersion(self.version) >= LooseVersion('5.0'): | ||
| elif ('AVX2' in optarch or 'X86-64-V3' in optarch) and LooseVersion(self.version) >= LooseVersion('5.0'): | ||
| res = 'AVX2_256' | ||
| elif 'AVX' in optarch: | ||
| res = 'AVX_256' | ||
| elif 'SSE3' in optarch or 'SSE2' in optarch or 'MARCH=NOCONA' in optarch: | ||
| elif 'SSE3' in optarch or 'SSE2' in optarch or 'MARCH=NOCONA' in optarch or 'X86-64-V2' in optarch: | ||
| # Gromacs doesn't have any GMX_SIMD=SSE3 but only SSE2 and SSE4.1 [1]. | ||
| # According to [2] the performance difference between SSE2 and SSE4.1 is minor on x86 | ||
| # and SSE4.1 is not supported by AMD Magny-Cours[1]. | ||
|
|
@@ -215,43 +220,81 @@ def configure_step(self): | |
| self.cfg.update('configopts', "-DGMX_GPU=OFF") | ||
|
|
||
| # PLUMED detection | ||
| # enable PLUMED support if PLUMED is listed as a dependency | ||
| # and PLUMED support is either explicitly enabled (plumed = True) or unspecified ('plumed' not defined) | ||
| # enable PLUMED support if PLUMED is listed as a dependency. | ||
| # plumed = 'native' will enable GROMACS' native PLUMED support ('-DGMX_USE_PLUMED=ON') | ||
| # for GROMACS 2025 and newer. plumed = 'patch' specifically requests PLUMED patches. | ||
| # In auto-detect ('plumed = None' or not defined) will prefer native support for 2026 | ||
| # and newer. Older versions of GROMACS patches are applied to enable PLUMED support. | ||
| # plumed = True behaves like plumed = 'patch' for backwards compatibility. | ||
| plumed_root = get_software_root('PLUMED') | ||
| plumed_patches = False | ||
| if self.cfg['plumed'] and not plumed_root: | ||
| msg = "PLUMED support has been requested but PLUMED is not listed as a dependency." | ||
| raise EasyBuildError(msg) | ||
| elif plumed_root and self.cfg['plumed'] is False: | ||
| self.log.info('PLUMED was found, but compilation without PLUMED has been requested.') | ||
| plumed_root = None | ||
| elif plumed_root and self.cfg['plumed'] == 'patch': | ||
| self.log.info('PLUMED was found, and PLUMED patching has been requested.') | ||
| plumed_patches = True | ||
| elif plumed_root and self.cfg['plumed'] == 'native': | ||
| msg = 'PLUMED was found, and native PLUMED support has been requested.' | ||
| if gromacs_version >= '2025': | ||
| msg += ' Will use native PLUMED support.' | ||
| plumed_patches = False | ||
| self.log.info(msg) | ||
| else: | ||
| msg += " Native PLUMED support is only available with GROMACS 2025 and newer." | ||
| raise EasyBuildError(msg) | ||
| elif plumed_root and self.cfg['plumed'] is True: | ||
| msg = 'PLUMED was found, and PLUMED support has been requested.' | ||
| msg += ' Will apply PLUMED patches.' | ||
| plumed_patches = True | ||
| self.log.info(msg) | ||
| elif plumed_root and self.cfg['plumed'] is None: | ||
| msg = 'PLUMED was found.' | ||
| if gromacs_version >= '2026': | ||
| # Even though native support is available since GROMACS 2025, we'll only use | ||
| # it as default with 2026 and newer to avoid a sudden change in behaviour. | ||
| msg += ' Will use native PLUMED support.' | ||
| plumed_patches = False | ||
| else: | ||
| msg += ' Will apply PLUMED patches.' | ||
| plumed_patches = True | ||
| self.log.info(msg) | ||
|
|
||
| if plumed_root: | ||
| self.log.info('PLUMED support has been enabled.') | ||
|
|
||
| # Need to check if PLUMED has an engine for this version | ||
| engine = 'gromacs-%s' % self.version | ||
| if gromacs_version >= '2025' and plumed_patches is False: | ||
| self.log.info('Native PLUMED support has been enabled.') | ||
| self.cfg.update('configopts', '-DGMX_USE_PLUMED=ON') | ||
|
|
||
| res = run_shell_cmd("plumed-patch -l") | ||
| if not re.search(engine, res.output): | ||
| plumed_ver = get_software_version('PLUMED') | ||
| msg = "There is no support in PLUMED version %s for GROMACS %s: %s" % (plumed_ver, self.version, | ||
| res.output) | ||
| if self.cfg['ignore_plumed_version_check']: | ||
| self.log.warning(msg) | ||
| else: | ||
| raise EasyBuildError(msg) | ||
| else: | ||
| # Need to check if PLUMED has an engine for this version | ||
| engine = 'gromacs-%s' % self.version | ||
|
|
||
| res = run_shell_cmd("plumed-patch -l") | ||
| if not re.search(engine, res.output): | ||
| plumed_ver = get_software_version('PLUMED') | ||
| msg = "There is no support in PLUMED version %s for GROMACS %s: %s" % (plumed_ver, self.version, | ||
| res.output) | ||
| if self.cfg['ignore_plumed_version_check']: | ||
| self.log.warning(msg) | ||
| else: | ||
| raise EasyBuildError(msg) | ||
|
|
||
| # PLUMED patching must be done at different stages depending on | ||
| # version of GROMACS. Just prepare first part of cmd here | ||
| plumed_cmd = "plumed-patch -p -e %s" % engine | ||
| # PLUMED patching must be done at different stages depending on | ||
| # version of GROMACS. Just prepare first part of cmd here | ||
| plumed_cmd = "plumed-patch -p -e %s" % engine | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Long options: |
||
|
|
||
| # Ensure that the GROMACS log files report how the code was patched | ||
| # during the build, so that any problems are easier to diagnose. | ||
| # The GMX_VERSION_STRING_OF_FORK feature is available since 2020. | ||
| if (gromacs_version >= '2020' and | ||
| '-DGMX_VERSION_STRING_OF_FORK=' not in self.cfg['configopts']): | ||
| gromacs_version_string_suffix = 'EasyBuild-%s' % EASYBUILD_VERSION | ||
| if plumed_root: | ||
| if plumed_patches: | ||
| gromacs_version_string_suffix += '-PLUMED-%s' % get_software_version('PLUMED') | ||
| self.cfg.update('configopts', '-DGMX_VERSION_STRING_OF_FORK=%s' % gromacs_version_string_suffix) | ||
|
|
||
|
|
@@ -291,7 +334,8 @@ def configure_step(self): | |
| ConfigureMake.configure_step(self) | ||
|
|
||
| # Now patch GROMACS for PLUMED between configure and build | ||
| if plumed_root: | ||
| if plumed_root and plumed_patches: | ||
| self.log.info('Applying PLUMED patches to GROMACS.') | ||
| run_shell_cmd(plumed_cmd) | ||
|
|
||
| else: | ||
|
|
@@ -330,7 +374,14 @@ def configure_step(self): | |
| if gromacs_version >= '2020': | ||
| # build Python bindings if Python is loaded as a dependency | ||
| python_root = get_software_root('Python') | ||
| if python_root: | ||
| if self.cfg['python_pkg'] is True and not python_root: | ||
| msg = "Building Python gmxapi has been requested but Python is not listed as a dependency." | ||
| raise EasyBuildError(msg) | ||
| elif python_root and self.cfg['python_pkg'] is False: | ||
| msg = "Python was found, but compilation without Python gmxapi has been requested." | ||
| self.log.info(msg) | ||
| self.cfg.update('configopts', "-DGMX_PYTHON_PACKAGE=OFF") | ||
| elif python_root: | ||
| self.cfg.update('configopts', "-DGMX_PYTHON_PACKAGE=ON") | ||
| bin_python = os.path.join(python_root, 'bin', 'python') | ||
| # For find_package(PythonInterp) | ||
|
|
@@ -340,7 +391,7 @@ def configure_step(self): | |
| self.cfg.update('configopts', "-DPython3_FIND_VIRTUALENV=STANDARD") | ||
|
|
||
| # Now patch GROMACS for PLUMED before cmake | ||
| if plumed_root: | ||
| if plumed_root and plumed_patches: | ||
| if gromacs_version >= '5.1': | ||
| # Use shared or static patch depending on | ||
| # setting of self.cfg['build_shared_libs'] | ||
|
|
@@ -655,8 +706,12 @@ def sanity_check_step(self): | |
| else: | ||
| mpisuff = '_mpi' | ||
|
|
||
| mpi_bins.extend([binary + mpisuff for binary in mpi_bins]) | ||
| mpi_libnames.extend([libname + mpisuff for libname in mpi_libnames]) | ||
| if self.cfg['mpi_only']: | ||
| mpi_bins = [binary + mpisuff for binary in mpi_bins] | ||
| mpi_libnames = [libname + mpisuff for libname in mpi_libnames] | ||
| else: | ||
| mpi_bins.extend([binary + mpisuff for binary in mpi_bins]) | ||
| mpi_libnames.extend([libname + mpisuff for libname in mpi_libnames]) | ||
|
|
||
| suffixes = [''] | ||
|
|
||
|
|
@@ -769,9 +824,12 @@ def run_all_steps(self, *args, **kwargs): | |
| if precisions == []: | ||
| raise EasyBuildError("No precision selected. At least one of single/double_precision must be unset or True") | ||
|
|
||
| mpitypes = ['nompi'] | ||
| if self.toolchain.options.get('usempi', None): | ||
| mpitypes.append('mpi') | ||
| if self.cfg['mpi_only']: | ||
| mpitypes = ['mpi'] | ||
| else: | ||
| mpitypes = ['nompi'] | ||
| if self.toolchain.options.get('usempi', None): | ||
| mpitypes.append('mpi') | ||
|
|
||
| # We need to count the number of variations to build. | ||
| versions_built = [] | ||
|
|
||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A long command line option would facilitate understanding for those less familiar with PLUMED:
--plumed-patch --list-engines.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks.
Those lines originate from upstream. I just idented them while adding an additional if-clause.
I'll suggest that change for my upstream PR.