Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add easyblock for CFDEMcoupling #1439

Merged
merged 5 commits into from Oct 16, 2020
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
159 changes: 159 additions & 0 deletions easybuild/easyblocks/c/cfdemcoupling.py
@@ -0,0 +1,159 @@
##
# Copyright 2018-2018 Ghent University
#
# This file is part of EasyBuild,
# originally created by the HPC team of Ghent University (http://ugent.be/hpc/en),
# with support of Ghent University (http://ugent.be/hpc),
# the Flemish Supercomputer Centre (VSC) (https://www.vscentrum.be),
# Flemish Research Foundation (FWO) (http://www.fwo.be/en)
# and the Department of Economy, Science and Innovation (EWI) (http://www.ewi-vlaanderen.be/en).
#
# https://github.com/easybuilders/easybuild
#
# EasyBuild is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation v2.
#
# EasyBuild is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with EasyBuild. If not, see <http://www.gnu.org/licenses/>.
##
"""
EasyBuild support for building and installing CFDEMcoupling, implemented as an easyblock

@author: Kenneth Hoste (Ghent University)
"""
import glob
import os

import easybuild.tools.environment as env
import easybuild.tools.toolchain as toolchain
from easybuild.framework.easyblock import EasyBlock
from easybuild.tools.build_log import EasyBuildError
from easybuild.tools.filetools import copy_file, mkdir, move_file
from easybuild.tools.modules import get_software_root, get_software_version
from easybuild.tools.run import run_cmd


class EB_CFDEMcoupling(EasyBlock):
"""Support for building/installing CFDEMcoupling."""

def __init__(self, *args, **kwargs):
"""Initialisation of custom class variables for CFDEMcoupling."""
super(EB_CFDEMcoupling, self).__init__(*args, **kwargs)

self.build_in_installdir = True

self.cfdem_project_dir = os.path.join(self.installdir, '%s-%s' % (self.name, self.version))
self.liggghts_dir = os.path.join(self.installdir, 'LIGGGHTS-%s' % self.version)

def configure_step(self):
"""Set up environment for building/installing CFDEMcoupling."""

# rename top-level directory to CFDEMcoupling-<version>
top_dirs = os.listdir(self.builddir)

for (pkgname, target_dir) in [('CFDEMcoupling', self.cfdem_project_dir), ('LIGGGHTS', self.liggghts_dir)]:
pkg_topdirs = [d for d in top_dirs if d.startswith(pkgname)]
if len(pkg_topdirs) == 1:
orig_dir = os.path.join(self.builddir, pkg_topdirs[0])
move_file(orig_dir, target_dir)
else:
raise EasyBuildError("Failed to find subdirectory for %s in %s %s", pkgname, self.builddir, top_dirs)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe suggest here that the sources for that package might be missing? If LIGGGTHS is missing easybuild will proceed until this point and then say that the directory hasn't been found, but giving no clue about the reason.


# always use env.setvar instead of os.putenv or os.environ for defining environment variables
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems more like a guideline for easyblock developers than a relevant comment for this particular easyblock. I'd remove it.

env.setvar('CFDEM_VERSION', self.version)
env.setvar('CFDEM_PROJECT_DIR', self.cfdem_project_dir)

# define $CFDEM_PROJECT_USER_DIR to an empty existing directory
env.setvar('CFDEM_PROJECT_USER_DIR', os.path.join(self.builddir, 'CFDEM_PROJECT_USER_DIR'))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CFDEM_PROJECT_USER_DIR seems to me like a weird name for a directory, and it is confusing that the directory name is the same as the environment variable. I suggest to rename it to user_dir or something similar.

mkdir(os.getenv('CFDEM_PROJECT_USER_DIR'), parents=True)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems odd to set a variable and read it right after. Not that it matters a lot, but it is certainly not efficient. Doesn't it make more sense to define a python variable and use it in both places?


cfdem_bashrc = os.path.join(self.cfdem_project_dir, 'src', 'lagrangian', 'cfdemParticle', 'etc', 'bashrc')
env.setvar('CFDEM_bashrc', cfdem_bashrc)

env.setvar('CFDEM_LIGGGHTS_SRC_DIR', os.path.join(self.liggghts_dir, 'src'))
env.setvar('CFDEM_LIGGGHTS_MAKEFILE_NAME', 'auto')

lpp_dirs = glob.glob(os.path.join(self.builddir, 'LPP-*'))
if len(lpp_dirs) == 1:
env.setvar('CFDEM_LPP_DIR', lpp_dirs[0])
else:
raise EasyBuildError("Failed to isolate LPP-* directory in %s", self.builddir)

# build in parallel
env.setvar("WM_NCOMPPROCS", str(self.cfg['parallel']))

vtk_root = get_software_root('VTK')
if vtk_root:
vtk_ver_maj_min = '.'.join(get_software_version('VTK').split('.')[:2])
env.setvar('VTK_INC_USR', '-I%s' % os.path.join(vtk_root, 'include', 'vtk-%s' % vtk_ver_maj_min))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it makes sense to check if these directories exists and are not empty.

env.setvar('VTK_LIB_USR', '-L%s' % os.path.join(vtk_root, 'lib'))
else:
raise EasyBuildError("VTK not included as dependency")

# can't seem to use defined 'cfdemSysTest' alias...
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure I understand the meaning of this comment.......

cmd = "source $CFDEM_bashrc && $CFDEM_SRC_DIR/lagrangian/cfdemParticle/etc/cfdemSystemTest.sh"
run_cmd(cmd, log_all=True, simple=True, log_ok=True)

def build_step(self):
"""Custom build procedure for CFDEMcoupling."""

if get_software_root('OpenFOAM'):
openfoam_ver = get_software_version('OpenFOAM')
openfoam_maj_ver = openfoam_ver.split('.')[0]
else:
raise EasyBuildError("OpenFOAM not included as dependency")

# make sure expected additionalLibs_* file is available
addlibs_subdir = os.path.join('src', 'lagrangian', 'cfdemParticle', 'etc', 'addLibs_universal')
src_addlibs = os.path.join(self.cfdem_project_dir, addlibs_subdir, 'additionalLibs_%s.x' % openfoam_maj_ver)
target_addlibs = os.path.join(self.cfdem_project_dir, addlibs_subdir, 'additionalLibs_%s' % openfoam_ver)
copy_file(src_addlibs, target_addlibs)

# can't seem to use defined 'cfdemCompCFDEMall' alias...
akesandgren marked this conversation as resolved.
Show resolved Hide resolved
cmd = "$CFDEM_SRC_DIR/lagrangian/cfdemParticle/etc/compileCFDEMcoupling_all.sh"
run_cmd("source $FOAM_BASH && source $CFDEM_bashrc && %s" % cmd, log_all=True, simple=True, log_ok=True)

def install_step(self):
"""No custom install procedure for CFDEMcoupling."""
pass

def sanity_check_step(self):
"""Custom sanity check for CFDEMcoupling."""
comp_fam = self.toolchain.comp_family()
if comp_fam == toolchain.GCC:
wm_compiler = 'Gcc'
elif comp_fam == toolchain.INTELCOMP:
wm_compiler = 'Icc'
else:
raise EasyBuildError("Unknown compiler family, don't know how to set WM_COMPILER")

psubdir = "linux64%sDPInt32Opt" % wm_compiler
akesandgren marked this conversation as resolved.
Show resolved Hide resolved

cfdem_base_dir = os.path.basename(self.cfdem_project_dir)
bins = ['cfdemPostproc', 'cfdemSolverIB', 'cfdemSolverPiso', 'cfdemSolverPisoScalar', 'cfdemSolverPisoSTM']
custom_paths = {
'files': [os.path.join(cfdem_base_dir, 'platforms', psubdir, 'bin', b) for b in bins],
'dirs': [os.path.join(cfdem_base_dir, 'platforms', psubdir, 'lib')],
}
super(EB_CFDEMcoupling, self).sanity_check_step(custom_paths=custom_paths)

def make_module_extra(self):
"""Custom extra module file entries for CFDEMcoupling."""

txt = super(EB_CFDEMcoupling, self).make_module_extra()

txt += self.module_generator.set_environment('CFDEM_VERSION', self.version)
txt += self.module_generator.set_environment('CFDEM_PROJECT_DIR', self.cfdem_project_dir)
txt += self.module_generator.set_environment('CFDEM_LIGGGHTS_SRC_DIR', os.path.join(self.liggghts_dir, 'src'))
txt += self.module_generator.set_environment('CFDEM_LIGGGHTS_MAKEFILE_NAME', 'auto')

cfdem_bashrc = os.path.join(self.cfdem_project_dir, 'src', 'lagrangian', 'cfdemParticle', 'etc', 'bashrc')
txt += self.module_generator.set_environment('CFDEM_bashrc', cfdem_bashrc)

return txt