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 support for CP2K QM/MM in GROMACS easyblock #2750

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from

Conversation

ostueker
Copy link
Contributor

This PR implements building GROMACS with CP2K QM/MM enabled.

As such a version of GROMACS needs to be compiled statically, which doesn't generate any libraries, the sanity_check needs to be adjusted to not expect any libs in such a case.

i.e. Don't look for libs when they are not exected to be built.
Auto-detection if CP2K is loaded as a depencency.
Custom parameter can force behavior:
* `cp2k = True` will raise an exception if CP2K is missing
* `cp2k = False` will ignore CP2K (in case it has been pulled in
   by a different dependency.

This requires GROMACS to be built statically (w/o libs).
@ostueker ostueker marked this pull request as draft June 20, 2022 13:24
@ostueker
Copy link
Contributor Author

I found an issue when building this for AVX512. Will push some changes to this soon.

@ostueker ostueker closed this Jun 20, 2022
@ostueker ostueker reopened this Jun 20, 2022
@boegel boegel added this to the 4.x milestone Jun 21, 2022
Because CP2K is built with MPI, the (Open)MPI libs would need
to be linked to non-MPI Gromacs binaries, which interfers with
the threaded MPI impletation.
@ostueker ostueker marked this pull request as ready for review June 22, 2022 18:47
@ostueker ostueker changed the title GROMACS with CP2K QM/MM support CP2K QM/MM in GROMACS easyblock Jun 27, 2022
@ostueker
Copy link
Contributor Author

Resolved merge-conflict caused by changes in #2749
This PR is ready for review and this easyblock is already in use at ComputeCanada

Copy link
Contributor

@Micket Micket left a comment

Choose a reason for hiding this comment

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

In order to merge any easyblock changes, we need easyconfigs to test with first.

Comment on lines +250 to +255
"$(pkg-config --libs-only-l libcp2k)"
]
if get_software_root('Libint'):
# for some reason libint2 is not discovered by pkg-config:
cp2k_linker_flags.append('-lint2')
self.cfg.update('configopts', '-DCP2K_LINKER_FLAGS="%s"' % " ".join(cp2k_linker_flags))
Copy link
Contributor

Choose a reason for hiding this comment

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

This made me a bit curious. It's not like we are doing something strange to Libint here. It should work if we have pkg-config/pkgconf as a dependency.

[ohmanm@vera2 ~]$ ml Libint/2.6.0-iimpi-2021a-lmax-6-cp2k pkg-config/0.29.2-GCCcore-10.3.0 
[ohmanm@vera2 ~]$ pkg-config --libs-only-l libint2
-lint2

For CP2K/8.2 on the other hand, there doesn't seem to be any pkgconfig file installed, in fact, no libcp2k at all, so i guess this also depends on some updated CP2K easyblock that also builds a library?

Also, since pkg-config is explicitly called here, perhaps the logic should check that pkg-config is added explicitly as a build-dep.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the feedback. Indeed CP2K needs to be build with library = True.

On our system we have pkg-config in our Gentoo layer and therefore we don't specify that as a dependency.

I'll prepare a PR with the needed easyconfigs as best as I can over the coming days.
There will be some guesswork with the dependencies as our easybuild installation is a bit different in certain ways.

@ostueker
Copy link
Contributor Author

ostueker commented Oct 5, 2022

I've opened easybuilders/easybuild-easyconfigs#16362 with the missing easyconfigs to test this patch.

I'll add the check for pkg-config shortly.

@ostueker
Copy link
Contributor Author

ostueker commented Oct 5, 2022

Thanks @Micket,

I've added some checks that CP2K has been compiled with library = True and that pkg-config was used.
It also checks that pkg-config is has been loaded (e.g. as a build-dep).

Easyconfigs to test this enhancement are in: easybuilders/easybuild-easyconfigs#16362

@ostueker ostueker requested a review from Micket October 5, 2022 20:31
@boegel boegel changed the title support CP2K QM/MM in GROMACS easyblock add support for CP2K QM/MM in GROMACS easyblock Oct 12, 2022
self.log.info("Building with CP2K QM/MM.")
self.cfg['build_shared_libs'] = False
self.libext = 'a'
cp2k_version = get_software_version('CP2K')
Copy link
Contributor

Choose a reason for hiding this comment

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

Move this up above the first use of CP2K version

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done in 6b1f77d

if LooseVersion(self.version) < LooseVersion('2022'):
msg = 'CP2K support is only available for GROMACS 2022 and newer.'
raise EasyBuildError(msg)
elif LooseVersion(get_software_version('CP2K')) < LooseVersion('8.1'):
Copy link
Contributor

Choose a reason for hiding this comment

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

This can be a simple "if", then one can put the

cp2k_version = get_software_version('CP2K')

before this line.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done in 6b1f77d

Comment on lines 254 to 261
cp2k_linker_flags = [
# Need MPI linker flags b/c libcp2k.a is compiled with mpifort.
# These are for OpenMPI (mpifort --showme).
"-lmpi_usempif08 -lmpi_usempi_ignore_tkr -lmpi_mpifh",
"-L%s/lib/exts/dbcsr" % cp2k_root,
# get depenencies for libcp2k.a:
"$(pkg-config --libs-only-l libcp2k)"
]
Copy link
Contributor

Choose a reason for hiding this comment

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

This is not good. We must not depend on it being built with OpenMPI. To do it this way it MUST first check that OpenMPI is part of the toolchain.
And the pkgconfig for libcp2k should probably include the MPI libs it depends on which "should" then make all this redundant if the CMake for GROMACS does things correctly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unfortunately CP2K's pkgconfig doesn't contain the MPI libs. That's why I had to hack them in manually.

$ pkg-config --libs-only-l libcp2k
-lcp2k -ldbcsr -lm -lpthread -lstdc++ -lxcf03 -lxc -lxsmm -lxsmmf -lopenblas -lgfortran -lfftw3_omp -lfftw3 -lpthread -lopenblas -lgfortran -lpthread -lscalapack -lopenblas -lgfortran

Should I rework it like this?

cp2k_linker_flags = []
# Need MPI linker flags b/c libcp2k.a is compiled with mpifort.
# These are for OpenMPI (mpifort --showme).
if get_software_root('OpenMPI'):
    cp2k_linker_flags.append("-lmpi_usempif08 -lmpi_usempi_ignore_tkr -lmpi_mpifh")
elif get_software_root('IntelMPI'):
    # append Intel MPI libs for fortran here:
    cp2k_linker_flags.append("...")

cp2k_linker_flags += [
    "-L%s/lib/exts/dbcsr" % cp2k_root,
    # get dependencies for libcp2k.a:
    "$(pkg-config --libs-only-l libcp2k)"
]

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In 2bacbb3 the easyblock is now checking for the cases of Open MPI and Intel MPI to add the fortran-MPI libraries.
Other MPI implementations could be added if needed.

@ostueker ostueker requested review from akesandgren and removed request for Micket October 25, 2022 16:32

if cp2k_root:
if LooseVersion(self.version) < LooseVersion('2022'):
msg = 'CP2K support is only available for GROMACS 2022 and newer.'
Copy link
Contributor

Choose a reason for hiding this comment

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

s/for GROMACS/in GROMACS/

msg = 'CP2K needs to be compiled with "library = True".'
raise EasyBuildError(msg)
if not os.path.exists(os.path.join(cp2k_root, 'lib', 'pkgconfig', 'libcp2k.pc')):
msg = "pkg-config is required as a build-dependency for CP2K"
Copy link
Contributor

Choose a reason for hiding this comment

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

we can either use pkg-config or the newer replacement pkgconf, please change msgs and the test for pkg-config software_root below to accommodate for this.

Copy link
Contributor

Choose a reason for hiding this comment

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

And you should not really test if cp2k has libcp2k.pc like this. Use the pkg-config tool to check instead since it can actually be installed somewhere else than under lib/pkgconfig.

And I'm not sure we should even bother checking for it in the gromacs easyblock, the GROMACS CMake scripts should handle this and bail out if it's missing...

self.cfg.update('configopts', "-DGMX_CP2K=ON")
# Ensure that the GROMACS log files report that CP2K was enabled and which version was used.
self.cfg.update('configopts', "-DGMX_VERSION_STRING_OF_FORK=CP2K-{:}".format(cp2k_version))
self.cfg.update('configopts', "-DCP2K_DIR=%s/lib64" % cp2k_root)
Copy link
Contributor

Choose a reason for hiding this comment

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

lib64.... -> lib and please use os.path.join for this instead of hardcoding "/"

Comment on lines +263 to +265
elif get_software_root('IntelMPI'):
# for Intel MPI (mpiifort -show)
cp2k_linker_flags.append("-lmpifort")
Copy link
Contributor

Choose a reason for hiding this comment

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

Needs a else: with an error msg that tells the user the there is currently no support for other MPI versions, like MPICH or others...

# for Intel MPI (mpiifort -show)
cp2k_linker_flags.append("-lmpifort")
cp2k_linker_flags += [
"-L%s/lib/exts/dbcsr" % cp2k_root,
Copy link
Contributor

Choose a reason for hiding this comment

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

Use os.path.join instead of hardcoding "/"

@@ -310,7 +380,7 @@ def configure_step(self):
mpiexec_path, self.cfg.get('mpiexec_numproc_flag'),
mpi_numprocs)

if LooseVersion(self.version) >= LooseVersion('2019'):
elif LooseVersion(self.version) >= LooseVersion('2019') and self.cfg['build_shared_libs']:
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm fairly sure you can't change this to an elif without breaking things for the non-cp2k builds

@@ -556,6 +626,12 @@ def get_lib_subdir(self):
lib_subdir = os.path.dirname(libpaths[0])[len(self.installdir) + 1:]
self.log.info("Found lib subdirectory that contains %s: %s", libname, lib_subdir)
break
if not self.cfg['build_shared_libs']:
msg = "Found lib subdirectory: %s but it doesn't contain: %s.\n"
Copy link
Contributor

Choose a reason for hiding this comment

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

Remove the ":" to make reference correct

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants