Enhancing Conda Environments in HPC with an External MPI and Lmod


In our HPC environments, we employ a dynamic approach to software deployment, wherein users can request the compilation and integration of specific software packages into the cluster environment, facilitated by Lmod. While Spack is our primary tool for software installation, there are instances where utilizing Conda to install Python-based scientific software presents a more straightforward or advantageous solution. Consider the case of OpenMC[1], which necessitates the py-openmc package. Utilizing spack spec py-openmc illustrates the complexity and extensive nature of its Python dependencies. I truncated the output for brevity:

spack spec py-openmc
Input spec
--------------------------------
 -   py-openmc

Concretized
--------------------------------
 -   py-openmc@0.13.3%gcc@12.3.0~mpi build_system=python_pip arch=linux-rhel8-zen3
[+]      ^gcc-runtime@12.3.0%gcc@12.3.0 build_system=generic arch=linux-rhel8-zen3
[e]      ^git@2.39.3%gcc@12.3.0+man+nls+perl+subtree~svn~tcltk build_system=autotools arch=linux-rhel8-zen3
 -       ^openmc@0.13.3%gcc@12.3.0~ipo~mpi+openmp build_system=cmake build_type=Release generator=make arch=linux-rhel8-zen3
[e]          ^cmake@3.20.2%gcc@12.3.0~doc+ncurses+ownlibs build_system=generic build_type=Release arch=linux-rhel8-zen3
[e]          ^gmake@4.2.1%gcc@12.3.0~guile build_system=generic patches=ca60bd9,fe5b60d arch=linux-rhel8-zen3
 -           ^hdf5@1.14.3%gcc@12.3.0~cxx~fortran+hl~ipo~java~map~mpi+shared~szip~threadsafe+tools api=default build_system=cmake build_type=Release generator=make arch=linux-rhel8-zen3
[+]              ^zlib-ng@2.1.3%gcc@12.3.0+compat+opt build_system=autotools patches=299b958,ae9077a,b692621 arch=linux-rhel8-zen3
 -       ^py-cython@0.29.36%gcc@12.3.0 build_system=python_pip patches=c4369ad arch=linux-rhel8-zen3
 -       ^py-h5py@3.8.0%gcc@12.3.0~mpi build_system=python_pip arch=linux-rhel8-zen3
 -           ^py-pkgconfig@1.5.5%gcc@12.3.0 build_system=python_pip arch=linux-rhel8-zen3
 -               ^py-poetry-core@1.7.0%gcc@12.3.0 build_system=python_pip arch=linux-rhel8-zen3
[+]          ^py-setuptools@68.0.0%gcc@12.3.0 build_system=generic arch=linux-rhel8-zen3
 -       ^py-ipython@8.14.0%gcc@12.3.0 build_system=python_pip arch=linux-rhel8-zen3
[+]          ^py-backcall@0.2.0%gcc@12.3.0 build_system=python_pip arch=linux-rhel8-zen3
[-]              ^py-flit-core@3.9.0%gcc@12.3.0 build_system=python_pip arch=linux-rhel8-zen3
[+]          ^py-decorator@5.1.1%gcc@12.3.0 build_system=python_pip arch=linux-rhel8-zen3
 -           ^py-jedi@0.18.2%gcc@12.3.0 build_system=python_pip arch=linux-rhel8-zen3
[+]              ^py-parso@0.8.3%gcc@12.3.0 build_system=python_pip arch=linux-rhel8-zen3
[+]          ^py-matplotlib-inline@0.1.6%gcc@12.3.0 build_system=python_pip arch=linux-rhel8-zen3
[+]          ^py-pexpect@4.8.0%gcc@12.3.0 build_system=python_pip arch=linux-rhel8-zen3
[+]              ^py-ptyprocess@0.7.0%gcc@12.3.0 build_system=python_pip arch=linux-rhel8-zen3
[+]          ^py-pickleshare@0.7.5%gcc@12.3.0 build_system=python_pip arch=linux-rhel8-zen3
[+]          ^py-prompt-toolkit@3.0.38%gcc@12.3.0 build_system=python_pip arch=linux-rhel8-zen3
[+]              ^py-wcwidth@0.2.5%gcc@12.3.0 build_system=python_pip arch=linux-rhel8-zen3
 -           ^py-pygments@2.13.0%gcc@12.3.0 build_system=python_pip arch=linux-rhel8-zen3
[+]          ^py-stack-data@0.6.2%gcc@12.3.0 build_system=python_pip arch=linux-rhel8-zen3
[+]              ^py-asttokens@2.2.1%gcc@12.3.0 build_system=python_pip arch=linux-rhel8-zen3
[+]              ^py-executing@1.2.0%gcc@12.3.0 build_system=python_pip arch=linux-rhel8-zen3
[+]              ^py-pure-eval@0.2.2%gcc@12.3.0 build_system=python_pip arch=linux-rhel8-zen3
[-]              ^py-setuptools-scm@7.1.0%gcc@12.3.0+toml build_system=python_pip arch=linux-rhel8-zen3
[+]          ^py-traitlets@5.9.0%gcc@12.3.0 build_system=python_pip arch=linux-rhel8-zen3
[-]              ^py-hatchling@1.17.0%gcc@12.3.0 build_system=python_pip arch=linux-rhel8-zen3
[-]                  ^py-editables@0.3%gcc@12.3.0 build_system=python_pip arch=linux-rhel8-zen3
[-]                  ^py-pathspec@0.11.1%gcc@12.3.0 build_system=python_pip arch=linux-rhel8-zen3
[-]                  ^py-pluggy@1.0.0%gcc@12.3.0 build_system=python_pip arch=linux-rhel8-zen3
[-]                  ^py-trove-classifiers@2023.3.9%gcc@12.3.0 build_system=python_pip arch=linux-rhel8-zen3
[-]                      ^py-calver@2022.6.26%gcc@12.3.0 build_system=python_pip arch=linux-rhel8-zen3
 -       ^py-lxml@4.9.2%gcc@12.3.0~cssselect~html5~htmlsoup build_system=python_pip arch=linux-rhel8-zen3
[+]          ^libxml2@2.10.3%gcc@12.3.0+pic~python+shared build_system=autotools arch=linux-rhel8-zen3
[+]              ^libiconv@1.17%gcc@12.3.0 build_system=autotools libs=shared,static arch=linux-rhel8-zen3
[+]              ^xz@5.4.1%gcc@12.3.0~pic build_system=autotools libs=shared,static arch=linux-rhel8-zen3
 -           ^libxslt@1.1.33%gcc@12.3.0+crypto~python build_system=autotools arch=linux-rhel8-zen3
[+]              ^libgcrypt@1.10.2%gcc@12.3.0 build_system=autotools arch=linux-rhel8-zen3
[+]                  ^libgpg-error@1.47%gcc@12.3.0 build_system=autotools arch=linux-rhel8-zen3
[e]                      ^gawk@4.2.1%gcc@12.3.0~nls build_system=autotools arch=linux-rhel8-zen3
...

When considering using Conda for software installation, two aspects require attention:

  1. It is important to ask whether there exists a compatible build of an MPI implementation for MPI-aware applications within a Conda environment. Specifically, when installing packages like mpi4py in a Conda environment, it is crucial to determine if it should be linked against an external MPI implementation, such as OpenMPI, MPICH, or MVAPICH2, rather than a Conda-provided variant.
  2. There is a need to establish an effective means of communicating to users that unique Conda environments exist, and that new software builds exist within these environments. Moreover, it is essential to provide a user-friendly mechanism that enables them to seamlessly access and utilize these software builds. I leverage Lmod as the medium of communication and mode of accessing the environment.

Addressing these considerations ensures that users and system administrators alike can leverage Conda's capabilities while maintaining compatibility and ease of use with our existing infrastructure. I'll demonstrate this with OpenMC.

Nuances in MPI Implementations


The OpenMC documentation[2] provides a standard procedure for installing OpenMC within a Conda environment, familiar to those experienced with Conda:

  1. Add the conda-forge software channel.
  2. Create and activate the Conda environment in which you want to install OpenMC.
  3. Install the Mamba solver.
  4. Use Mamba to search for the OpenMC variants that are available in the conda-forge channel.
  5. Install OpenMC.

Running mamba search openmc | grep -v nompi reveals the MPI-compatible OpenMC variants. For instance:

openmc                        0.14.0 mpi_mpich_py310h3e4797a_1    conda-forge
openmc                        0.14.0 mpi_mpich_py311h7521181_0    conda-forge
openmc                        0.14.0 mpi_mpich_py311h7521181_1    conda-forge
openmc                        0.14.0 mpi_mpich_py312h9a9b0f1_1    conda-forge
openmc                        0.14.0 mpi_mpich_py38ha556591_0     conda-forge
openmc                        0.14.0 mpi_mpich_py38ha556591_1     conda-forge
openmc                        0.14.0 mpi_mpich_py39h1bb9d22_0     conda-forge
openmc                        0.14.0 mpi_mpich_py39h1bb9d22_1     conda-forge
openmc                        0.14.0 mpi_openmpi_py310h49795cf_0  conda-forge
openmc                        0.14.0 mpi_openmpi_py310h49795cf_1  conda-forge
openmc                        0.14.0 mpi_openmpi_py311h4e5b465_0  conda-forge
openmc                        0.14.0 mpi_openmpi_py311h4e5b465_1  conda-forge
openmc                        0.14.0 mpi_openmpi_py312hbb52303_1  conda-forge
openmc                        0.14.0 mpi_openmpi_py38hb77ba25_0   conda-forge
openmc                        0.14.0 mpi_openmpi_py38hb77ba25_1   conda-forge
openmc                        0.14.0 mpi_openmpi_py39hed284d2_0   conda-forge
openmc                        0.14.0 mpi_openmpi_py39hed284d2_1   conda-forge

As one might expect, installing any of these MPI-aware variants will install the respective MPI software implementation from conda-forge as a dependency. mamba info provides more insight into the dependencies.

$ mamba info openmc=0.14.0=mpi_openmpi_py312hbb52303_1

          mamba version : 1.5.6
openmc 0.14.0 mpi_openmpi_py312hbb52303_1
-----------------------------------------
file name   : openmc-0.14.0-mpi_openmpi_py312hbb52303_1.conda
name        : openmc
version     : 0.14.0
build string: mpi_openmpi_py312hbb52303_1
build number: 1
channel     : https://conda.anaconda.org/conda-forge/linux-64
size        : 3.5 MB
arch        : None
constrains  : ()
license     : MIT
license_family: MIT
md5         : 929fd13be6f06eb339b363707d21c06b
platform    : None
sha256      : a275ad86b50787965141eb5d55660b6305e86917886f75ca2ffd8b3ef6a4926c
subdir      : linux-64
timestamp   : 1701915930537
url         : https://conda.anaconda.org/conda-forge/linux-64/openmc-0.14.0-mpi_openmpi_py312hbb52303_1.conda
dependencies:
    _openmp_mutex >=4.5
    h5py * mpi_openmpi_*
    hdf5 * mpi_openmpi_*
    hdf5 >=1.14.2,<1.14.4.0a0 mpi_openmpi_*
    ipython
    libgcc-ng >=12
    libpng >=1.6.39,<1.7.0a0
    libstdcxx-ng >=12
    lxml
    matplotlib-base
    njoy2016
    numpy >=1.26.2,<2.0a0
    openmpi >=4.1.6,<5.0a0
    openssh
    pandas
    python >=3.12,<3.13.0a0
    python_abi 3.12.* *_cp312
    scipy
    setuptools
    uncertainties.

However, this standard installation approach may overlook specific intricacies associated with a cluster's MPI configuration. In the context of our Zen 3 cluster, these nuances include:

  1. OpenMPI installations with custom default runtime parameters that we set to achieve the best possible general performance on our cluster with the least amount of hassle for the user.
  2. OpenMPI installations built atop a source-compiled UCX version.
  3. OpenMPI installations that were built against PBS Pro, the job scheduler on our Zen 3 cluster.

To align the Conda environment's MPI software with our cluster's installation of OpenMPI 4.1.6, the following steps are crucial:

  1. Ensure correct MPI environment variables by loading the necessary modules, e.g., module load gcc/13.2.0 openmpi/4.1.6-gcc-13.2.0.
  2. Tell Conda to install any build of the Open MPI package version 4.1.6 that matches the build string pattern external_*. This is targets a specific variant of OpenMPI that has been built with some external dependencies or settings in mind: conda install "openmpi=4.1.6=external_*"

To visualize what this does, let's compare the shared library dependencies of the libopenmc.so libraries that were built with and without an external OpenMPI.

External OpenMPI

$ ldd ./lib/python3.12/site-packages/openmc/lib/libopenmc.so
	linux-vdso.so.1 (0x0000155555551000)
	libhdf5.so.310 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../../libhdf5.so.310 (0x0000155554c03000)
	libpthread.so.0 => /lib64/libpthread.so.0 (0x00001555549e3000)
	libdl.so.2 => /lib64/libdl.so.2 (0x00001555547df000)
	libm.so.6 => /lib64/libm.so.6 (0x000015555445d000)
	libhdf5_hl.so.310 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../../libhdf5_hl.so.310 (0x000015555551a000)
	libpng16.so.16 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../../libpng16.so.16 (0x00001555554dd000)
	libmpi.so.40 => /gpfs/fs1/soft/improv/software/spack-built/linux-rhel8-zen3/gcc-13.2.0/openmpi-4.1.6-knzkvb2/lib/libmpi.so.40 (0x0000155554138000)
	libstdc++.so.6 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../../libstdc++.so.6 (0x0000155553f55000)
	libgomp.so.1 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../../libgomp.so.1 (0x00001555554a1000)
	libgcc_s.so.1 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../../libgcc_s.so.1 (0x0000155555484000)
	libc.so.6 => /lib64/libc.so.6 (0x0000155553b90000)
	/lib64/ld-linux-x86-64.so.2 (0x0000155555325000)
	libcrypto.so.3 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../.././libcrypto.so.3 (0x0000155553655000)
	libcurl.so.4 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../.././libcurl.so.4 (0x00001555553c8000)
	libsz.so.2 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../.././libsz.so.2 (0x00001555553bb000)
	libz.so.1 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../.././libz.so.1 (0x000015555539e000)
	librt.so.1 => /lib64/librt.so.1 (0x000015555344d000)
	libhcoll.so.1 => /opt/mellanox/hcoll/lib/libhcoll.so.1 (0x000015555311d000)
	libocoms.so.0 => /opt/mellanox/hcoll/lib/libocoms.so.0 (0x0000155552ed0000)
	librdmacm.so.1 => /lib64/librdmacm.so.1 (0x0000155552cb5000)
	libibverbs.so.1 => /lib64/libibverbs.so.1 (0x0000155552a95000)
	libgpfs.so => /lib64/libgpfs.so (0x000015555287f000)
	libopen-rte.so.40 => /gpfs/fs1/soft/improv/software/spack-built/linux-rhel8-zen3/gcc-13.2.0/openmpi-4.1.6-knzkvb2/lib/libopen-rte.so.40 (0x0000155552759000)
	libpbs.so.0 => /opt/pbs/lib/libpbs.so.0 (0x00001555524d7000)
	libopen-pal.so.40 => /gpfs/fs1/soft/improv/software/spack-built/linux-rhel8-zen3/gcc-13.2.0/openmpi-4.1.6-knzkvb2/lib/libopen-pal.so.40 (0x00001555523d0000)
	libucp.so.0 => /gpfs/fs1/soft/improv/software/spack-built/linux-rhel8-zen3/gcc-13.2.0/ucx-1.15.0-aaef34k/lib/libucp.so.0 (0x00001555522fb000)
	libuct.so.0 => /gpfs/fs1/soft/improv/software/spack-built/linux-rhel8-zen3/gcc-13.2.0/ucx-1.15.0-aaef34k/lib/libuct.so.0 (0x000015555535d000)
	libucm.so.0 => /gpfs/fs1/soft/improv/software/spack-built/linux-rhel8-zen3/gcc-13.2.0/ucx-1.15.0-aaef34k/lib/libucm.so.0 (0x00001555522df000)
	libucs.so.0 => /gpfs/fs1/soft/improv/software/spack-built/linux-rhel8-zen3/gcc-13.2.0/ucx-1.15.0-aaef34k/lib/libucs.so.0 (0x0000155552278000)
	libxpmem.so.0 => /lib64/libxpmem.so.0 (0x0000155552075000)
	libpmix.so.2 => /opt/pmix/4.2.6/lib/libpmix.so.2 (0x0000155551c72000)
	libnl-3.so.200 => /lib64/libnl-3.so.200 (0x0000155551a4f000)
	libnl-route-3.so.200 => /lib64/libnl-route-3.so.200 (0x00001555517bd000)
	libutil.so.1 => /lib64/libutil.so.1 (0x00001555515b9000)
	libhwloc.so.15 => /lib64/libhwloc.so.15 (0x0000155551369000)
	libevent_core-2.1.so.6 => /lib64/libevent_core-2.1.so.6 (0x0000155551130000)
	libevent_pthreads-2.1.so.6 => /lib64/libevent_pthreads-2.1.so.6 (0x0000155550f2d000)
	libnghttp2.so.14 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../../././libnghttp2.so.14 (0x0000155550f01000)
	libssh2.so.1 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../../././libssh2.so.1 (0x0000155550ebc000)
	libssl.so.3 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../../././libssl.so.3 (0x0000155550dd7000)
	libgssapi_krb5.so.2 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../../././libgssapi_krb5.so.2 (0x0000155550d84000)
	libzstd.so.1 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../../././libzstd.so.1 (0x0000155550c70000)
	libcrypto.so.1.1 => /lib64/libcrypto.so.1.1 (0x0000155550785000)
	libkrb5.so.3 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../../libkrb5.so.3 (0x00001555506af000)
	libk5crypto.so.3 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../../libk5crypto.so.3 (0x0000155550697000)
	libcom_err.so.2 => /lib64/libcom_err.so.2 (0x0000155550493000)
	libcom_err.so.3 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../.././././libcom_err.so.3 (0x000015555048d000)
	libkrb5support.so.0 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../.././././libkrb5support.so.0 (0x000015555047f000)
	libkeyutils.so.1 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../.././././libkeyutils.so.1 (0x0000155550478000)
	libresolv.so.2 => /lib64/libresolv.so.2 (0x0000155550260000)

Internal (Conda) OpenMPI

$ ldd ./lib/python3.12/site-packages/openmc/lib/libopenmc.so
	linux-vdso.so.1 (0x0000155555551000)
	libhdf5.so.310 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../../libhdf5.so.310 (0x0000155554c03000)
	libpthread.so.0 => /lib64/libpthread.so.0 (0x00001555549e3000)
	libdl.so.2 => /lib64/libdl.so.2 (0x00001555547df000)
	libm.so.6 => /lib64/libm.so.6 (0x000015555445d000)
	libhdf5_hl.so.310 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../../libhdf5_hl.so.310 (0x000015555551c000)
	libpng16.so.16 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../../libpng16.so.16 (0x00001555554dd000)
	libmpi.so.40 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../../libmpi.so.40 (0x00001555553bb000)
	libstdc++.so.6 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../../libstdc++.so.6 (0x000015555427a000)
	libgomp.so.1 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../../libgomp.so.1 (0x000015555537f000)
	libgcc_s.so.1 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../../libgcc_s.so.1 (0x0000155555364000)
	libc.so.6 => /lib64/libc.so.6 (0x0000155553eb5000)
	/lib64/ld-linux-x86-64.so.2 (0x0000155555325000)
	libcrypto.so.3 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../.././libcrypto.so.3 (0x000015555397a000)
	libcurl.so.4 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../.././libcurl.so.4 (0x00001555538be000)
	libsz.so.2 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../.././libsz.so.2 (0x0000155555355000)
	libz.so.1 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../.././libz.so.1 (0x00001555538a3000)
	librt.so.1 => /lib64/librt.so.1 (0x000015555369b000)
	libopen-rte.so.40 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../.././libopen-rte.so.40 (0x00001555535e1000)
	libopen-pal.so.40 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../.././libopen-pal.so.40 (0x00001555534e1000)
	libnghttp2.so.14 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../../././libnghttp2.so.14 (0x00001555534b5000)
	libssh2.so.1 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../../././libssh2.so.1 (0x000015555346e000)
	libssl.so.3 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../../././libssl.so.3 (0x0000155553389000)
	libgssapi_krb5.so.2 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../../././libgssapi_krb5.so.2 (0x0000155553336000)
	libzstd.so.1 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../../././libzstd.so.1 (0x0000155553222000)
	libutil.so.1 => /lib64/libutil.so.1 (0x000015555301e000)
	libkrb5.so.3 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../.././././libkrb5.so.3 (0x0000155552f46000)
	libk5crypto.so.3 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../.././././libk5crypto.so.3 (0x0000155552f2e000)
	libcom_err.so.3 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../.././././libcom_err.so.3 (0x0000155552f28000)
	libkrb5support.so.0 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../.././././libkrb5support.so.0 (0x0000155552f1a000)
	libkeyutils.so.1 => /gpfs/fs1/home/tlivolsi/.conda/envs/test/./lib/python3.12/site-packages/openmc/lib/../../../.././././libkeyutils.so.1 (0x0000155552f13000)
	libresolv.so.2 => /lib64/libresolv.so.2 (0x0000155552cf9000)

Providing Users With an Easily-Discoverable Environment


I repeated the OpenMC installation steps, with the sole modication being the creation of the OpenMC Conda environment in a location where users possess execution but not write permissions. This allows them to load and optionally extend the OpenMC Conda environment. To achieve this, I execute the following command:

  $ conda create --prefix /gpfs/fs1/soft/improv/software/custom-built/anaconda3/envs/openmc-0.14.0

After OpenMC is installed in this environment, the last thing to do is create an Lmod module to easily load and unload this environment with the necessary dependencies:

help([[
The OpenMC Anaconda Python environment.
You can modify this environment as follows:
 
  - Extend this environment locally
      $ pip install --user [package]
  - Create a new one of your own
      $ conda create -n [environment_name] [package]
https://docs.conda.io/projects/conda/en/latest/user-guide/getting-started.html
]])
 
if (mode() == "load") then
    LmodMessage("The OpenMC 0.14.0 Anaconda Python environment. Run 'module help openmc/0.14.0' for more details.")
end
 
whatis("Name: openmc")
whatis("Version: 0.14.0")
whatis("Category: python conda")
whatis("Keywords: python conda")
whatis("Description: OpenMC Anaconda Python environment")
whatis("URL: https://docs.conda.io/projects/conda/en/latest/user-guide/getting-started.html")
 
-- Dependencies
always_load("gcc/13.2.0")
always_load("openmpi/4.1.6-gcc-13.2.0")
 
local conda_dir = "/gpfs/fs1/soft/improv/software/custom-built/anaconda3/2023.09"
local funcs = "conda __conda_activate __conda_hashr __conda_reactivate"
local home = os.getenv("HOME")
local username = os.getenv("USER")
local env_path = "/gpfs/fs1/soft/improv/software/custom-built/anaconda3/envs/openmc-0.14.0"
 
-- Specify where system and user environments should be created
setenv("CONDA_PKGS_DIRS", pathJoin("/home", username, ".conda/pkgs"))
setenv("ENV_NAME", myModuleFullName())
 
local pyuserbase = pathJoin(home, ".local/", "improv/", myModuleFullName())
setenv("PYTHONUSERBASE", pyuserbase)
unsetenv("PYTHONSTARTUP")
 
-- Initialize conda and activate the openmc-0.14.0 environment
execute{cmd="source " .. conda_dir .. "/etc/profile.d/conda.sh;", modeA={"load"}}
execute{cmd="[[ -z ${ZSH_EVAL_CONTEXT+x} ]] && export -f " .. funcs, modeA={"load"}}
execute{cmd="conda activate " .. env_path, modeA={"load"}}
 
-- Unload environments and clear conda from environment
execute{cmd="for i in $(seq ${CONDA_SHLVL:=0}); do conda deactivate; done; pre=" .. conda_dir .. "; \
        export LD_LIBRARY_PATH=$(echo ${LD_LIBRARY_PATH} | tr ':' '\\n' | grep . | grep -v $pre | tr '\\n' ':' | sed 's/:$//'); \
        export PATH=$(echo ${PATH} | tr ':' '\\n' | grep . | grep -v $pre | tr '\\n' ':' | sed 's/:$//'); \
        unset -f " .. funcs .. "; \
        unset $(env | grep -o \"[^=]*CONDA[^=]*\");", modeA={"unload"}}
 
family("python")

Here it is in action.

References

^ [1]OpenMC
^ [2]OpenMC's Conda installation documentation