From b520b2e84bdfd88bc8c4b1f2d23e66227f3a29f2 Mon Sep 17 00:00:00 2001 From: sassy Date: Thu, 22 Sep 2022 14:23:35 +0100 Subject: [PATCH 01/41] Working EasyBlock for newer versions of GAMESS-US, based on PR #1925 --- easybuild/easyblocks/g/gamess_us.py | 237 ++++++++++++++++++++++------ 1 file changed, 185 insertions(+), 52 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 4d658a7c0e..35a92812b4 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -1,5 +1,5 @@ ## -# Copyright 2009-2022 Ghent University +# Copyright 2009-2020 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -37,17 +37,20 @@ import fileinput import glob import os +import random import re import shutil import sys import tempfile +import fnmatch from easybuild.framework.easyblock import EasyBlock from easybuild.framework.easyconfig import CUSTOM, MANDATORY from easybuild.tools.build_log import EasyBuildError from easybuild.tools.config import build_option -from easybuild.tools.filetools import read_file, write_file +from easybuild.tools.filetools import change_dir, read_file, write_file from easybuild.tools.modules import get_software_root, get_software_version +from easybuild.tools.py2vs3 import ascii_letters from easybuild.tools.run import run_cmd, run_cmd_qa from easybuild.tools.systemtools import get_platform_name from easybuild.tools import toolchain @@ -64,6 +67,7 @@ def extra_options(): 'maxcpus': [None, "Maximum number of cores per node", MANDATORY], 'maxnodes': [None, "Maximum number of nodes", MANDATORY], 'runtest': [True, "Run GAMESS-US tests", CUSTOM], + 'omp': [False, "Enabling OpenMP", CUSTOM], 'scratch_dir': ['$TMPDIR', "Scratch dir to be used in rungms script", CUSTOM], } return EasyBlock.extra_options(extra_vars) @@ -77,8 +81,10 @@ def __init__(self, *args, **kwargs): self.testdir = tempfile.mkdtemp() # make sure test dir doesn't contain [ or ], rungms csh script doesn't handle that well ("set: No match") if re.search(r'[\[\]]', self.testdir): - error_msg = "Temporary dir for tests '%s' will cause problems with rungms csh script" - raise EasyBuildError(error_msg, self.testdir) + raise EasyBuildError("Temporary dir for tests '%s' will cause problems with rungms csh script", + self.testdir) + + self.scratch_dir = self.cfg['scratch_dir'] def extract_step(self): """Extract sources.""" @@ -88,12 +94,17 @@ def extract_step(self): def configure_step(self): """Configure GAMESS-US build via provided interactive 'config' script.""" - + """Opening install.info file as append""" + f = open(self.builddir + "/install.info", "a") + f.writelines(["setenv GMS_PATH " + self.builddir + "\n" + "setenv GMS_BUILD_DIR " + self.installdir + "\n"]) # machine type platform_name = get_platform_name() x86_64_linux_re = re.compile('^x86_64-.*$') if x86_64_linux_re.match(platform_name): machinetype = "linux64" + f.writelines(["setenv GMS_TARGET " + machinetype + "\n" + + "setenv GMS_HPC_SYSTEM_TARGET generic" + "\n"]) else: raise EasyBuildError("Build target %s currently unsupported", platform_name) @@ -114,6 +125,9 @@ def configure_step(self): else: raise EasyBuildError("Compiler family '%s' currently unsupported.", comp_fam) + f.writelines(["setenv GMS_FORTRAN " + fortran_comp + "\n" + + "setenv GMS_GFORTRAN_VERNO " + fortran_ver + "\n"]) + # math library config known_mathlibs = ['imkl', 'OpenBLAS', 'ATLAS', 'ACML'] mathlib, mathlib_root = None, None @@ -125,15 +139,38 @@ def configure_step(self): raise EasyBuildError("None of the known math libraries (%s) available, giving up.", known_mathlibs) if mathlib == 'imkl': mathlib = 'mkl' - mathlib_root = os.path.join(mathlib_root, 'mkl') + mathlib_vers_res = '.'.join(get_software_version('imkl').split('.')[:1]) + if int(mathlib_vers_res) == 2020: + mathlib_root = os.path.join(mathlib_root, 'mkl/lib/intel64') + elif int(mathlib_vers_res) == 2021: + mathlib_root = os.path.join(mathlib_root, 'mkl/latest/lib/intel64') + + if int(mathlib_vers_res) >= 2020: + # For some GAMESS-US versions oneapi is not in lked, so we use 12-so instead + if self.version == "20200630-R1" or self.version == "20200930-R2": + mathlib_vers = "12-so" + elif self.version == "20210620-R1": + mathlib_vers = "12-so" + else: + mathlib_vers = "oneapi-so" + else: + mathlib_vers = "12" + else: mathlib = mathlib.lower() + f.writelines(["setenv GMS_MATHLIB " + mathlib + "\n" + + "setenv GMS_MATHLIB_PATH " + mathlib_root + "\n" + + "setenv GMS_MKL_VERNO " + mathlib_vers + "\n" + + "setenv GMS_LAPACK_LINK_LINE" + "" + "\n"]) + # verify selected DDI communication layer known_ddi_comms = ['mpi', 'mixed', 'shmem', 'sockets'] if not self.cfg['ddi_comm'] in known_ddi_comms: raise EasyBuildError("Unsupported DDI communication layer specified (known: %s): %s", known_ddi_comms, self.cfg['ddi_comm']) + + f.writelines(["setenv GMS_DDI_COMM " + self.cfg['ddi_comm'] + "\n" ]) # MPI library config mpilib, mpilib_root, mpilib_path = None, None, None @@ -154,38 +191,32 @@ def configure_step(self): else: mpilib, mpilib_root = '', '' - # run interactive 'config' script to generate install.info file - cmd = "%(preconfigopts)s ./config %(configopts)s" % { - 'preconfigopts': self.cfg['preconfigopts'], - 'configopts': self.cfg['configopts'], - } - qa = { - "After the new window is open, please hit to go on.": '', - "please enter your target machine name: ": machinetype, - "Version? [00] ": self.version, - "Please enter your choice of FORTRAN: ": fortran_comp, - "hit to continue to the math library setup.": '', - "MKL pathname? ": mathlib_root, - "MKL version (or 'skip')? ": 'skip', - "MKL version (or 'proceed')? ": 'proceed', # changed in gamess-20170420R1 - "please hit to compile the GAMESS source code activator": '', - "please hit to set up your network for Linux clusters.": '', - "communication library ('sockets' or 'mpi')? ": self.cfg['ddi_comm'], - "Enter MPI library (impi, mvapich2, mpt, sockets):": mpilib, - "Enter MPI library (impi, mpich, mpich2, mvapich2, mpt, sockets):": mpilib, # changed in gamess-20170420R1 - "Please enter your %s's location: " % mpilib: mpilib_root, - "Do you want to try LIBCCHEM? (yes/no): ": 'no', - "Enter full path to OpenBLAS libraries (without 'lib' subdirectory):": mathlib_root, - "Optional: Build Michigan State University CCT3 & CCSD3A methods? (yes/no): ": 'no', - } - stdqa = { - r"GAMESS directory\? \[.*\] ": self.builddir, - r"GAMESS build directory\? \[.*\] ": self.installdir, # building in install directory - r"Enter only the main version number, such as .*\nVersion\? ": fortran_ver, - r".+gfortran version.\n( \n)?Please enter only the first decimal place, such as .*:": fortran_ver, - "Enter your choice of 'mkl' or .* 'none': ": mathlib, - } - run_cmd_qa(cmd, qa=qa, std_qa=stdqa, log_all=True, simple=True) + f.writelines(["setenv GMS_MPI_LIB " + mpilib + "\n" + + "setenv GMS_MPI_PATH " + mpilib_root + "\n"]) + + # These are extra programs which for now we simply set all to FALSE + f. writelines(["setenv GMS_MSUCC false " + "\n"]) + f. writelines(["setenv GMS_LIBCCHEM false" + "\n"]) + f. writelines(["setenv GMS_PHI none " + "\n"]) + f. writelines(["setenv GMS_SHMTYPE sysv " + "\n"]) + + if self.cfg['omp'] == 'True': + f. writelines(["setenv GMS_OPENMP true" + "\n"]) + else: + f. writelines(["setenv GMS_OPENMP false" + "\n"]) + + f. writelines(["setenv GMS_LIBXC false " + "\n"]) + f. writelines(["setenv GMS_MDI false " + "\n"]) + f. writelines(["setenv GMS_VM2 false " + "\n"]) + f. writelines(["setenv TINKER false " + "\n"]) + f. writelines(["setenv VB2000 false " + "\n"]) + f. writelines(["setenv XMVB false " + "\n"]) + f. writelines(["setenv NEO false " + "\n"]) + f. writelines(["setenv NBO false " + "\n"]) + f. writelines(["setenv GMS_FPE_FLAGS " + "\n"]) + #f. writelines(["setenv GMS_FPE_FLAGS '-ffpe-trap=invalid,zero,overflow' " + "\n"]) # This seems to be useful for debugging + + f.close() self.log.debug("Contents of install.info:\n%s" % read_file(os.path.join(self.builddir, 'install.info'))) @@ -209,6 +240,107 @@ def configure_step(self): except IOError as err: raise EasyBuildError("Failed to patch %s: %s", rungms, err) + # Replacing the MAXCPUS and MAXNODES in compddi to a value from the EasyConfig file + compddi = os.path.join(self.builddir, 'ddi/compddi') + try: + for line in fileinput.input(compddi, inplace=1, backup='.orig'): + line = re.sub(r"^(\s*set MAXCPUS)=.*", r"\1=%s" % self.cfg['maxcpus'], line, 1) + line = re.sub(r"^(\s*set MAXNODES)=.*", r"\1=%s" % self.cfg['maxnodes'], line, 1) + sys.stdout.write(line) + except IOError as err: + raise EasyBuildError("Failed to patch compddi", compddi, err) + + # for GAMESS-US 20200630-R1 we need to build the actvte.x program + if self.version == "20200630-R1": + actvte = os.path.join(self.builddir, 'tools/actvte.code') + try: + for line in fileinput.input(actvte, inplace=1, backup='.orig'): + line = re.sub("\*UNX", " ", line) + sys.stdout.write(line) + except IOError as err: + raise EasyBuildError("Failed to patch actvte.code", actvte, err) + # compiling + run_cmd("mv %s/tools/actvte.code" % self.builddir + " %s/tools/actvte.f" % self.builddir) + run_cmd("%s -o " % fortran_comp + " %s/tools/actvte.x" % self.builddir + " %s/tools/actvte.f" % self.builddir) + + def build_step(self): + """Custom build procedure for GAMESS-US: using compddi, compall and lked scripts.""" + compddi = os.path.join(self.cfg['start_dir'], 'ddi', 'compddi') + run_cmd(compddi, log_all=True, simple=True) + + # make sure the libddi.a library is present + libddi = os.path.join(self.cfg['start_dir'], 'ddi', 'libddi.a') + if not os.path.isfile(libddi): + raise EasyBuildError("The libddi.a library (%s) was never built", libddi) + else: + self.log.info("The libddi.a library (%s) was successfully built." % libddi) + + ddikick = os.path.join(self.cfg['start_dir'], 'ddi', 'ddikick.x') + if os.path.isfile(ddikick): + self.log.info("The ddikick.x executable (%s) was successfully built." % ddikick) + + if self.cfg['ddi_comm'] == 'sockets': + src = ddikick + dst = os.path.join(self.cfg['start_dir'], 'ddikick.x') + self.log.info("Moving ddikick.x executable from %s to %s." % (src, dst)) + os.rename(src, dst) + + compall_cmd = os.path.join(self.cfg['start_dir'], 'compall') + compall = "%s %s %s" % (self.cfg['prebuildopts'], compall_cmd, self.cfg['buildopts']) + run_cmd(compall, log_all=True, simple=True) + + cmd = "%s gamess %s" % (os.path.join(self.cfg['start_dir'], 'lked'), self.version) + run_cmd(cmd, log_all=True, simple=True) + + # Done up to here + quit() + + if self.scratch_dir: + # FIXME: resolve environment variables used in scratch_dir values + + # use unique subdirectory in specified scratch dir; + # we should use a shell command to create this directory, + # since scratch_dir may include names of environment variables + salt = ''.join(random.choice(ascii_letters) for i in range(10)) + self.scratch_dir = os.path.join(self.scratch_dir, self.name + '-' + salt) + + # make sure that specified directory is accessible via 'ssh', since rungms relies on that; + # touch a file, and then use "ssh localhost ls" to see if it's accessible; + # we must use shell commands for this, since scratch_dir may contain names of environment variables + test_file = os.path.join(self.scratch_dir, 'test.txt') + run_cmd("mkdir -p %s" % self.scratch_dir) + run_cmd("touch %s" % test_file) + test_cmd = 'ssh localhost "ls %s"' % test_file + (out, ec) = run_cmd(test_cmd, simple=False, log_ok=False, log_all=False) + if ec: + error_msg = "Scratch directory %s is not accessible via 'ssh'!\n" % self.scratch_dir + error_msg += "Specify a different path using the 'scratch_dir' easyconfig parameter.\n" + error_msg += "Output of test command '%s': %s" % (test_cmd, out) + raise EasyBuildError(error_msg) + else: + self.log.info("Using %s as scratch directory", self.scratch_dir) + + # patch hardcoded settings in rungms to use values specified in easyconfig file + rungms = os.path.join(self.builddir, 'rungms') + extra_gmspath_lines = "set ERICFMT=$GMSPATH/auxdata/ericfmt.dat\nset MCPPATH=$GMSPATH/auxdata/MCP\n" + try: + for line in fileinput.input(rungms, inplace=1, backup='.orig'): + line = re.sub(r"^(\s*set\s*TARGET)=.*", r"\1=%s" % self.cfg['ddi_comm'], line) + line = re.sub(r"^(\s*set\s*GMSPATH)=.*", r"\1=%s\n%s" % (self.installdir, extra_gmspath_lines), line) + line = re.sub(r"^(\s*set\s*GMS_OPENMP)=.*", r"\1=%s" % "true", line) # changed in gamess-20190930-R2 for OpenBLAS support + line = re.sub(r"(null\) set VERNO)=.*", r"\1=%s" % self.version, line) + line = re.sub(r"^(\s*set DDI_MPI_CHOICE)=.*", r"\1=%s" % mpilib, line) + line = re.sub(r"^(\s*set DDI_MPI_ROOT)=.*%s.*" % mpilib.lower(), r"\1=%s" % mpilib_path, line) + line = re.sub(r"^(\s*set GA_MPI_ROOT)=.*%s.*" % mpilib.lower(), r"\1=%s" % mpilib_path, line) + # comment out all adjustments to $LD_LIBRARY_PATH that involves hardcoded paths + line = re.sub(r"^(\s*)(setenv\s*LD_LIBRARY_PATH\s*/.*)", r"\1#\2", line) + if self.scratch_dir: + line = re.sub(r"^(\s*set\s*SCR)=.*", r"\1=%s" % self.scratch_dir, line) + line = re.sub(r"^(\s*set\s*USERSCR)=.*", r"\1=%s" % self.scratch_dir, line) + sys.stdout.write(line) + except IOError as err: + raise EasyBuildError("Failed to patch %s: %s", rungms, err) + def build_step(self): """Custom build procedure for GAMESS-US: using compddi, compall and lked scripts.""" compddi = os.path.join(self.cfg['start_dir'], 'ddi', 'compddi') @@ -247,11 +379,7 @@ def test_step(self): self.log.info("Skipping testing of GAMESS-US since MPI testing is disabled") return - try: - cwd = os.getcwd() - os.chdir(self.testdir) - except OSError as err: - raise EasyBuildError("Failed to move to temporary directory for running tests: %s", err) + cwd = change_dir(self.testdir) # copy input files for exam standard tests for test_input in glob.glob(os.path.join(self.installdir, 'tests', 'standard', 'exam*.inp')): @@ -261,7 +389,7 @@ def test_step(self): raise EasyBuildError("Failed to copy %s to %s: %s", test_input, os.getcwd(), err) rungms = os.path.join(self.installdir, 'rungms') - test_env_vars = ['TMPDIR=%s' % self.testdir] + test_env_vars = ['export OMP_NUM_THREADS=1; TMPDIR=%s' % self.testdir ] if self.toolchain.mpi_family() == toolchain.INTELMPI: test_env_vars.extend([ 'I_MPI_FALLBACK=enable', # enable fallback in case first fabric fails (see $I_MPI_FABRICS_LIST) @@ -269,8 +397,10 @@ def test_step(self): ]) # run all exam tests, dump output to exam.log - n_tests = 47 - for i in range(1, n_tests + 1): + # we let Python count the number of *.inp files as that changes + tests_path = os.path.join(self.installdir, 'tests', 'standard') + n_tests = len(fnmatch.filter(os.listdir(tests_path), '*.inp')) + for i in range(1, n_tests+1): test_cmd = ' '.join(test_env_vars + [rungms, 'exam%02d' % i, self.version, '1', '2']) (out, _) = run_cmd(test_cmd, log_all=True, simple=False) write_file('exam%02d.log' % i, out) @@ -284,12 +414,7 @@ def test_step(self): else: raise EasyBuildError("Not all tests ran successfully...") - # cleanup - os.chdir(cwd) - try: - shutil.rmtree(self.testdir) - except OSError as err: - raise EasyBuildError("Failed to remove test directory %s: %s", self.testdir, err) + change_dir(cwd) def install_step(self): """Skip install step, since we're building in the install directory.""" @@ -309,3 +434,11 @@ def make_module_extra(self): txt += self.module_generator.set_environment('GAMESSUSROOT', self.installdir) txt += self.module_generator.prepend_paths("PATH", ['']) return txt + + def cleanup_step(self): + """Cleanup set.""" + # remove dedicated scratch directory (if any); + # we must use a shell command for this, since the path may contain environment variables + super(EB_GAMESS_minus_US, self).cleanup_step() + + # FIXME From e1691ad3f71594a7b454ea23f0e07853a73780a9 Mon Sep 17 00:00:00 2001 From: sassy Date: Thu, 22 Sep 2022 16:34:10 +0100 Subject: [PATCH 02/41] Whitespace deleted --- easybuild/easyblocks/g/gamess_us.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 35a92812b4..04b9abae28 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -389,7 +389,7 @@ def test_step(self): raise EasyBuildError("Failed to copy %s to %s: %s", test_input, os.getcwd(), err) rungms = os.path.join(self.installdir, 'rungms') - test_env_vars = ['export OMP_NUM_THREADS=1; TMPDIR=%s' % self.testdir ] + test_env_vars = ['export OMP_NUM_THREADS=1; TMPDIR=%s' % self.testdir] if self.toolchain.mpi_family() == toolchain.INTELMPI: test_env_vars.extend([ 'I_MPI_FALLBACK=enable', # enable fallback in case first fabric fails (see $I_MPI_FABRICS_LIST) From 1b03f22c81a2414af083c476d661d4a246db78b2 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Tue, 7 Mar 2023 11:20:07 +0100 Subject: [PATCH 03/41] revert error message format change in gamess-us easyblock --- easybuild/easyblocks/g/gamess_us.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 04b9abae28..2ffe4414a2 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -81,8 +81,8 @@ def __init__(self, *args, **kwargs): self.testdir = tempfile.mkdtemp() # make sure test dir doesn't contain [ or ], rungms csh script doesn't handle that well ("set: No match") if re.search(r'[\[\]]', self.testdir): - raise EasyBuildError("Temporary dir for tests '%s' will cause problems with rungms csh script", - self.testdir) + error_msg = "Temporary dir for tests '%s' will cause problems with rungms csh script" + raise EasyBuildError(error_msg, self.testdir) self.scratch_dir = self.cfg['scratch_dir'] From 1fe8e0aba57c7e1287955352f652e5670bbdfdaa Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Tue, 7 Mar 2023 11:27:47 +0100 Subject: [PATCH 04/41] remove duplicate build step in gamess-us easyblock --- easybuild/easyblocks/g/gamess_us.py | 78 ----------------------------- 1 file changed, 78 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 2ffe4414a2..a450ab9387 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -263,84 +263,6 @@ def configure_step(self): run_cmd("mv %s/tools/actvte.code" % self.builddir + " %s/tools/actvte.f" % self.builddir) run_cmd("%s -o " % fortran_comp + " %s/tools/actvte.x" % self.builddir + " %s/tools/actvte.f" % self.builddir) - def build_step(self): - """Custom build procedure for GAMESS-US: using compddi, compall and lked scripts.""" - compddi = os.path.join(self.cfg['start_dir'], 'ddi', 'compddi') - run_cmd(compddi, log_all=True, simple=True) - - # make sure the libddi.a library is present - libddi = os.path.join(self.cfg['start_dir'], 'ddi', 'libddi.a') - if not os.path.isfile(libddi): - raise EasyBuildError("The libddi.a library (%s) was never built", libddi) - else: - self.log.info("The libddi.a library (%s) was successfully built." % libddi) - - ddikick = os.path.join(self.cfg['start_dir'], 'ddi', 'ddikick.x') - if os.path.isfile(ddikick): - self.log.info("The ddikick.x executable (%s) was successfully built." % ddikick) - - if self.cfg['ddi_comm'] == 'sockets': - src = ddikick - dst = os.path.join(self.cfg['start_dir'], 'ddikick.x') - self.log.info("Moving ddikick.x executable from %s to %s." % (src, dst)) - os.rename(src, dst) - - compall_cmd = os.path.join(self.cfg['start_dir'], 'compall') - compall = "%s %s %s" % (self.cfg['prebuildopts'], compall_cmd, self.cfg['buildopts']) - run_cmd(compall, log_all=True, simple=True) - - cmd = "%s gamess %s" % (os.path.join(self.cfg['start_dir'], 'lked'), self.version) - run_cmd(cmd, log_all=True, simple=True) - - # Done up to here - quit() - - if self.scratch_dir: - # FIXME: resolve environment variables used in scratch_dir values - - # use unique subdirectory in specified scratch dir; - # we should use a shell command to create this directory, - # since scratch_dir may include names of environment variables - salt = ''.join(random.choice(ascii_letters) for i in range(10)) - self.scratch_dir = os.path.join(self.scratch_dir, self.name + '-' + salt) - - # make sure that specified directory is accessible via 'ssh', since rungms relies on that; - # touch a file, and then use "ssh localhost ls" to see if it's accessible; - # we must use shell commands for this, since scratch_dir may contain names of environment variables - test_file = os.path.join(self.scratch_dir, 'test.txt') - run_cmd("mkdir -p %s" % self.scratch_dir) - run_cmd("touch %s" % test_file) - test_cmd = 'ssh localhost "ls %s"' % test_file - (out, ec) = run_cmd(test_cmd, simple=False, log_ok=False, log_all=False) - if ec: - error_msg = "Scratch directory %s is not accessible via 'ssh'!\n" % self.scratch_dir - error_msg += "Specify a different path using the 'scratch_dir' easyconfig parameter.\n" - error_msg += "Output of test command '%s': %s" % (test_cmd, out) - raise EasyBuildError(error_msg) - else: - self.log.info("Using %s as scratch directory", self.scratch_dir) - - # patch hardcoded settings in rungms to use values specified in easyconfig file - rungms = os.path.join(self.builddir, 'rungms') - extra_gmspath_lines = "set ERICFMT=$GMSPATH/auxdata/ericfmt.dat\nset MCPPATH=$GMSPATH/auxdata/MCP\n" - try: - for line in fileinput.input(rungms, inplace=1, backup='.orig'): - line = re.sub(r"^(\s*set\s*TARGET)=.*", r"\1=%s" % self.cfg['ddi_comm'], line) - line = re.sub(r"^(\s*set\s*GMSPATH)=.*", r"\1=%s\n%s" % (self.installdir, extra_gmspath_lines), line) - line = re.sub(r"^(\s*set\s*GMS_OPENMP)=.*", r"\1=%s" % "true", line) # changed in gamess-20190930-R2 for OpenBLAS support - line = re.sub(r"(null\) set VERNO)=.*", r"\1=%s" % self.version, line) - line = re.sub(r"^(\s*set DDI_MPI_CHOICE)=.*", r"\1=%s" % mpilib, line) - line = re.sub(r"^(\s*set DDI_MPI_ROOT)=.*%s.*" % mpilib.lower(), r"\1=%s" % mpilib_path, line) - line = re.sub(r"^(\s*set GA_MPI_ROOT)=.*%s.*" % mpilib.lower(), r"\1=%s" % mpilib_path, line) - # comment out all adjustments to $LD_LIBRARY_PATH that involves hardcoded paths - line = re.sub(r"^(\s*)(setenv\s*LD_LIBRARY_PATH\s*/.*)", r"\1#\2", line) - if self.scratch_dir: - line = re.sub(r"^(\s*set\s*SCR)=.*", r"\1=%s" % self.scratch_dir, line) - line = re.sub(r"^(\s*set\s*USERSCR)=.*", r"\1=%s" % self.scratch_dir, line) - sys.stdout.write(line) - except IOError as err: - raise EasyBuildError("Failed to patch %s: %s", rungms, err) - def build_step(self): """Custom build procedure for GAMESS-US: using compddi, compall and lked scripts.""" compddi = os.path.join(self.cfg['start_dir'], 'ddi', 'compddi') From bcb9f0fbcca6da8459a35b74833cfd4bc9f4757a Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Tue, 7 Mar 2023 11:32:52 +0100 Subject: [PATCH 05/41] add user_scratch_dir extra option to gamess-us easyblock --- easybuild/easyblocks/g/gamess_us.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index a450ab9387..612b987951 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -68,7 +68,8 @@ def extra_options(): 'maxnodes': [None, "Maximum number of nodes", MANDATORY], 'runtest': [True, "Run GAMESS-US tests", CUSTOM], 'omp': [False, "Enabling OpenMP", CUSTOM], - 'scratch_dir': ['$TMPDIR', "Scratch dir to be used in rungms script", CUSTOM], + 'scratch_dir': ['$TMPDIR', "dir for temporary binary files", CUSTOM], + 'user_scratch_dir': ['$TMPDIR', "dir for supplementary output files", CUSTOM], } return EasyBlock.extra_options(extra_vars) @@ -84,8 +85,6 @@ def __init__(self, *args, **kwargs): error_msg = "Temporary dir for tests '%s' will cause problems with rungms csh script" raise EasyBuildError(error_msg, self.testdir) - self.scratch_dir = self.cfg['scratch_dir'] - def extract_step(self): """Extract sources.""" # strip off 'gamess' part to avoid having everything in a 'gamess' subdirectory @@ -233,9 +232,10 @@ def configure_step(self): line = re.sub(r"^(\s*set GA_MPI_ROOT)=.*%s.*" % mpilib.lower(), r"\1=%s" % mpilib_path, line) # comment out all adjustments to $LD_LIBRARY_PATH that involves hardcoded paths line = re.sub(r"^(\s*)(setenv\s*LD_LIBRARY_PATH\s*/.*)", r"\1#\2", line) - if self.cfg['scratch_dir']: - line = re.sub(r"^(\s*set\s*SCR)=.*", r"\1=%s" % self.cfg['scratch_dir'], line) - line = re.sub(r"^(\s*set\s*USERSCR)=.*", r"\1=%s" % self.cfg['scratch_dir'], line) + # scratch directory paths + line = re.sub(r"^(\s*set\s*SCR)=.*", r"if ( ! $?SCR ) \1=%s" % self.cfg['scratch_dir'], line) + line = re.sub(r"^(\s*set\s*USERSCR)=.*", r"if ( ! $?USERSCR ) \1=%s" % self.cfg['user_scratch_dir'], line) + line = re.sub(r"^(df -k \$SCR)$", r"mkdir -p $SCR && mkdir -p $USERSCR && \1", line) sys.stdout.write(line) except IOError as err: raise EasyBuildError("Failed to patch %s: %s", rungms, err) From bf674ad87f23ae303cd710afbf8a0de6c7d500ad Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Wed, 8 Mar 2023 15:26:55 +0100 Subject: [PATCH 06/41] streamline IMKL and fix support for OpenBLAS in gamess-us easyblock --- easybuild/easyblocks/g/gamess_us.py | 62 +++++++++++++++-------------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 612b987951..4ac5684faf 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -44,6 +44,8 @@ import tempfile import fnmatch +from distutils.version import LooseVersion + from easybuild.framework.easyblock import EasyBlock from easybuild.framework.easyconfig import CUSTOM, MANDATORY from easybuild.tools.build_log import EasyBuildError @@ -129,39 +131,41 @@ def configure_step(self): # math library config known_mathlibs = ['imkl', 'OpenBLAS', 'ATLAS', 'ACML'] - mathlib, mathlib_root = None, None - for mathlib in known_mathlibs: - mathlib_root = get_software_root(mathlib) - if mathlib_root is not None: - break - if mathlib_root is None: + loaded_mathlib = [mathlib for mathlib in known_mathlibs if get_software_root(mathlib)] + + # math library: default settings + try: + mathlib = loaded_mathlib[0].lower() + mathlib_root = get_software_root(loaded_mathlib[0]) + mathlib_subfolder = '' + mathlib_flags = '' + except IndexError: raise EasyBuildError("None of the known math libraries (%s) available, giving up.", known_mathlibs) + if mathlib == 'imkl': mathlib = 'mkl' - mathlib_vers_res = '.'.join(get_software_version('imkl').split('.')[:1]) - if int(mathlib_vers_res) == 2020: - mathlib_root = os.path.join(mathlib_root, 'mkl/lib/intel64') - elif int(mathlib_vers_res) == 2021: - mathlib_root = os.path.join(mathlib_root, 'mkl/latest/lib/intel64') - - if int(mathlib_vers_res) >= 2020: - # For some GAMESS-US versions oneapi is not in lked, so we use 12-so instead - if self.version == "20200630-R1" or self.version == "20200930-R2": - mathlib_vers = "12-so" - elif self.version == "20210620-R1": - mathlib_vers = "12-so" - else: - mathlib_vers = "oneapi-so" - else: - mathlib_vers = "12" - + mathlib_subfolder = 'mkl' + mathlib_flags = '-lmkl_intel_lp64' + imkl_ver = get_software_version('imkl') + if LooseVersion(imkl_ver) >= LooseVersion("2021"): + mathlib_subfolder = 'mkl/latest/lib/intel64' + elif LooseVersion(imkl_ver) >= LooseVersion("2020"): + mathlib_subfolder = 'mkl/lib/intel64' + elif mathlib == 'openblas': + mathlib_flags="-lopenblas -lgfortran" + if LooseVersion(self.version) >= LooseVersion('20210101'): + mathlib_subfolder = 'lib' + + if mathlib_root is not None: + mathlib_path = os.path.join(mathlib_root, mathlib_subfolder) + self.log.debug("Software root of math libraries set to: %s", mathlib_path) else: - mathlib = mathlib.lower() + raise EasyBuildError("Software root of math libraries (%s) not found", mathlib) - f.writelines(["setenv GMS_MATHLIB " + mathlib + "\n" + - "setenv GMS_MATHLIB_PATH " + mathlib_root + "\n" + - "setenv GMS_MKL_VERNO " + mathlib_vers + "\n" + - "setenv GMS_LAPACK_LINK_LINE" + "" + "\n"]) + f.writelines([ + "setenv GMS_MATHLIB " + mathlib + "\n" + + "setenv GMS_MATHLIB_PATH " + mathlib_path + "\n" + + "setenv GMS_LAPACK_LINK_LINE " + '"%s"' % mathlib_flags + "\n"]) # verify selected DDI communication layer known_ddi_comms = ['mpi', 'mixed', 'shmem', 'sockets'] @@ -169,7 +173,7 @@ def configure_step(self): raise EasyBuildError("Unsupported DDI communication layer specified (known: %s): %s", known_ddi_comms, self.cfg['ddi_comm']) - f.writelines(["setenv GMS_DDI_COMM " + self.cfg['ddi_comm'] + "\n" ]) + f.writelines(["setenv GMS_DDI_COMM " + self.cfg['ddi_comm'] + "\n"]) # MPI library config mpilib, mpilib_root, mpilib_path = None, None, None From 04ef3a9922c3456d5b35114d5a087184b5cd194a Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Wed, 8 Mar 2023 15:27:27 +0100 Subject: [PATCH 07/41] replace extra omp option with toolchain.options.openmp --- easybuild/easyblocks/g/gamess_us.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 4ac5684faf..d7b741e6eb 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -69,7 +69,6 @@ def extra_options(): 'maxcpus': [None, "Maximum number of cores per node", MANDATORY], 'maxnodes': [None, "Maximum number of nodes", MANDATORY], 'runtest': [True, "Run GAMESS-US tests", CUSTOM], - 'omp': [False, "Enabling OpenMP", CUSTOM], 'scratch_dir': ['$TMPDIR', "dir for temporary binary files", CUSTOM], 'user_scratch_dir': ['$TMPDIR', "dir for supplementary output files", CUSTOM], } @@ -203,7 +202,7 @@ def configure_step(self): f. writelines(["setenv GMS_PHI none " + "\n"]) f. writelines(["setenv GMS_SHMTYPE sysv " + "\n"]) - if self.cfg['omp'] == 'True': + if self.toolchain.options.get('openmp', None): f. writelines(["setenv GMS_OPENMP true" + "\n"]) else: f. writelines(["setenv GMS_OPENMP false" + "\n"]) From 18db2c552d83c7a6e073b24ee2536f9e0cd7124b Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Wed, 8 Mar 2023 15:41:29 +0100 Subject: [PATCH 08/41] check dependency on libxc to enable GMS_LIBXC --- easybuild/easyblocks/g/gamess_us.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index d7b741e6eb..11d641ae34 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -206,8 +206,16 @@ def configure_step(self): f. writelines(["setenv GMS_OPENMP true" + "\n"]) else: f. writelines(["setenv GMS_OPENMP false" + "\n"]) - - f. writelines(["setenv GMS_LIBXC false " + "\n"]) + + external_plugs = dict() + if LooseVersion(self.version) >= LooseVersion('2021'): + external_plugs['GMS_LIBXC'] = "false" + if get_software_root('libxc'): + external_plugs['GMS_LIBXC'] = "true" + + for opt in external_plugs.items(): + f. writelines(["setenv %s %s \n" % opt]) + f. writelines(["setenv GMS_MDI false " + "\n"]) f. writelines(["setenv GMS_VM2 false " + "\n"]) f. writelines(["setenv TINKER false " + "\n"]) From 3b91897d652791eff2ab0c3c924efaaa4e4126f8 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Thu, 9 Mar 2023 14:10:09 +0100 Subject: [PATCH 09/41] set interfaces and plugins through plugs_opts in gamess-us easyblock --- easybuild/easyblocks/g/gamess_us.py | 39 +++++++++++++++++++---------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 11d641ae34..e369987dc5 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -207,22 +207,35 @@ def configure_step(self): else: f. writelines(["setenv GMS_OPENMP false" + "\n"]) - external_plugs = dict() - if LooseVersion(self.version) >= LooseVersion('2021'): - external_plugs['GMS_LIBXC'] = "false" + # Optional plug-ins and interfaces + # libXC + plugs_opt = dict() + if LooseVersion(self.version) >= LooseVersion('20210101'): + plugs_opt['GMS_LIBXC'] = "false" if get_software_root('libxc'): - external_plugs['GMS_LIBXC'] = "true" - - for opt in external_plugs.items(): + plugs_opt['GMS_LIBXC'] = "true" + # MDI + # needs https://github.com/MolSSI-MDI/MDI_Library + plugs_opt['GMS_MDI'] = "false" + # VM2 + plugs_opt['GMS_VM2'] = "false" + # NBO + plugs_opt['NBO'] = "false" + if get_software_root('NBO'): + plugs_opt['NBO'] = "true" + # NEO + plugs_opt['NEO'] = "false" + # TINKER + plugs_opt['TINKER'] = "false" + if get_software_root('TINKER'): + plugs_opt['TINKER'] = "true" + # VB2000 + plugs_opt['VB2000'] = "false" + # XMVB + plugs_opt['XMVB'] = "false" + for opt in plugs_opt.items(): f. writelines(["setenv %s %s \n" % opt]) - f. writelines(["setenv GMS_MDI false " + "\n"]) - f. writelines(["setenv GMS_VM2 false " + "\n"]) - f. writelines(["setenv TINKER false " + "\n"]) - f. writelines(["setenv VB2000 false " + "\n"]) - f. writelines(["setenv XMVB false " + "\n"]) - f. writelines(["setenv NEO false " + "\n"]) - f. writelines(["setenv NBO false " + "\n"]) f. writelines(["setenv GMS_FPE_FLAGS " + "\n"]) #f. writelines(["setenv GMS_FPE_FLAGS '-ffpe-trap=invalid,zero,overflow' " + "\n"]) # This seems to be useful for debugging From b85076a7d94afae428a4a02920a65cb0aa6f2c4e Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Thu, 9 Mar 2023 21:09:41 +0100 Subject: [PATCH 10/41] fix linking to libxc in gamess-us easyblock --- easybuild/easyblocks/g/gamess_us.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index e369987dc5..a2d7670c5c 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -214,6 +214,16 @@ def configure_step(self): plugs_opt['GMS_LIBXC'] = "false" if get_software_root('libxc'): plugs_opt['GMS_LIBXC'] = "true" + # the linker needs to be patched to use external libXC + lixc_libs = [os.path.join(os.environ['EBROOTLIBXC'], 'lib', l) for l in ['libxcf03.a', 'libxc.a']] + libxc_linker_flags = ' '.join(lixc_libs) + try: + lked = os.path.join(self.builddir, 'lked') + for line in fileinput.input(lked, inplace=1, backup='.orig'): + line = re.sub(r"^(\s*set\sLIBXC_FLAGS)=.*GMS_PATH.*", r'\1="%s"' % libxc_linker_flags, line) + sys.stdout.write(line) + except IOError as err: + raise EasyBuildError("Failed to patch %s: %s", lked, err) # MDI # needs https://github.com/MolSSI-MDI/MDI_Library plugs_opt['GMS_MDI'] = "false" @@ -236,7 +246,8 @@ def configure_step(self): for opt in plugs_opt.items(): f. writelines(["setenv %s %s \n" % opt]) - f. writelines(["setenv GMS_FPE_FLAGS " + "\n"]) + # add include paths from dependencies + f. writelines(['setenv GMS_FPE_FLAGS "%s" \n' % os.environ['CPPFLAGS']]) #f. writelines(["setenv GMS_FPE_FLAGS '-ffpe-trap=invalid,zero,overflow' " + "\n"]) # This seems to be useful for debugging f.close() From 133861ca1c939c041f35160aa45e3ca1cc01c7fb Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Fri, 10 Mar 2023 08:55:21 +0100 Subject: [PATCH 11/41] move openmp settings to original position in gamess-us easyblock --- easybuild/easyblocks/g/gamess_us.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index a2d7670c5c..125397d64a 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -196,17 +196,18 @@ def configure_step(self): f.writelines(["setenv GMS_MPI_LIB " + mpilib + "\n" + "setenv GMS_MPI_PATH " + mpilib_root + "\n"]) + # OpenMP config + if self.toolchain.options.get('openmp', None): + f. writelines(["setenv GMS_OPENMP true" + "\n"]) + else: + f. writelines(["setenv GMS_OPENMP false" + "\n"]) + # These are extra programs which for now we simply set all to FALSE f. writelines(["setenv GMS_MSUCC false " + "\n"]) f. writelines(["setenv GMS_LIBCCHEM false" + "\n"]) f. writelines(["setenv GMS_PHI none " + "\n"]) f. writelines(["setenv GMS_SHMTYPE sysv " + "\n"]) - if self.toolchain.options.get('openmp', None): - f. writelines(["setenv GMS_OPENMP true" + "\n"]) - else: - f. writelines(["setenv GMS_OPENMP false" + "\n"]) - # Optional plug-ins and interfaces # libXC plugs_opt = dict() From b7834736ae54caf448b6b2630cec4a676f2c9a40 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Sat, 11 Mar 2023 23:47:42 +0100 Subject: [PATCH 12/41] skip tests in gamess-us with less than 2 cores --- easybuild/easyblocks/g/gamess_us.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 125397d64a..9254726298 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -337,6 +337,10 @@ def test_step(self): self.log.info("Skipping testing of GAMESS-US since MPI testing is disabled") return + if int(self.cfg['parallel']) < 2: + self.log.info("Skipping testing of GAMESS-US as MPI tests need at least 2 CPU cores to run") + return + cwd = change_dir(self.testdir) # copy input files for exam standard tests From d4a6a38f2c81ab82d5a6befbba2791ad556a8152 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Sat, 11 Mar 2023 23:58:59 +0100 Subject: [PATCH 13/41] remove unused modules from gamess-us easyblock --- easybuild/easyblocks/g/gamess_us.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 9254726298..b344f96d76 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -52,8 +52,7 @@ from easybuild.tools.config import build_option from easybuild.tools.filetools import change_dir, read_file, write_file from easybuild.tools.modules import get_software_root, get_software_version -from easybuild.tools.py2vs3 import ascii_letters -from easybuild.tools.run import run_cmd, run_cmd_qa +from easybuild.tools.run import run_cmd from easybuild.tools.systemtools import get_platform_name from easybuild.tools import toolchain From 29e42e3aca40c93f3ce37c04c65d5d335c31b815 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Sun, 12 Mar 2023 00:09:53 +0100 Subject: [PATCH 14/41] cleanup scratch generated by tests of gamess-us --- easybuild/easyblocks/g/gamess_us.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index b344f96d76..baad03e504 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -50,7 +50,7 @@ from easybuild.framework.easyconfig import CUSTOM, MANDATORY from easybuild.tools.build_log import EasyBuildError from easybuild.tools.config import build_option -from easybuild.tools.filetools import change_dir, read_file, write_file +from easybuild.tools.filetools import change_dir, read_file, write_file, remove_dir from easybuild.tools.modules import get_software_root, get_software_version from easybuild.tools.run import run_cmd from easybuild.tools.systemtools import get_platform_name @@ -398,8 +398,12 @@ def make_module_extra(self): def cleanup_step(self): """Cleanup set.""" + super(EB_GAMESS_minus_US, self).cleanup_step() + # remove dedicated scratch directory (if any); # we must use a shell command for this, since the path may contain environment variables - super(EB_GAMESS_minus_US, self).cleanup_step() + (scratch_path, _) = run_cmd('echo "%s"' % self.cfg['scratch_dir'], simple=False) + if os.path.isdir(scratch_path): + remove_dir(scratch_path) + self.log.info("Removed test scratch: %s", scratch_path) - # FIXME From e5bc041287c707214ee1597b4f7fbc9158d2f00e Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Sun, 12 Mar 2023 00:44:38 +0100 Subject: [PATCH 15/41] use write_file from easybuild to create install.info file in gamess-us --- easybuild/easyblocks/g/gamess_us.py | 108 +++++++++++++++------------- 1 file changed, 59 insertions(+), 49 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index baad03e504..9fc3c64390 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -53,8 +53,10 @@ from easybuild.tools.filetools import change_dir, read_file, write_file, remove_dir from easybuild.tools.modules import get_software_root, get_software_version from easybuild.tools.run import run_cmd -from easybuild.tools.systemtools import get_platform_name +from easybuild.tools.systemtools import POWER, X86_64 +from easybuild.tools.systemtools import get_cpu_architecture from easybuild.tools import toolchain +INSTALL_INFO = 'install.info' class EB_GAMESS_minus_US(EasyBlock): @@ -92,20 +94,24 @@ def extract_step(self): super(EB_GAMESS_minus_US, self).extract_step() def configure_step(self): - """Configure GAMESS-US build via provided interactive 'config' script.""" - """Opening install.info file as append""" - f = open(self.builddir + "/install.info", "a") - f.writelines(["setenv GMS_PATH " + self.builddir + "\n" - "setenv GMS_BUILD_DIR " + self.installdir + "\n"]) + """Configure GAMESS-US via install.info file""" + installinfo_opts = {} + + # installation paths + installinfo_opts["GMS_PATH"] = self.installdir + installinfo_opts["GMS_BUILD_DIR"] = self.builddir + # machine type - platform_name = get_platform_name() - x86_64_linux_re = re.compile('^x86_64-.*$') - if x86_64_linux_re.match(platform_name): + cpu_arch = get_cpu_architecture() + if cpu_arch == X86_64: machinetype = "linux64" - f.writelines(["setenv GMS_TARGET " + machinetype + "\n" + - "setenv GMS_HPC_SYSTEM_TARGET generic" + "\n"]) + elif cpu_arch == POWER: + machinetype = "ibm64" else: - raise EasyBuildError("Build target %s currently unsupported", platform_name) + raise EasyBuildError("Build target %s currently unsupported", cpu_arch) + + installinfo_opts["GMS_TARGET"] = machinetype + installinfo_opts["GMS_HPC_SYSTEM_TARGET"] = "generic" # compiler config comp_fam = self.toolchain.comp_family() @@ -124,8 +130,8 @@ def configure_step(self): else: raise EasyBuildError("Compiler family '%s' currently unsupported.", comp_fam) - f.writelines(["setenv GMS_FORTRAN " + fortran_comp + "\n" + - "setenv GMS_GFORTRAN_VERNO " + fortran_ver + "\n"]) + installinfo_opts["GMS_FORTRAN"] = fortran_comp + installinfo_opts["GMS_GFORTRAN_VERNO"] = fortran_ver # math library config known_mathlibs = ['imkl', 'OpenBLAS', 'ATLAS', 'ACML'] @@ -140,6 +146,7 @@ def configure_step(self): except IndexError: raise EasyBuildError("None of the known math libraries (%s) available, giving up.", known_mathlibs) + # math library: special cases if mathlib == 'imkl': mathlib = 'mkl' mathlib_subfolder = 'mkl' @@ -160,18 +167,18 @@ def configure_step(self): else: raise EasyBuildError("Software root of math libraries (%s) not found", mathlib) - f.writelines([ - "setenv GMS_MATHLIB " + mathlib + "\n" + - "setenv GMS_MATHLIB_PATH " + mathlib_path + "\n" + - "setenv GMS_LAPACK_LINK_LINE " + '"%s"' % mathlib_flags + "\n"]) + installinfo_opts["GMS_MATHLIB"] = mathlib + installinfo_opts["GMS_MATHLIB_PATH"] = mathlib_path + installinfo_opts["GMS_LAPACK_LINK_LINE"] = '"%s"' % mathlib_flags # verify selected DDI communication layer known_ddi_comms = ['mpi', 'mixed', 'shmem', 'sockets'] if not self.cfg['ddi_comm'] in known_ddi_comms: - raise EasyBuildError("Unsupported DDI communication layer specified (known: %s): %s", - known_ddi_comms, self.cfg['ddi_comm']) + raise EasyBuildError( + "Unsupported DDI communication layer specified (known: %s): %s", known_ddi_comms, self.cfg['ddi_comm'] + ) - f.writelines(["setenv GMS_DDI_COMM " + self.cfg['ddi_comm'] + "\n"]) + installinfo_opts["GMS_DDI_COMM"] = self.cfg['ddi_comm'] # MPI library config mpilib, mpilib_root, mpilib_path = None, None, None @@ -192,28 +199,29 @@ def configure_step(self): else: mpilib, mpilib_root = '', '' - f.writelines(["setenv GMS_MPI_LIB " + mpilib + "\n" + - "setenv GMS_MPI_PATH " + mpilib_root + "\n"]) + installinfo_opts["GMS_MPI_LIB"] = mpilib + installinfo_opts["GMS_MPI_PATH"] = mpilib_root # OpenMP config if self.toolchain.options.get('openmp', None): - f. writelines(["setenv GMS_OPENMP true" + "\n"]) + omp_enabled = "true" else: - f. writelines(["setenv GMS_OPENMP false" + "\n"]) + omp_enabled = "false" + + installinfo_opts["GMS_OPENMP"] = omp_enabled # These are extra programs which for now we simply set all to FALSE - f. writelines(["setenv GMS_MSUCC false " + "\n"]) - f. writelines(["setenv GMS_LIBCCHEM false" + "\n"]) - f. writelines(["setenv GMS_PHI none " + "\n"]) - f. writelines(["setenv GMS_SHMTYPE sysv " + "\n"]) + installinfo_opts["GMS_MSUCC"] = "false" + installinfo_opts["GMS_LIBCCHEM"] = "false" + installinfo_opts["GMS_PHI"] = "none" + installinfo_opts["GMS_SHMTYPE"] = "sysv" # Optional plug-ins and interfaces # libXC - plugs_opt = dict() if LooseVersion(self.version) >= LooseVersion('20210101'): - plugs_opt['GMS_LIBXC'] = "false" + installinfo_opts['GMS_LIBXC'] = "false" if get_software_root('libxc'): - plugs_opt['GMS_LIBXC'] = "true" + installinfo_opts['GMS_LIBXC'] = "true" # the linker needs to be patched to use external libXC lixc_libs = [os.path.join(os.environ['EBROOTLIBXC'], 'lib', l) for l in ['libxcf03.a', 'libxc.a']] libxc_linker_flags = ' '.join(lixc_libs) @@ -226,33 +234,35 @@ def configure_step(self): raise EasyBuildError("Failed to patch %s: %s", lked, err) # MDI # needs https://github.com/MolSSI-MDI/MDI_Library - plugs_opt['GMS_MDI'] = "false" + installinfo_opts['GMS_MDI'] = "false" # VM2 - plugs_opt['GMS_VM2'] = "false" + installinfo_opts['GMS_VM2'] = "false" # NBO - plugs_opt['NBO'] = "false" + installinfo_opts['NBO'] = "false" if get_software_root('NBO'): - plugs_opt['NBO'] = "true" + installinfo_opts['NBO'] = "true" # NEO - plugs_opt['NEO'] = "false" + installinfo_opts['NEO'] = "false" # TINKER - plugs_opt['TINKER'] = "false" + installinfo_opts['TINKER'] = "false" if get_software_root('TINKER'): - plugs_opt['TINKER'] = "true" + installinfo_opts['TINKER'] = "true" # VB2000 - plugs_opt['VB2000'] = "false" + installinfo_opts['VB2000'] = "false" # XMVB - plugs_opt['XMVB'] = "false" - for opt in plugs_opt.items(): - f. writelines(["setenv %s %s \n" % opt]) + installinfo_opts['XMVB'] = "false" # add include paths from dependencies - f. writelines(['setenv GMS_FPE_FLAGS "%s" \n' % os.environ['CPPFLAGS']]) - #f. writelines(["setenv GMS_FPE_FLAGS '-ffpe-trap=invalid,zero,overflow' " + "\n"]) # This seems to be useful for debugging - - f.close() + installinfo_opts["GMS_FPE_FLAGS"] = '"%s"' % os.environ['CPPFLAGS'] + # might be useful for debugging + # installinfo_opts["GMS_FPE_FLAGS"] = '"%s"' % os.environ['CPPFLAGS'] + "-ffpe-trap=invalid,zero,overflow" - self.log.debug("Contents of install.info:\n%s" % read_file(os.path.join(self.builddir, 'install.info'))) + # write install.info file with configuration settings + # format: setenv KEY VALUE + installinfo_file = os.path.join(self.builddir, INSTALL_INFO) + txt = '\n'.join(["setenv %s %s" % (k, installinfo_opts[k]) for k in installinfo_opts]) + write_file(installinfo_file, txt) + self.log.debug("Contents of install.info:\n%s" % read_file(installinfo_file)) # patch hardcoded settings in rungms to use values specified in easyconfig file rungms = os.path.join(self.builddir, 'rungms') @@ -402,7 +412,7 @@ def cleanup_step(self): # remove dedicated scratch directory (if any); # we must use a shell command for this, since the path may contain environment variables - (scratch_path, _) = run_cmd('echo "%s"' % self.cfg['scratch_dir'], simple=False) + (scratch_path, _) = run_cmd('printf "%%s" "%s"' % self.cfg['scratch_dir'], simple=False) if os.path.isdir(scratch_path): remove_dir(scratch_path) self.log.info("Removed test scratch: %s", scratch_path) From 6dc3248b4136121736014455e82164351ace7325 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Sun, 12 Mar 2023 02:18:22 +0100 Subject: [PATCH 16/41] use specific version setting for each fortran compiler in gamess-us --- easybuild/easyblocks/g/gamess_us.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 9fc3c64390..a069f271f5 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -120,18 +120,20 @@ def configure_step(self): fortran_comp = 'ifort' (out, _) = run_cmd("ifort -v", simple=False) res = re.search(r"^ifort version ([0-9]+)\.[0-9.]+$", out) - if res: - fortran_ver = res.group(1) - else: + try: + version_num = res.group(1) + except (AttributeError, IndexError): raise EasyBuildError("Failed to determine ifort major version number") + fortran_version = {"GMS_IFORT_VERNO": version_num} elif comp_fam == toolchain.GCC: fortran_comp = 'gfortran' - fortran_ver = '.'.join(get_software_version('GCC').split('.')[:2]) + version_num = '.'.join(get_software_version('GCC').split('.')[:2]) + fortran_version = {"GMS_GFORTRAN_VERNO": version_num} else: raise EasyBuildError("Compiler family '%s' currently unsupported.", comp_fam) installinfo_opts["GMS_FORTRAN"] = fortran_comp - installinfo_opts["GMS_GFORTRAN_VERNO"] = fortran_ver + installinfo_opts.update(fortran_version) # math library config known_mathlibs = ['imkl', 'OpenBLAS', 'ATLAS', 'ACML'] From fa047dcd7cd0f26ab5728b11661ec623ef411d15 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Sun, 12 Mar 2023 02:43:13 +0100 Subject: [PATCH 17/41] add support for impi v2021+ to gamess-us easyblock --- easybuild/easyblocks/g/gamess_us.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index a069f271f5..221ba1ff0d 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -183,9 +183,8 @@ def configure_step(self): installinfo_opts["GMS_DDI_COMM"] = self.cfg['ddi_comm'] # MPI library config - mpilib, mpilib_root, mpilib_path = None, None, None + mpilib, mpilib_path = '', '' if self.cfg['ddi_comm'] == 'mpi': - known_mpilibs = ['impi', 'OpenMPI', 'MVAPICH2', 'MPICH2'] for mpilib in known_mpilibs: mpilib_root = get_software_root(mpilib) @@ -195,14 +194,16 @@ def configure_step(self): raise EasyBuildError("None of the known MPI libraries (%s) available, giving up.", known_mpilibs) mpilib_path = mpilib_root if mpilib == 'impi': - mpilib_path = os.path.join(mpilib_root, 'intel64') + impi_ver = get_software_version('impi') + if LooseVersion(impi_ver) >= LooseVersion("2021.0.0"): + mpilib_path = os.path.join(mpilib_root, 'mpi', 'latest') + else: + mpilib_path = os.path.join(mpilib_root, 'intel64') else: mpilib = mpilib.lower() - else: - mpilib, mpilib_root = '', '' installinfo_opts["GMS_MPI_LIB"] = mpilib - installinfo_opts["GMS_MPI_PATH"] = mpilib_root + installinfo_opts["GMS_MPI_PATH"] = mpilib_path # OpenMP config if self.toolchain.options.get('openmp', None): From c04d19d794b49a24db668649e142755e003605d0 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Sun, 12 Mar 2023 01:52:13 +0100 Subject: [PATCH 18/41] add extra option to gamess-us easyblock to disable hyperthreading --- easybuild/easyblocks/g/gamess_us.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 221ba1ff0d..0d254ebfbb 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -69,6 +69,7 @@ def extra_options(): 'ddi_comm': ['mpi', "DDI communication layer to use", CUSTOM], 'maxcpus': [None, "Maximum number of cores per node", MANDATORY], 'maxnodes': [None, "Maximum number of nodes", MANDATORY], + 'hyperthreading': [True, "Enable support for hyperthreading (2 threads per core)", CUSTOM], 'runtest': [True, "Run GAMESS-US tests", CUSTOM], 'scratch_dir': ['$TMPDIR', "dir for temporary binary files", CUSTOM], 'user_scratch_dir': ['$TMPDIR', "dir for supplementary output files", CUSTOM], @@ -284,6 +285,10 @@ def configure_step(self): line = re.sub(r"^(\s*set\s*SCR)=.*", r"if ( ! $?SCR ) \1=%s" % self.cfg['scratch_dir'], line) line = re.sub(r"^(\s*set\s*USERSCR)=.*", r"if ( ! $?USERSCR ) \1=%s" % self.cfg['user_scratch_dir'], line) line = re.sub(r"^(df -k \$SCR)$", r"mkdir -p $SCR && mkdir -p $USERSCR && \1", line) + if self.cfg['hyperthreading'] is False: + # disable hyperthreading (1 thread per core) + line = re.sub(r"\$PPN \+ \$PPN", r"$PPN", line) + line = re.sub(r"\$NCPUS \+ \$NCPUS", r"$NCPUS", line) sys.stdout.write(line) except IOError as err: raise EasyBuildError("Failed to patch %s: %s", rungms, err) From 440f9600fdab92d9aa41e33195a58dc5c56a8528 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Mon, 13 Mar 2023 00:32:41 +0100 Subject: [PATCH 19/41] set version of MKL in gamess-us easyblock --- easybuild/easyblocks/g/gamess_us.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 0d254ebfbb..dc56010716 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -152,13 +152,15 @@ def configure_step(self): # math library: special cases if mathlib == 'imkl': mathlib = 'mkl' - mathlib_subfolder = 'mkl' - mathlib_flags = '-lmkl_intel_lp64' + mathlib_subfolder = 'mkl/lib/intel64' + mkl_version = '12' imkl_ver = get_software_version('imkl') if LooseVersion(imkl_ver) >= LooseVersion("2021"): + # OneAPI version mathlib_subfolder = 'mkl/latest/lib/intel64' - elif LooseVersion(imkl_ver) >= LooseVersion("2020"): - mathlib_subfolder = 'mkl/lib/intel64' + mkl_version = 'oneapi' + installinfo_opts["GMS_MKL_VERNO"] = mkl_version + elif mathlib == 'openblas': mathlib_flags="-lopenblas -lgfortran" if LooseVersion(self.version) >= LooseVersion('20210101'): From 45e9a3e48310e6fb4509453de48fbce4ebb6d4c0 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Mon, 13 Mar 2023 11:59:29 +0100 Subject: [PATCH 20/41] set parallelization of tests in gamess-us to 2 processes --- easybuild/easyblocks/g/gamess_us.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index dc56010716..567a6c98ca 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -56,7 +56,9 @@ from easybuild.tools.systemtools import POWER, X86_64 from easybuild.tools.systemtools import get_cpu_architecture from easybuild.tools import toolchain -INSTALL_INFO = 'install.info' + +GAMESS_INSTALL_INFO = 'install.info' +GAMESS_TEST_TASKS = 2 class EB_GAMESS_minus_US(EasyBlock): @@ -265,10 +267,10 @@ def configure_step(self): # write install.info file with configuration settings # format: setenv KEY VALUE - installinfo_file = os.path.join(self.builddir, INSTALL_INFO) + installinfo_file = os.path.join(self.builddir, GAMESS_INSTALL_INFO) txt = '\n'.join(["setenv %s %s" % (k, installinfo_opts[k]) for k in installinfo_opts]) write_file(installinfo_file, txt) - self.log.debug("Contents of install.info:\n%s" % read_file(installinfo_file)) + self.log.debug("Contents of %s:\n%s" % (installinfo_file, read_file(installinfo_file))) # patch hardcoded settings in rungms to use values specified in easyconfig file rungms = os.path.join(self.builddir, 'rungms') @@ -382,7 +384,8 @@ def test_step(self): tests_path = os.path.join(self.installdir, 'tests', 'standard') n_tests = len(fnmatch.filter(os.listdir(tests_path), '*.inp')) for i in range(1, n_tests+1): - test_cmd = ' '.join(test_env_vars + [rungms, 'exam%02d' % i, self.version, '1', '2']) + rungms_cmd = [rungms, 'exam%02d' % i, self.version, str(GAMESS_TEST_TASKS), str(GAMESS_TEST_TASKS)] + test_cmd = ' '.join(test_env_vars + rungms_cmd) (out, _) = run_cmd(test_cmd, log_all=True, simple=False) write_file('exam%02d.log' % i, out) From a9de2fdf0a316ca70db760b8ad8154fd4d95a199 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Mon, 13 Mar 2023 15:19:16 +0100 Subject: [PATCH 21/41] fix gamess-us configuration for Intel MPI v2019+ --- easybuild/easyblocks/g/gamess_us.py | 39 +++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 567a6c98ca..7bbf77d906 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -191,21 +191,40 @@ def configure_step(self): mpilib, mpilib_path = '', '' if self.cfg['ddi_comm'] == 'mpi': known_mpilibs = ['impi', 'OpenMPI', 'MVAPICH2', 'MPICH2'] - for mpilib in known_mpilibs: - mpilib_root = get_software_root(mpilib) - if mpilib_root is not None: - break - if mpilib_root is None: + loaded_mpilib = [mpilib for mpilib in known_mpilibs if get_software_root(mpilib)] + + # mpi library: default settings + try: + mpilib = loaded_mpilib[0].lower() + mpilib_root = get_software_root(loaded_mpilib[0]) + mpilib_subfolder = '' + except IndexError: raise EasyBuildError("None of the known MPI libraries (%s) available, giving up.", known_mpilibs) - mpilib_path = mpilib_root + if mpilib == 'impi': impi_ver = get_software_version('impi') - if LooseVersion(impi_ver) >= LooseVersion("2021.0.0"): - mpilib_path = os.path.join(mpilib_root, 'mpi', 'latest') + if LooseVersion(impi_ver) >= LooseVersion("2021"): + mpilib_subfolder = "mpi/latest" else: - mpilib_path = os.path.join(mpilib_root, 'intel64') + mpilib_subfolder = "intel64" + + if LooseVersion(impi_ver) >= LooseVersion("2019"): + # fix rungms settings for newer versions of Intel MPI + print("PATCH IMPI") + rungms = os.path.join(self.builddir, 'rungms') + try: + for line in fileinput.input(rungms, inplace=1, backup='.orig'): + line = re.sub(r"^(\s*setenv\s*I_MPI_STATS).*", r"# \1", line) + line = re.sub(r"^(\s*setenv\s*I_MPI_WAIT_MODE)\s*enable.*", r"\1 1", line) + sys.stdout.write(line) + except IOError as err: + raise EasyBuildError("Failed to patch Intel MPI settings in %s: %s", rungms, err) + + if mpilib_root is not None: + mpilib_path = os.path.join(mpilib_root, mpilib_subfolder) + self.log.debug("Software root of MPI libraries set to: %s", mpilib_path) else: - mpilib = mpilib.lower() + raise EasyBuildError("Software root of MPI libraries (%s) not found", mpilib) installinfo_opts["GMS_MPI_LIB"] = mpilib installinfo_opts["GMS_MPI_PATH"] = mpilib_path From b009762a6e9a40c2660da772cfc26b9762108dfc Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Mon, 20 Mar 2023 16:06:57 +0100 Subject: [PATCH 22/41] reduce minimum version for libxc support in gamess-us to 20200101 --- easybuild/easyblocks/g/gamess_us.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 7bbf77d906..9b9149cb74 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -245,7 +245,7 @@ def configure_step(self): # Optional plug-ins and interfaces # libXC - if LooseVersion(self.version) >= LooseVersion('20210101'): + if LooseVersion(self.version) >= LooseVersion('20200101'): installinfo_opts['GMS_LIBXC'] = "false" if get_software_root('libxc'): installinfo_opts['GMS_LIBXC'] = "true" From c4f0baec11cbb45831d83b0f21197204be817954 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Mon, 20 Mar 2023 16:07:36 +0100 Subject: [PATCH 23/41] add Alex Domingo as author of gamess-us easyblock --- easybuild/easyblocks/g/gamess_us.py | 1 + 1 file changed, 1 insertion(+) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 9b9149cb74..aff9753f4e 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -33,6 +33,7 @@ @author: Toon Willems (Ghent University) @author: Pablo Escobar (sciCORE, SIB, University of Basel) @author: Benjamin Roberts (The University of Auckland) +@author: Alex Domingo (Vrije Universiteit Brussel) """ import fileinput import glob From 1505dc54499e85e45af4db1938aea55f8d145e8c Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Wed, 6 Dec 2023 18:18:06 +0100 Subject: [PATCH 24/41] fix code formatting in gamess_us easyblock --- easybuild/easyblocks/g/gamess_us.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index ea8f10da33..cf8bdd00d9 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -38,7 +38,6 @@ import fileinput import glob import os -import random import re import shutil import sys @@ -165,7 +164,7 @@ def configure_step(self): installinfo_opts["GMS_MKL_VERNO"] = mkl_version elif mathlib == 'openblas': - mathlib_flags="-lopenblas -lgfortran" + mathlib_flags = "-lopenblas -lgfortran" if LooseVersion(self.version) >= LooseVersion('20210101'): mathlib_subfolder = 'lib' @@ -185,7 +184,7 @@ def configure_step(self): raise EasyBuildError( "Unsupported DDI communication layer specified (known: %s): %s", known_ddi_comms, self.cfg['ddi_comm'] ) - + installinfo_opts["GMS_DDI_COMM"] = self.cfg['ddi_comm'] # MPI library config @@ -282,7 +281,7 @@ def configure_step(self): # add include paths from dependencies installinfo_opts["GMS_FPE_FLAGS"] = '"%s"' % os.environ['CPPFLAGS'] - # might be useful for debugging + # might be useful for debugging # installinfo_opts["GMS_FPE_FLAGS"] = '"%s"' % os.environ['CPPFLAGS'] + "-ffpe-trap=invalid,zero,overflow" # write install.info file with configuration settings @@ -307,7 +306,9 @@ def configure_step(self): line = re.sub(r"^(\s*)(setenv\s*LD_LIBRARY_PATH\s*/.*)", r"\1#\2", line) # scratch directory paths line = re.sub(r"^(\s*set\s*SCR)=.*", r"if ( ! $?SCR ) \1=%s" % self.cfg['scratch_dir'], line) - line = re.sub(r"^(\s*set\s*USERSCR)=.*", r"if ( ! $?USERSCR ) \1=%s" % self.cfg['user_scratch_dir'], line) + line = re.sub( + r"^(\s*set\s*USERSCR)=.*", r"if ( ! $?USERSCR ) \1=%s" % self.cfg['user_scratch_dir'], line + ) line = re.sub(r"^(df -k \$SCR)$", r"mkdir -p $SCR && mkdir -p $USERSCR && \1", line) if self.cfg['hyperthreading'] is False: # disable hyperthreading (1 thread per core) @@ -325,20 +326,22 @@ def configure_step(self): line = re.sub(r"^(\s*set MAXNODES)=.*", r"\1=%s" % self.cfg['maxnodes'], line, 1) sys.stdout.write(line) except IOError as err: - raise EasyBuildError("Failed to patch compddi", compddi, err) + raise EasyBuildError("Failed to patch compddi", compddi, err) # for GAMESS-US 20200630-R1 we need to build the actvte.x program if self.version == "20200630-R1": actvte = os.path.join(self.builddir, 'tools/actvte.code') try: for line in fileinput.input(actvte, inplace=1, backup='.orig'): - line = re.sub("\*UNX", " ", line) + line = re.sub("[*]UNX", " ", line) sys.stdout.write(line) except IOError as err: raise EasyBuildError("Failed to patch actvte.code", actvte, err) # compiling run_cmd("mv %s/tools/actvte.code" % self.builddir + " %s/tools/actvte.f" % self.builddir) - run_cmd("%s -o " % fortran_comp + " %s/tools/actvte.x" % self.builddir + " %s/tools/actvte.f" % self.builddir) + run_cmd( + "%s -o " % fortran_comp + " %s/tools/actvte.x" % self.builddir + " %s/tools/actvte.f" % self.builddir + ) def build_step(self): """Custom build procedure for GAMESS-US: using compddi, compall and lked scripts.""" @@ -449,4 +452,3 @@ def cleanup_step(self): if os.path.isdir(scratch_path): remove_dir(scratch_path) self.log.info("Removed test scratch: %s", scratch_path) - From 9fd5be5e4a6b5d67084c87829fd25a439a1038d6 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Wed, 6 Dec 2023 18:20:39 +0100 Subject: [PATCH 25/41] fix variable names in gamess_us easyblock --- easybuild/easyblocks/g/gamess_us.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index cf8bdd00d9..02a073fc4c 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -118,7 +118,7 @@ def configure_step(self): # compiler config comp_fam = self.toolchain.comp_family() - fortran_comp, fortran_ver = None, None + fortran_comp, fortran_version = None, None if comp_fam == toolchain.INTELCOMP: fortran_comp = 'ifort' (out, _) = run_cmd("ifort -v", simple=False) @@ -250,7 +250,7 @@ def configure_step(self): if get_software_root('libxc'): installinfo_opts['GMS_LIBXC'] = "true" # the linker needs to be patched to use external libXC - lixc_libs = [os.path.join(os.environ['EBROOTLIBXC'], 'lib', l) for l in ['libxcf03.a', 'libxc.a']] + lixc_libs = [os.path.join(os.environ['EBROOTLIBXC'], 'lib', lib) for lib in ['libxcf03.a', 'libxc.a']] libxc_linker_flags = ' '.join(lixc_libs) try: lked = os.path.join(self.builddir, 'lked') From 2bd1871e9fc3bfac327036740f0ba0a897cf1088 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Mon, 11 Dec 2023 15:29:20 +0100 Subject: [PATCH 26/41] disable libcchem2 support in GAMESS-US v20230601+ --- easybuild/easyblocks/g/gamess_us.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 02a073fc4c..d9c98da3c2 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -239,9 +239,13 @@ def configure_step(self): # These are extra programs which for now we simply set all to FALSE installinfo_opts["GMS_MSUCC"] = "false" - installinfo_opts["GMS_LIBCCHEM"] = "false" installinfo_opts["GMS_PHI"] = "none" installinfo_opts["GMS_SHMTYPE"] = "sysv" + installinfo_opts["GMS_LIBCCHEM"] = "false" # libcchem + if LooseVersion(self.version) >= LooseVersion('20230601'): + # install options for libcchem2 + installinfo_opts["GMS_HPCCHEM"] = "false" + installinfo_opts["GMS_HPCCHEM_USE_DATA_SERVERS"] = "false" # Optional plug-ins and interfaces # libXC From d46d5a12ed74810772e35399ec2508080f287a80 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Tue, 12 Dec 2023 09:22:01 +0100 Subject: [PATCH 27/41] disable OpenMP offloading on Intel GPUs in GAMESS-US --- easybuild/easyblocks/g/gamess_us.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index d9c98da3c2..318a84594d 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -237,6 +237,12 @@ def configure_step(self): installinfo_opts["GMS_OPENMP"] = omp_enabled + # Accelerators (disabled) + # TODO: add support for GPUs + if LooseVersion(self.version) >= LooseVersion('20230601'): + # offloading onto Intel GPUs + installinfo_opts["GMS_OPENMP_OFFLOAD"] = "false" + # These are extra programs which for now we simply set all to FALSE installinfo_opts["GMS_MSUCC"] = "false" installinfo_opts["GMS_PHI"] = "none" From c0c0e5e7a85489a1b73baa9bb598633176fdbcb1 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Tue, 12 Dec 2023 09:22:20 +0100 Subject: [PATCH 28/41] disable Michigan State University code in GAMESS-US --- easybuild/easyblocks/g/gamess_us.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 318a84594d..f3f0d1da17 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -252,6 +252,8 @@ def configure_step(self): # install options for libcchem2 installinfo_opts["GMS_HPCCHEM"] = "false" installinfo_opts["GMS_HPCCHEM_USE_DATA_SERVERS"] = "false" + # build Michigan State University code + installinfo_opts["GMS_MSUAUTO"] = "false" # Optional plug-ins and interfaces # libXC From df5cfd1c04c29fe927c1aa1bec53b542f49ee137 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Tue, 12 Dec 2023 14:02:11 +0100 Subject: [PATCH 29/41] disable RISM plugin in GAMESS-US v20230601+ --- easybuild/easyblocks/g/gamess_us.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index f3f0d1da17..5a45ddc9ba 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -274,20 +274,23 @@ def configure_step(self): # MDI # needs https://github.com/MolSSI-MDI/MDI_Library installinfo_opts['GMS_MDI'] = "false" - # VM2 - installinfo_opts['GMS_VM2'] = "false" # NBO installinfo_opts['NBO'] = "false" if get_software_root('NBO'): installinfo_opts['NBO'] = "true" # NEO installinfo_opts['NEO'] = "false" + # RISM + if LooseVersion(self.version) >= LooseVersion('20230601'): + installinfo_opts['RISM'] = "false" # TINKER installinfo_opts['TINKER'] = "false" if get_software_root('TINKER'): installinfo_opts['TINKER'] = "true" # VB2000 installinfo_opts['VB2000'] = "false" + # VM2 + installinfo_opts['GMS_VM2'] = "false" # XMVB installinfo_opts['XMVB'] = "false" From b4b7479553c5e89bc3b7fff2f99cb939659bab19 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Fri, 15 Dec 2023 11:40:05 +0100 Subject: [PATCH 30/41] run GAMESS-US tests following the parallelism set in parallel setting --- easybuild/easyblocks/g/gamess_us.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 5a45ddc9ba..28614e4b0f 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -58,7 +58,6 @@ from easybuild.tools import toolchain GAMESS_INSTALL_INFO = 'install.info' -GAMESS_TEST_TASKS = 2 class EB_GAMESS_minus_US(EasyBlock): @@ -420,9 +419,10 @@ def test_step(self): # run all exam tests, dump output to exam.log # we let Python count the number of *.inp files as that changes tests_path = os.path.join(self.installdir, 'tests', 'standard') - n_tests = len(fnmatch.filter(os.listdir(tests_path), '*.inp')) - for i in range(1, n_tests+1): - rungms_cmd = [rungms, 'exam%02d' % i, self.version, str(GAMESS_TEST_TASKS), str(GAMESS_TEST_TASKS)] + tests_num = len(fnmatch.filter(os.listdir(tests_path), '*.inp')) + tests_procs = str(self.cfg['parallel']) + for i in range(1, tests_num+1): + rungms_cmd = [rungms, 'exam%02d' % i, self.version, tests_procs, tests_procs] test_cmd = ' '.join(test_env_vars + rungms_cmd) (out, _) = run_cmd(test_cmd, log_all=True, simple=False) write_file('exam%02d.log' % i, out) @@ -430,7 +430,7 @@ def test_step(self): # verify output of tests check_cmd = os.path.join(self.installdir, 'tests', 'standard', 'checktst') (out, _) = run_cmd(check_cmd, log_all=True, simple=False) - success_regex = re.compile("^All %d test results are correct" % n_tests, re.M) + success_regex = re.compile("^All %d test results are correct" % tests_num, re.M) if success_regex.search(out): self.log.info("All tests ran successfully!") else: From a017f26b9391cdf4494a112a2893b31cb0018262 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Sat, 16 Dec 2023 00:39:31 +0100 Subject: [PATCH 31/41] blacklist GAMESS-US tests not compatible with parallel execution --- easybuild/easyblocks/g/gamess_us.py | 47 ++++++++++++++++++----------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 28614e4b0f..4eb717c836 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -42,7 +42,6 @@ import shutil import sys import tempfile -import fnmatch from distutils.version import LooseVersion @@ -58,7 +57,14 @@ from easybuild.tools import toolchain GAMESS_INSTALL_INFO = 'install.info' - +GAMESS_MPI_TEST_BLACKLIST = [ + 'exam05', # only the gradients for CITYP=CIS run in parallel + 'exam32', # only CCTYP=CCSD or CCTYP=CCSD(T) can run in parallel + 'exam42', # ROHF'S CCTYP must be CCSD or CR-CCL, with serial execution + 'exam45', # only CCTYP=CCSD or CCTYP=CCSD(T) can run in parallel + 'exam46', # ROHF'S CCTYP must be CCSD or CR-CCL, with serial execution + 'exam47', # ROHF'S CCTYP must be CCSD or CR-CCL, with serial execution +] class EB_GAMESS_minus_US(EasyBlock): """Support for building/installing GAMESS-US.""" @@ -402,11 +408,16 @@ def test_step(self): cwd = change_dir(self.testdir) # copy input files for exam standard tests + target_tests = [] for test_input in glob.glob(os.path.join(self.installdir, 'tests', 'standard', 'exam*.inp')): - try: - shutil.copy2(test_input, os.getcwd()) - except OSError as err: - raise EasyBuildError("Failed to copy %s to %s: %s", test_input, os.getcwd(), err) + test_name = os.path.splitext(os.path.basename(test_input))[0] + if test_name not in GAMESS_MPI_TEST_BLACKLIST: + try: + shutil.copy2(test_input, os.getcwd()) + except OSError as err: + raise EasyBuildError("Failed to copy %s to %s: %s", test_input, os.getcwd(), err) + else: + target_tests.append(test_name) rungms = os.path.join(self.installdir, 'rungms') test_env_vars = ['export OMP_NUM_THREADS=1; TMPDIR=%s' % self.testdir] @@ -416,25 +427,25 @@ def test_step(self): 'I_MPI_HYDRA_BOOTSTRAP=fork', # tests are only run locally (2 processes), so no SSH required ]) - # run all exam tests, dump output to exam.log - # we let Python count the number of *.inp files as that changes - tests_path = os.path.join(self.installdir, 'tests', 'standard') - tests_num = len(fnmatch.filter(os.listdir(tests_path), '*.inp')) + # run target exam tests, dump output to exam.log tests_procs = str(self.cfg['parallel']) - for i in range(1, tests_num+1): - rungms_cmd = [rungms, 'exam%02d' % i, self.version, tests_procs, tests_procs] + for test_exam in target_tests: + rungms_cmd = [rungms, test_exam, self.version, tests_procs, tests_procs] test_cmd = ' '.join(test_env_vars + rungms_cmd) (out, _) = run_cmd(test_cmd, log_all=True, simple=False) - write_file('exam%02d.log' % i, out) + write_file('%s.log' % test_exam, out) - # verify output of tests check_cmd = os.path.join(self.installdir, 'tests', 'standard', 'checktst') (out, _) = run_cmd(check_cmd, log_all=True, simple=False) - success_regex = re.compile("^All %d test results are correct" % tests_num, re.M) - if success_regex.search(out): - self.log.info("All tests ran successfully!") + + # verify output of tests + failed_regex = re.compile(r"^.*!!FAILED\.$", re.M) + failed_tests = [exam[0:6] for exam in failed_regex.findall(out)] + if set(failed_tests) == set(GAMESS_MPI_TEST_BLACKLIST): + blacklisted_msg = "(blacklisted: %s)" % ", ".join(GAMESS_MPI_TEST_BLACKLIST) + self.log.info("All target tests ran successfully! %s", blacklisted_msg) else: - raise EasyBuildError("Not all tests ran successfully...") + raise EasyBuildError("ERROR: Not all target tests ran successfully") change_dir(cwd) From a9d1ef0f43c247e3e1e6041061935f0317a3729e Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Mon, 18 Dec 2023 10:32:19 +0100 Subject: [PATCH 32/41] run GAMESS-US tests in the scratch directory --- easybuild/easyblocks/g/gamess_us.py | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 4eb717c836..dcdc5728d9 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -49,7 +49,7 @@ from easybuild.framework.easyconfig import CUSTOM, MANDATORY from easybuild.tools.build_log import EasyBuildError from easybuild.tools.config import build_option -from easybuild.tools.filetools import change_dir, read_file, write_file, remove_dir +from easybuild.tools.filetools import change_dir, mkdir, read_file, write_file, remove_dir from easybuild.tools.modules import get_software_root, get_software_version from easybuild.tools.run import run_cmd from easybuild.tools.systemtools import POWER, X86_64 @@ -87,9 +87,20 @@ def __init__(self, *args, **kwargs): """Easyblock constructor, enable building in installation directory.""" super(EB_GAMESS_minus_US, self).__init__(*args, **kwargs) self.build_in_installdir = True + + # resolve path to scratch dir and make it + scratch_dir_resolved = os.path.expandvars(self.cfg['scratch_dir']) + if "$" in scratch_dir_resolved: + error_msg = "Provided scratch directory '%s' does not resolve into a path." + raise EasyBuildError(error_msg, self.cfg['scratch_dir']) + + mkdir(scratch_dir_resolved, parents=True) + self.testdir = None if self.cfg['runtest']: - self.testdir = tempfile.mkdtemp() + # run tests in scratch dir + self.testdir = tempfile.mkdtemp(dir=scratch_dir_resolved) + # make sure test dir doesn't contain [ or ], rungms csh script doesn't handle that well ("set: No match") if re.search(r'[\[\]]', self.testdir): error_msg = "Temporary dir for tests '%s' will cause problems with rungms csh script" @@ -420,7 +431,7 @@ def test_step(self): target_tests.append(test_name) rungms = os.path.join(self.installdir, 'rungms') - test_env_vars = ['export OMP_NUM_THREADS=1; TMPDIR=%s' % self.testdir] + test_env_vars = ['export OMP_NUM_THREADS=1; SCR=%s' % self.testdir] if self.toolchain.mpi_family() == toolchain.INTELMPI: test_env_vars.extend([ 'I_MPI_FALLBACK=enable', # enable fallback in case first fabric fails (see $I_MPI_FABRICS_LIST) @@ -472,9 +483,7 @@ def cleanup_step(self): """Cleanup set.""" super(EB_GAMESS_minus_US, self).cleanup_step() - # remove dedicated scratch directory (if any); - # we must use a shell command for this, since the path may contain environment variables - (scratch_path, _) = run_cmd('printf "%%s" "%s"' % self.cfg['scratch_dir'], simple=False) - if os.path.isdir(scratch_path): - remove_dir(scratch_path) - self.log.info("Removed test scratch: %s", scratch_path) + # remove test directory + if os.path.isdir(self.testdir): + remove_dir(self.testdir) + self.log.info("Removed test scratch: %s", self.testdir) From da4b7770252ffa37cfe29c6c589440b84b48cab2 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Mon, 18 Dec 2023 11:12:46 +0100 Subject: [PATCH 33/41] fix code formatting in GAMESS-US easyblock --- easybuild/easyblocks/g/gamess_us.py | 1 + 1 file changed, 1 insertion(+) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index dcdc5728d9..f1f941ca98 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -66,6 +66,7 @@ 'exam47', # ROHF'S CCTYP must be CCSD or CR-CCL, with serial execution ] + class EB_GAMESS_minus_US(EasyBlock): """Support for building/installing GAMESS-US.""" From b839b5dd1e09c7191304046fe79c9434a068b2c1 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Mon, 18 Dec 2023 14:05:55 +0100 Subject: [PATCH 34/41] move cleanup of test dir back to test step of GAMESS-US --- easybuild/easyblocks/g/gamess_us.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index f1f941ca98..22e2d711c4 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -459,7 +459,12 @@ def test_step(self): else: raise EasyBuildError("ERROR: Not all target tests ran successfully") + # cleanup change_dir(cwd) + try: + remove_dir(self.testdir) + except OSError as err: + raise EasyBuildError("Failed to remove test directory %s: %s", self.testdir, err) def install_step(self): """Skip install step, since we're building in the install directory.""" @@ -479,12 +484,3 @@ def make_module_extra(self): txt += self.module_generator.set_environment('GAMESSUSROOT', self.installdir) txt += self.module_generator.prepend_paths("PATH", ['']) return txt - - def cleanup_step(self): - """Cleanup set.""" - super(EB_GAMESS_minus_US, self).cleanup_step() - - # remove test directory - if os.path.isdir(self.testdir): - remove_dir(self.testdir) - self.log.info("Removed test scratch: %s", self.testdir) From cf206fb485fdcda4344f45c677811ee57550cca3 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Mon, 18 Dec 2023 14:07:03 +0100 Subject: [PATCH 35/41] replace shutil.copy2 with filetools.copy_files method in GAMESS-US --- easybuild/easyblocks/g/gamess_us.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 22e2d711c4..b6e6655e75 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -39,7 +39,6 @@ import glob import os import re -import shutil import sys import tempfile @@ -49,7 +48,7 @@ from easybuild.framework.easyconfig import CUSTOM, MANDATORY from easybuild.tools.build_log import EasyBuildError from easybuild.tools.config import build_option -from easybuild.tools.filetools import change_dir, mkdir, read_file, write_file, remove_dir +from easybuild.tools.filetools import change_dir, copy_file, mkdir, read_file, write_file, remove_dir from easybuild.tools.modules import get_software_root, get_software_version from easybuild.tools.run import run_cmd from easybuild.tools.systemtools import POWER, X86_64 @@ -417,7 +416,11 @@ def test_step(self): self.log.info("Skipping testing of GAMESS-US as MPI tests need at least 2 CPU cores to run") return - cwd = change_dir(self.testdir) + try: + cwd = os.getcwd() + change_dir(self.testdir) + except OSError as err: + raise EasyBuildError("Failed to move to temporary directory for running tests: %s", err) # copy input files for exam standard tests target_tests = [] @@ -425,9 +428,9 @@ def test_step(self): test_name = os.path.splitext(os.path.basename(test_input))[0] if test_name not in GAMESS_MPI_TEST_BLACKLIST: try: - shutil.copy2(test_input, os.getcwd()) + copy_file(test_input, self.testdir) except OSError as err: - raise EasyBuildError("Failed to copy %s to %s: %s", test_input, os.getcwd(), err) + raise EasyBuildError("Failed to copy %s to %s: %s", test_input, self.testdir, err) else: target_tests.append(test_name) From 2d513f25aa9d6d1c7ef005678d1dbcffc3898f1a Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Mon, 18 Dec 2023 14:09:46 +0100 Subject: [PATCH 36/41] replace distutils.LooseVersion with easybuild.tools.LooseVersion in GAMESS-US easyblock --- easybuild/easyblocks/g/gamess_us.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index b6e6655e75..e8fd7d8512 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -42,8 +42,6 @@ import sys import tempfile -from distutils.version import LooseVersion - from easybuild.framework.easyblock import EasyBlock from easybuild.framework.easyconfig import CUSTOM, MANDATORY from easybuild.tools.build_log import EasyBuildError @@ -53,7 +51,7 @@ from easybuild.tools.run import run_cmd from easybuild.tools.systemtools import POWER, X86_64 from easybuild.tools.systemtools import get_cpu_architecture -from easybuild.tools import toolchain +from easybuild.tools import LooseVersion, toolchain GAMESS_INSTALL_INFO = 'install.info' GAMESS_MPI_TEST_BLACKLIST = [ From 9af8f84c87e8d57a5a52f59def57c99f2538ab34 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Thu, 21 Dec 2023 09:46:41 +0100 Subject: [PATCH 37/41] add support for GMS_THREADED_BLAS in 2023+ versions of GAMESS-US --- easybuild/easyblocks/g/gamess_us.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index e8fd7d8512..0c73fc6063 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -130,7 +130,7 @@ def configure_step(self): installinfo_opts["GMS_TARGET"] = machinetype installinfo_opts["GMS_HPC_SYSTEM_TARGET"] = "generic" - # compiler config + # Compiler config comp_fam = self.toolchain.comp_family() fortran_comp, fortran_version = None, None if comp_fam == toolchain.INTELCOMP: @@ -152,7 +152,15 @@ def configure_step(self): installinfo_opts["GMS_FORTRAN"] = fortran_comp installinfo_opts.update(fortran_version) - # math library config + # OpenMP config + if self.toolchain.options.get('openmp', None): + omp_enabled = "true" + else: + omp_enabled = "false" + + installinfo_opts["GMS_OPENMP"] = omp_enabled + + # Math library config known_mathlibs = ['imkl', 'OpenBLAS', 'ATLAS', 'ACML'] loaded_mathlib = [mathlib for mathlib in known_mathlibs if get_software_root(mathlib)] @@ -177,6 +185,9 @@ def configure_step(self): mkl_version = 'oneapi' installinfo_opts["GMS_MKL_VERNO"] = mkl_version + if LooseVersion(self.version) >= LooseVersion('20230601'): + installinfo_opts["GMS_THREADED_BLAS"] = omp_enabled + elif mathlib == 'openblas': mathlib_flags = "-lopenblas -lgfortran" if LooseVersion(self.version) >= LooseVersion('20210101'): @@ -243,14 +254,6 @@ def configure_step(self): installinfo_opts["GMS_MPI_LIB"] = mpilib installinfo_opts["GMS_MPI_PATH"] = mpilib_path - # OpenMP config - if self.toolchain.options.get('openmp', None): - omp_enabled = "true" - else: - omp_enabled = "false" - - installinfo_opts["GMS_OPENMP"] = omp_enabled - # Accelerators (disabled) # TODO: add support for GPUs if LooseVersion(self.version) >= LooseVersion('20230601'): From c79e6e250d03ef6013b7d63677bfd25dd8f65b83 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Sat, 3 Feb 2024 10:58:24 +0100 Subject: [PATCH 38/41] execute all tests in serial for non-mpi builds of GAMESS-US --- easybuild/easyblocks/g/gamess_us.py | 90 ++++++++++++++++------------- 1 file changed, 51 insertions(+), 39 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 0c73fc6063..d68e96c2db 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -54,7 +54,7 @@ from easybuild.tools import LooseVersion, toolchain GAMESS_INSTALL_INFO = 'install.info' -GAMESS_MPI_TEST_BLACKLIST = [ +GAMESS_SERIAL_TESTS = [ 'exam05', # only the gradients for CITYP=CIS run in parallel 'exam32', # only CCTYP=CCSD or CCTYP=CCSD(T) can run in parallel 'exam42', # ROHF'S CCTYP must be CCSD or CR-CCL, with serial execution @@ -406,60 +406,72 @@ def build_step(self): def test_step(self): """Run GAMESS-US tests (if 'runtest' easyconfig parameter is set to True).""" - # don't use provided 'runall' script for tests, since that only runs the tests single-core if self.cfg['runtest']: - - if not build_option('mpi_tests'): - self.log.info("Skipping testing of GAMESS-US since MPI testing is disabled") - return - - if int(self.cfg['parallel']) < 2: - self.log.info("Skipping testing of GAMESS-US as MPI tests need at least 2 CPU cores to run") - return - + # Avoid provided 'runall' script for tests, since that only runs the tests in serial + # Tests must be run in parallel for MPI builds and can be run serial for other build types + + target_tests = [ + # (test name, path to test input) + (os.path.splitext(os.path.basename(exam_file))[0], exam_file) + for exam_file in glob.glob(os.path.join(self.installdir, 'tests', 'standard', 'exam*.inp')) + ] + test_procs = "1" + test_env_vars = ['export OMP_NUM_THREADS=1'] + + if self.cfg['ddi_comm'] == 'mpi': + if not build_option('mpi_tests'): + self.log.info("Skipping tests of MPI build of GAMESS-US by user request ('mpi_tests' is disabled)") + retur + + # MPI builds can only run tests that support parallel execution + if int(self.cfg['parallel']) < 2: + self.log.info("Skipping testing of GAMESS-US as MPI tests need at least 2 CPU cores to run") + return + + test_procs = str(self.cfg['parallel']) + target_tests = [exam for exam in target_tests if exam[0] not in GAMESS_SERIAL_TESTS] + + if self.toolchain.mpi_family() == toolchain.INTELMPI: + test_env_vars.extend([ + 'export I_MPI_FALLBACK=enable', # enable fallback in case first fabric fails (see $I_MPI_FABRICS_LIST) + 'export I_MPI_HYDRA_BOOTSTRAP=fork', # tests are only run locally (2 processes), so no SSH required + ]) + + # Prepare test directory to run tests try: cwd = os.getcwd() change_dir(self.testdir) except OSError as err: raise EasyBuildError("Failed to move to temporary directory for running tests: %s", err) - # copy input files for exam standard tests - target_tests = [] - for test_input in glob.glob(os.path.join(self.installdir, 'tests', 'standard', 'exam*.inp')): - test_name = os.path.splitext(os.path.basename(test_input))[0] - if test_name not in GAMESS_MPI_TEST_BLACKLIST: - try: - copy_file(test_input, self.testdir) - except OSError as err: - raise EasyBuildError("Failed to copy %s to %s: %s", test_input, self.testdir, err) - else: - target_tests.append(test_name) + for exam, exam_file in target_tests: + try: + copy_file(exam_file, self.testdir) + except OSError as err: + raise EasyBuildError("Failed to copy test '%s' to %s: %s", exam, self.testdir, err) - rungms = os.path.join(self.installdir, 'rungms') - test_env_vars = ['export OMP_NUM_THREADS=1; SCR=%s' % self.testdir] - if self.toolchain.mpi_family() == toolchain.INTELMPI: - test_env_vars.extend([ - 'I_MPI_FALLBACK=enable', # enable fallback in case first fabric fails (see $I_MPI_FABRICS_LIST) - 'I_MPI_HYDRA_BOOTSTRAP=fork', # tests are only run locally (2 processes), so no SSH required - ]) + test_env_vars.append('SCR=%s' % self.testdir) # run target exam tests, dump output to exam.log - tests_procs = str(self.cfg['parallel']) - for test_exam in target_tests: - rungms_cmd = [rungms, test_exam, self.version, tests_procs, tests_procs] - test_cmd = ' '.join(test_env_vars + rungms_cmd) - (out, _) = run_cmd(test_cmd, log_all=True, simple=False) - write_file('%s.log' % test_exam, out) + rungms = os.path.join(self.installdir, 'rungms') + for exam, exam_file in target_tests: + rungms_prefix = ' && '.join(test_env_vars) + test_cmd = [rungms_prefix, rungms, exam_file, self.version, test_procs, test_procs] + (out, _) = run_cmd(' '.join(test_cmd), log_all=True, simple=False) + write_file('%s.log' % exam, out) check_cmd = os.path.join(self.installdir, 'tests', 'standard', 'checktst') (out, _) = run_cmd(check_cmd, log_all=True, simple=False) # verify output of tests failed_regex = re.compile(r"^.*!!FAILED\.$", re.M) - failed_tests = [exam[0:6] for exam in failed_regex.findall(out)] - if set(failed_tests) == set(GAMESS_MPI_TEST_BLACKLIST): - blacklisted_msg = "(blacklisted: %s)" % ", ".join(GAMESS_MPI_TEST_BLACKLIST) - self.log.info("All target tests ran successfully! %s", blacklisted_msg) + failed_tests = set([exam[0:6] for exam in failed_regex.findall(out)]) + done_tests = set([exam[0] for exam in target_tests]) + if done_tests - failed_tests == done_tests: + info_msg = "All target tests ran successfully!" + if self.cfg['ddi_comm'] == 'mpi': + info_msg += " (serial tests ignored: %s)" % ", ".join(GAMESS_SERIAL_TESTS) + self.log.info(info_msg) else: raise EasyBuildError("ERROR: Not all target tests ran successfully") From 253ef5b522dd3b266278ef25c3220174adf06cdd Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Sat, 3 Feb 2024 11:02:26 +0100 Subject: [PATCH 39/41] fix code formatting in GAMESS-US easyblock --- easybuild/easyblocks/g/gamess_us.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index d68e96c2db..60b2b32397 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -421,7 +421,7 @@ def test_step(self): if self.cfg['ddi_comm'] == 'mpi': if not build_option('mpi_tests'): self.log.info("Skipping tests of MPI build of GAMESS-US by user request ('mpi_tests' is disabled)") - retur + return # MPI builds can only run tests that support parallel execution if int(self.cfg['parallel']) < 2: @@ -433,8 +433,10 @@ def test_step(self): if self.toolchain.mpi_family() == toolchain.INTELMPI: test_env_vars.extend([ - 'export I_MPI_FALLBACK=enable', # enable fallback in case first fabric fails (see $I_MPI_FABRICS_LIST) - 'export I_MPI_HYDRA_BOOTSTRAP=fork', # tests are only run locally (2 processes), so no SSH required + # enable fallback in case first fabric fails (see $I_MPI_FABRICS_LIST) + 'export I_MPI_FALLBACK=enable', + # tests are only run locally (single node), so no SSH required + 'export I_MPI_HYDRA_BOOTSTRAP=fork', ]) # Prepare test directory to run tests From 1bfd25373dca72660f725b65e87833420d8dd936 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Tue, 7 May 2024 15:34:47 +0200 Subject: [PATCH 40/41] swicth OpenMP in GAMESS-US through GMS_OPENMP and disable toolchain option --- easybuild/easyblocks/g/gamess_us.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 60b2b32397..a3d0625cae 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -104,6 +104,13 @@ def __init__(self, *args, **kwargs): error_msg = "Temporary dir for tests '%s' will cause problems with rungms csh script" raise EasyBuildError(error_msg, self.testdir) + # OpenMP cannot be enabled across the board, activate it only through + # GMS_OPENMP so that it gets enabled by the build where needed + self.omp_enabled = False + if self.toolchain.options.get('openmp', None): + self.omp_enabled = True + self.toolchain.options['openmp'] = False + def extract_step(self): """Extract sources.""" # strip off 'gamess' part to avoid having everything in a 'gamess' subdirectory @@ -153,12 +160,7 @@ def configure_step(self): installinfo_opts.update(fortran_version) # OpenMP config - if self.toolchain.options.get('openmp', None): - omp_enabled = "true" - else: - omp_enabled = "false" - - installinfo_opts["GMS_OPENMP"] = omp_enabled + installinfo_opts["GMS_OPENMP"] = self.omp_enabled # Math library config known_mathlibs = ['imkl', 'OpenBLAS', 'ATLAS', 'ACML'] @@ -186,7 +188,7 @@ def configure_step(self): installinfo_opts["GMS_MKL_VERNO"] = mkl_version if LooseVersion(self.version) >= LooseVersion('20230601'): - installinfo_opts["GMS_THREADED_BLAS"] = omp_enabled + installinfo_opts["GMS_THREADED_BLAS"] = self.omp_enabled elif mathlib == 'openblas': mathlib_flags = "-lopenblas -lgfortran" From 49e0c87a146f9b9acc02244c9a3b35e7ce196cea Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Tue, 7 May 2024 15:36:06 +0200 Subject: [PATCH 41/41] use real booleans for true/false install.info options in GAMESS-US easyblock --- easybuild/easyblocks/g/gamess_us.py | 45 +++++++++++++++-------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index a3d0625cae..ca03c51714 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -260,26 +260,26 @@ def configure_step(self): # TODO: add support for GPUs if LooseVersion(self.version) >= LooseVersion('20230601'): # offloading onto Intel GPUs - installinfo_opts["GMS_OPENMP_OFFLOAD"] = "false" + installinfo_opts["GMS_OPENMP_OFFLOAD"] = False # These are extra programs which for now we simply set all to FALSE - installinfo_opts["GMS_MSUCC"] = "false" + installinfo_opts["GMS_MSUCC"] = False installinfo_opts["GMS_PHI"] = "none" installinfo_opts["GMS_SHMTYPE"] = "sysv" - installinfo_opts["GMS_LIBCCHEM"] = "false" # libcchem + installinfo_opts["GMS_LIBCCHEM"] = False # libcchem if LooseVersion(self.version) >= LooseVersion('20230601'): # install options for libcchem2 - installinfo_opts["GMS_HPCCHEM"] = "false" - installinfo_opts["GMS_HPCCHEM_USE_DATA_SERVERS"] = "false" + installinfo_opts["GMS_HPCCHEM"] = False + installinfo_opts["GMS_HPCCHEM_USE_DATA_SERVERS"] = False # build Michigan State University code - installinfo_opts["GMS_MSUAUTO"] = "false" + installinfo_opts["GMS_MSUAUTO"] = False # Optional plug-ins and interfaces # libXC if LooseVersion(self.version) >= LooseVersion('20200101'): - installinfo_opts['GMS_LIBXC'] = "false" + installinfo_opts['GMS_LIBXC'] = False if get_software_root('libxc'): - installinfo_opts['GMS_LIBXC'] = "true" + installinfo_opts['GMS_LIBXC'] = True # the linker needs to be patched to use external libXC lixc_libs = [os.path.join(os.environ['EBROOTLIBXC'], 'lib', lib) for lib in ['libxcf03.a', 'libxc.a']] libxc_linker_flags = ' '.join(lixc_libs) @@ -292,26 +292,26 @@ def configure_step(self): raise EasyBuildError("Failed to patch %s: %s", lked, err) # MDI # needs https://github.com/MolSSI-MDI/MDI_Library - installinfo_opts['GMS_MDI'] = "false" + installinfo_opts['GMS_MDI'] = False # NBO - installinfo_opts['NBO'] = "false" + installinfo_opts['NBO'] = False if get_software_root('NBO'): - installinfo_opts['NBO'] = "true" + installinfo_opts['NBO'] = True # NEO - installinfo_opts['NEO'] = "false" + installinfo_opts['NEO'] = False # RISM if LooseVersion(self.version) >= LooseVersion('20230601'): - installinfo_opts['RISM'] = "false" + installinfo_opts['RISM'] = False # TINKER - installinfo_opts['TINKER'] = "false" + installinfo_opts['TINKER'] = False if get_software_root('TINKER'): - installinfo_opts['TINKER'] = "true" + installinfo_opts['TINKER'] = True # VB2000 - installinfo_opts['VB2000'] = "false" + installinfo_opts['VB2000'] = False # VM2 - installinfo_opts['GMS_VM2'] = "false" + installinfo_opts['GMS_VM2'] = False # XMVB - installinfo_opts['XMVB'] = "false" + installinfo_opts['XMVB'] = False # add include paths from dependencies installinfo_opts["GMS_FPE_FLAGS"] = '"%s"' % os.environ['CPPFLAGS'] @@ -319,10 +319,13 @@ def configure_step(self): # installinfo_opts["GMS_FPE_FLAGS"] = '"%s"' % os.environ['CPPFLAGS'] + "-ffpe-trap=invalid,zero,overflow" # write install.info file with configuration settings - # format: setenv KEY VALUE installinfo_file = os.path.join(self.builddir, GAMESS_INSTALL_INFO) - txt = '\n'.join(["setenv %s %s" % (k, installinfo_opts[k]) for k in installinfo_opts]) - write_file(installinfo_file, txt) + # replace boolean options with their string representation + boolean_opts = {opt: str(val).lower() for opt, val in installinfo_opts.items() if val in [True, False]} + installinfo_opts.update(boolean_opts) + # format: setenv KEY VALUE + installinfo_txt = '\n'.join(["setenv %s %s" % (k, installinfo_opts[k]) for k in installinfo_opts]) + write_file(installinfo_file, installinfo_txt) self.log.debug("Contents of %s:\n%s" % (installinfo_file, read_file(installinfo_file))) # patch hardcoded settings in rungms to use values specified in easyconfig file