Skip to content

Commit

Permalink
Merge pull request #3342 from lexming/gamess-5.0
Browse files Browse the repository at this point in the history
Make GAMESS-US easyblock compliant with EasyBuild 5.0
  • Loading branch information
boegel authored May 30, 2024
2 parents d0ab8a1 + 0edfbc9 commit 3f8fccd
Showing 1 changed file with 36 additions and 38 deletions.
74 changes: 36 additions & 38 deletions easybuild/easyblocks/g/gamess_us.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
from easybuild.tools.config import build_option
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.run import run_shell_cmd
from easybuild.tools.systemtools import POWER, X86_64
from easybuild.tools.systemtools import get_cpu_architecture
from easybuild.tools import LooseVersion, toolchain
Expand Down Expand Up @@ -142,10 +142,10 @@ def configure_step(self):
fortran_comp, fortran_version = None, None
if comp_fam == toolchain.INTELCOMP:
fortran_comp = 'ifort'
(out, _) = run_cmd("ifort -v", simple=False)
res = re.search(r"^ifort version ([0-9]+)\.[0-9.]+$", out)
res = run_shell_cmd("ifort -v")
regex = re.compile(r"^ifort version ([0-9]+)\.[0-9.]+$")
try:
version_num = res.group(1)
version_num = re.search(regex, res.output).group(1)
except (AttributeError, IndexError):
raise EasyBuildError("Failed to determine ifort major version number")
fortran_version = {"GMS_IFORT_VERNO": version_num}
Expand Down Expand Up @@ -203,7 +203,7 @@ def configure_step(self):

installinfo_opts["GMS_MATHLIB"] = mathlib
installinfo_opts["GMS_MATHLIB_PATH"] = mathlib_path
installinfo_opts["GMS_LAPACK_LINK_LINE"] = '"%s"' % mathlib_flags
installinfo_opts["GMS_LAPACK_LINK_LINE"] = f'"{mathlib_flags}"'

# verify selected DDI communication layer
known_ddi_comms = ['mpi', 'mixed', 'shmem', 'sockets']
Expand Down Expand Up @@ -286,7 +286,7 @@ def configure_step(self):
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)
line = re.sub(r"^(\s*set\sLIBXC_FLAGS)=.*GMS_PATH.*", rf'\1="{libxc_linker_flags}"', line)
sys.stdout.write(line)
except IOError as err:
raise EasyBuildError("Failed to patch %s: %s", lked, err)
Expand Down Expand Up @@ -314,7 +314,7 @@ def configure_step(self):
installinfo_opts['XMVB'] = False

# add include paths from dependencies
installinfo_opts["GMS_FPE_FLAGS"] = '"%s"' % os.environ['CPPFLAGS']
installinfo_opts["GMS_FPE_FLAGS"] = f"\"{os.environ['CPPFLAGS']}\""
# might be useful for debugging
# installinfo_opts["GMS_FPE_FLAGS"] = '"%s"' % os.environ['CPPFLAGS'] + "-ffpe-trap=invalid,zero,overflow"

Expand All @@ -324,27 +324,27 @@ def configure_step(self):
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])
installinfo_txt = '\n'.join([f"setenv {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)))
self.log.debug(f"Contents of {installinfo_file}:\n{read_file(installinfo_file)}")

# 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"(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)
line = re.sub(r"^(\s*set\s*TARGET)=.*", rf"\1={self.cfg['ddi_comm']}", line)
line = re.sub(r"^(\s*set\s*GMSPATH)=.*", rf"\1={self.installdir}\n{extra_gmspath_lines}", line)
line = re.sub(r"(null\) set VERNO)=.*", rf"\1={self.version}", line)
line = re.sub(r"^(\s*set DDI_MPI_CHOICE)=.*", rf"\1={mpilib}", line)
line = re.sub(rf"^(\s*set DDI_MPI_ROOT)=.*{mpilib.lower()}.*", rf"\1={mpilib_path}", line)
line = re.sub(rf"^(\s*set GA_MPI_ROOT)=.*{mpilib.lower()}.*", rf"\1={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)
# 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*SCR)=.*", rf"if ( ! $?SCR ) \1={self.cfg['scratch_dir']}", line)
line = re.sub(
r"^(\s*set\s*USERSCR)=.*", r"if ( ! $?USERSCR ) \1=%s" % self.cfg['user_scratch_dir'], line
r"^(\s*set\s*USERSCR)=.*", rf"if ( ! $?USERSCR ) \1={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:
Expand All @@ -359,8 +359,8 @@ def configure_step(self):
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)
line = re.sub(r"^(\s*set MAXCPUS)=.*", rf"\1={self.cfg['maxcpus']}", line, 1)
line = re.sub(r"^(\s*set MAXNODES)=.*", rf"\1={self.cfg['maxnodes']}", line, 1)
sys.stdout.write(line)
except IOError as err:
raise EasyBuildError("Failed to patch compddi", compddi, err)
Expand All @@ -375,39 +375,37 @@ def configure_step(self):
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_shell_cmd(f"mv {self.builddir}/tools/actvte.code {self.builddir}/tools/actvte.f")
run_shell_cmd(f"{fortran_comp} -o {self.builddir}/tools/actvte.x {self.builddir}/tools/actvte.f")

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)
run_shell_cmd(compddi)

# 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)
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)
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))
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)
compall = " ".join([self.cfg['prebuildopts'], compall_cmd, self.cfg['buildopts']])
run_shell_cmd(compall)

cmd = "%s gamess %s" % (os.path.join(self.cfg['start_dir'], 'lked'), self.version)
run_cmd(cmd, log_all=True, simple=True)
gamess_cmd = f"{os.path.join(self.cfg['start_dir'], 'lked')} gamess {self.version}"
run_shell_cmd(gamess_cmd)

def test_step(self):
"""Run GAMESS-US tests (if 'runtest' easyconfig parameter is set to True)."""
Expand Down Expand Up @@ -457,27 +455,27 @@ def test_step(self):
except OSError as err:
raise EasyBuildError("Failed to copy test '%s' to %s: %s", exam, self.testdir, err)

test_env_vars.append('SCR=%s' % self.testdir)
test_env_vars.append(f"SCR={self.testdir}")

# run target exam<id> tests, dump output to exam<id>.log
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)
res = run_shell_cmd(' '.join(test_cmd))
write_file(f"{exam}.log", res.output)

check_cmd = os.path.join(self.installdir, 'tests', 'standard', 'checktst')
(out, _) = run_cmd(check_cmd, log_all=True, simple=False)
res = run_shell_cmd(check_cmd)

# verify output of tests
failed_regex = re.compile(r"^.*!!FAILED\.$", re.M)
failed_tests = set([exam[0:6] for exam in failed_regex.findall(out)])
failed_tests = set([exam[0:6] for exam in failed_regex.findall(res.output)])
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)
info_msg += f" (serial tests ignored: {', '.join(GAMESS_SERIAL_TESTS)})"
self.log.info(info_msg)
else:
raise EasyBuildError("ERROR: Not all target tests ran successfully")
Expand All @@ -496,7 +494,7 @@ def install_step(self):
def sanity_check_step(self):
"""Custom sanity check for GAMESS-US."""
custom_paths = {
'files': ['gamess.%s.x' % self.version, 'rungms'],
'files': [f'gamess.{self.version}.x', 'rungms'],
'dirs': [],
}
super(EB_GAMESS_minus_US, self).sanity_check_step(custom_paths=custom_paths)
Expand Down

0 comments on commit 3f8fccd

Please sign in to comment.