Gmxapi RuntimeError: solvate failed in spc_water_box testing fixture

GROMACS version: 2023
GROMACS modification: No

I’ve tried installing GROMACS both with GMX_PYTHON_PACKAGE=ON, letting the make check run gmxapi tests for me, and with GMX_PYTHON_PACKAGE=OFF, installing gmxapi after the build is complete, and testing after that. I get different tests failing in the two scenarios, but the reason for failure of each test is the same: RuntimeError: solvate failed in spc_water_box testing fixture. Any idea why this might be happening?

gmxapi was installed into the python environment for gmx with pip install --no-cache-dir gmxapi

Is GROMACS built for MPI, thread-MPI, or no-MPI?

Does Subprocesses in MPI contexts need more comprehensive environment handling. (#4736) · Issues · GROMACS / GROMACS · GitLab look like what you are encountering?

If not, please attach a complete copy of the text from your terminal window.

Thanks for replying Eric!

TBH, I’m not sure if I’m encountering the problem in issue #4736 or something different. GROMACS is built for thread-MPI. Here are the first few test failures from testing after building GROMACS, copying python_packaging from the source directory into the build directory, and running pytest test:

================================================= test session starts ==================================================
platform linux -- Python 3.10.10, pytest-7.1.2, pluggy-1.0.0
rootdir: /da/dmp/cb/sloutro1/software/forGROMACS/gromacs/2023.0/AVX-512/Xeon-Gold-6132_noGPU/build/python_packaging/gmxapi/test, configfile: pytest.ini
collected 39 items

test/test_commandline.py ...........                                                                             [ 28%]
test/test_exceptions.py .                                                                                        [ 30%]
test/test_feature_check.py .ss                                                                                   [ 38%]
test/test_fileio.py EEE                                                                                          [ 46%]
test/test_fileio_low_level.py EEE                                                                                [ 53%]
test/test_mdrun.py EEsEsEE                                                                                       [ 71%]
test/test_operation.py ....                                                                                      [ 82%]
test/test_runtime.py ....                                                                                        [ 92%]
test/test_subgraph.py .E.                                                                                        [100%]

======================================================== ERRORS ========================================================
_______________________________________ ERROR at setup of test_tprfile_read_old ________________________________________

gmxcli = PosixPath('/home/sloutro1/software/forGROMACS/gromacs/2023.0/AVX-512/Xeon-Gold-6132_noGPU/install/bin/gmx')
tmp_path_factory = TempPathFactory(_given_basetemp=None, _trace=<pluggy._tracing.TagTracerSub object at 0x2aaac3d4d090>, _basetemp=PosixPath('/tmp/pytest-of-sloutro1/pytest-0'))

    @pytest.fixture(scope="session")
    def spc_water_box_collection(gmxcli, tmp_path_factory):
        """Provide a collection of simulation input items for a simple simulation.

        Prepare the MD input in a freshly created working directory.
        Solvate a 5nm cubic box with spc water. Return a dictionary of the artifacts produced.
        """
        import gmxapi as gmx
        from gmxapi.testsupport import scoped_chdir

        # TODO: (#2896) Fetch MD input from package / library data.
        # Example:
        #     import pkg_resources
        #     # Note: importing pkg_resources means setuptools is required for running this test.
        #     # Get or build TPR file from data bundled via setup(package_data=...)
        #     # Ref https://setuptools.readthedocs.io/en/latest/setuptools.html#including-data-files
        #     from gmx.data import tprfilename

        with scoped_chdir(tmp_path_factory.mktemp("spc_water_box")) as tempdir:

            testdir = os.path.dirname(__file__)
            with open(os.path.join(testdir, "testdata.json"), "r") as fh:
                testdata = json.load(fh)

            # TODO: (#2756) Don't rely on so many automagical behaviors (as described in comments below)

            structurefile = os.path.join(tempdir, "structure.gro")
            # We let `gmx solvate` use the default solvent. Otherwise, we would do
            #     gro_input = testdata['solvent_structure']
            #     with open(structurefile, 'w') as fh:
            #         fh.write('\n'.join(gro_input))
            #         fh.write('\n')

            topfile = os.path.join(tempdir, "topology.top")
            top_input = testdata["solvent_topology"]
            # `gmx solvate` will append a line to the provided file with the molecule count,
            # so we strip the last line from the input topology.
            with open(topfile, "w") as fh:
                fh.write("\n".join(top_input[:-1]))
                fh.write("\n")

            assert os.path.exists(topfile)
            solvate = gmx.commandline_operation(
                gmxcli,
                arguments=["solvate", "-box", "5", "5", "5"],
                # We use the default solvent instead of specifying one.
                # input_files={'-cs': structurefile},
                output_files={
                    "-p": topfile,
                    "-o": structurefile,
                },
                env={"PATH": os.getenv("PATH")},
            )
            assert os.path.exists(topfile)

            if solvate.output.returncode.result() != 0:
                logging.debug(solvate.output.stderr.result())
>               raise RuntimeError("solvate failed in spc_water_box testing fixture.")
E               RuntimeError: solvate failed in spc_water_box testing fixture.

test/conftest.py:126: RuntimeError
___________________________________________ ERROR at setup of test_read_tpr ____________________________________________

gmxcli = PosixPath('/home/sloutro1/software/forGROMACS/gromacs/2023.0/AVX-512/Xeon-Gold-6132_noGPU/install/bin/gmx')
tmp_path_factory = TempPathFactory(_given_basetemp=None, _trace=<pluggy._tracing.TagTracerSub object at 0x2aaac3d4d090>, _basetemp=PosixPath('/tmp/pytest-of-sloutro1/pytest-0'))

    @pytest.fixture(scope="session")
    def spc_water_box_collection(gmxcli, tmp_path_factory):
        """Provide a collection of simulation input items for a simple simulation.

        Prepare the MD input in a freshly created working directory.
        Solvate a 5nm cubic box with spc water. Return a dictionary of the artifacts produced.
        """
        import gmxapi as gmx
        from gmxapi.testsupport import scoped_chdir

        # TODO: (#2896) Fetch MD input from package / library data.
        # Example:
        #     import pkg_resources
        #     # Note: importing pkg_resources means setuptools is required for running this test.
        #     # Get or build TPR file from data bundled via setup(package_data=...)
        #     # Ref https://setuptools.readthedocs.io/en/latest/setuptools.html#including-data-files
        #     from gmx.data import tprfilename

        with scoped_chdir(tmp_path_factory.mktemp("spc_water_box")) as tempdir:

            testdir = os.path.dirname(__file__)
            with open(os.path.join(testdir, "testdata.json"), "r") as fh:
                testdata = json.load(fh)

            # TODO: (#2756) Don't rely on so many automagical behaviors (as described in comments below)

            structurefile = os.path.join(tempdir, "structure.gro")
            # We let `gmx solvate` use the default solvent. Otherwise, we would do
            #     gro_input = testdata['solvent_structure']
            #     with open(structurefile, 'w') as fh:
            #         fh.write('\n'.join(gro_input))
            #         fh.write('\n')

            topfile = os.path.join(tempdir, "topology.top")
            top_input = testdata["solvent_topology"]
            # `gmx solvate` will append a line to the provided file with the molecule count,
            # so we strip the last line from the input topology.
            with open(topfile, "w") as fh:
                fh.write("\n".join(top_input[:-1]))
                fh.write("\n")

            assert os.path.exists(topfile)
            solvate = gmx.commandline_operation(
                gmxcli,
                arguments=["solvate", "-box", "5", "5", "5"],
                # We use the default solvent instead of specifying one.
                # input_files={'-cs': structurefile},
                output_files={
                    "-p": topfile,
                    "-o": structurefile,
                },
                env={"PATH": os.getenv("PATH")},
            )
            assert os.path.exists(topfile)

            if solvate.output.returncode.result() != 0:
                logging.debug(solvate.output.stderr.result())
>               raise RuntimeError("solvate failed in spc_water_box testing fixture.")
E               RuntimeError: solvate failed in spc_water_box testing fixture.

test/conftest.py:126: RuntimeError
________________________________________ ERROR at setup of test_write_tpr_file _________________________________________

gmxcli = PosixPath('/home/sloutro1/software/forGROMACS/gromacs/2023.0/AVX-512/Xeon-Gold-6132_noGPU/install/bin/gmx')
tmp_path_factory = TempPathFactory(_given_basetemp=None, _trace=<pluggy._tracing.TagTracerSub object at 0x2aaac3d4d090>, _basetemp=PosixPath('/tmp/pytest-of-sloutro1/pytest-0'))

    @pytest.fixture(scope="session")
    def spc_water_box_collection(gmxcli, tmp_path_factory):
        """Provide a collection of simulation input items for a simple simulation.

        Prepare the MD input in a freshly created working directory.
        Solvate a 5nm cubic box with spc water. Return a dictionary of the artifacts produced.
        """
        import gmxapi as gmx
        from gmxapi.testsupport import scoped_chdir

        # TODO: (#2896) Fetch MD input from package / library data.
        # Example:
        #     import pkg_resources
        #     # Note: importing pkg_resources means setuptools is required for running this test.
        #     # Get or build TPR file from data bundled via setup(package_data=...)
        #     # Ref https://setuptools.readthedocs.io/en/latest/setuptools.html#including-data-files
        #     from gmx.data import tprfilename

        with scoped_chdir(tmp_path_factory.mktemp("spc_water_box")) as tempdir:

            testdir = os.path.dirname(__file__)
            with open(os.path.join(testdir, "testdata.json"), "r") as fh:
                testdata = json.load(fh)

            # TODO: (#2756) Don't rely on so many automagical behaviors (as described in comments below)

            structurefile = os.path.join(tempdir, "structure.gro")
            # We let `gmx solvate` use the default solvent. Otherwise, we would do
            #     gro_input = testdata['solvent_structure']
            #     with open(structurefile, 'w') as fh:
            #         fh.write('\n'.join(gro_input))
            #         fh.write('\n')

            topfile = os.path.join(tempdir, "topology.top")
            top_input = testdata["solvent_topology"]
            # `gmx solvate` will append a line to the provided file with the molecule count,
            # so we strip the last line from the input topology.
            with open(topfile, "w") as fh:
                fh.write("\n".join(top_input[:-1]))
                fh.write("\n")

            assert os.path.exists(topfile)
            solvate = gmx.commandline_operation(
                gmxcli,
                arguments=["solvate", "-box", "5", "5", "5"],
                # We use the default solvent instead of specifying one.
                # input_files={'-cs': structurefile},
                output_files={
                    "-p": topfile,
                    "-o": structurefile,
                },
                env={"PATH": os.getenv("PATH")},
            )
            assert os.path.exists(topfile)

            if solvate.output.returncode.result() != 0:
                logging.debug(solvate.output.stderr.result())
>               raise RuntimeError("solvate failed in spc_water_box testing fixture.")
E               RuntimeError: solvate failed in spc_water_box testing fixture.

test/conftest.py:126: RuntimeError
_________________________________________ ERROR at setup of test_core_read_tpr _________________________________________

gmxcli = PosixPath('/home/sloutro1/software/forGROMACS/gromacs/2023.0/AVX-512/Xeon-Gold-6132_noGPU/install/bin/gmx')
tmp_path_factory = TempPathFactory(_given_basetemp=None, _trace=<pluggy._tracing.TagTracerSub object at 0x2aaac3d4d090>, _basetemp=PosixPath('/tmp/pytest-of-sloutro1/pytest-0'))

    @pytest.fixture(scope="session")
    def spc_water_box_collection(gmxcli, tmp_path_factory):
        """Provide a collection of simulation input items for a simple simulation.

        Prepare the MD input in a freshly created working directory.
        Solvate a 5nm cubic box with spc water. Return a dictionary of the artifacts produced.
        """
        import gmxapi as gmx
        from gmxapi.testsupport import scoped_chdir

        # TODO: (#2896) Fetch MD input from package / library data.
        # Example:
        #     import pkg_resources
        #     # Note: importing pkg_resources means setuptools is required for running this test.
        #     # Get or build TPR file from data bundled via setup(package_data=...)
        #     # Ref https://setuptools.readthedocs.io/en/latest/setuptools.html#including-data-files
        #     from gmx.data import tprfilename

        with scoped_chdir(tmp_path_factory.mktemp("spc_water_box")) as tempdir:

            testdir = os.path.dirname(__file__)
            with open(os.path.join(testdir, "testdata.json"), "r") as fh:
                testdata = json.load(fh)

            # TODO: (#2756) Don't rely on so many automagical behaviors (as described in comments below)

            structurefile = os.path.join(tempdir, "structure.gro")
            # We let `gmx solvate` use the default solvent. Otherwise, we would do
            #     gro_input = testdata['solvent_structure']
            #     with open(structurefile, 'w') as fh:
            #         fh.write('\n'.join(gro_input))
            #         fh.write('\n')

            topfile = os.path.join(tempdir, "topology.top")
            top_input = testdata["solvent_topology"]
            # `gmx solvate` will append a line to the provided file with the molecule count,
            # so we strip the last line from the input topology.
            with open(topfile, "w") as fh:
                fh.write("\n".join(top_input[:-1]))
                fh.write("\n")

            assert os.path.exists(topfile)
            solvate = gmx.commandline_operation(
                gmxcli,
                arguments=["solvate", "-box", "5", "5", "5"],
                # We use the default solvent instead of specifying one.
                # input_files={'-cs': structurefile},
                output_files={
                    "-p": topfile,
                    "-o": structurefile,
                },
                env={"PATH": os.getenv("PATH")},
            )
            assert os.path.exists(topfile)

            if solvate.output.returncode.result() != 0:
                logging.debug(solvate.output.stderr.result())
>               raise RuntimeError("solvate failed in spc_water_box testing fixture.")
E               RuntimeError: solvate failed in spc_water_box testing fixture.

test/conftest.py:126: RuntimeError
_____________________________________ ERROR at setup of test_core_rewrite_tprfile ______________________________________

gmxcli = PosixPath('/home/sloutro1/software/forGROMACS/gromacs/2023.0/AVX-512/Xeon-Gold-6132_noGPU/install/bin/gmx')
tmp_path_factory = TempPathFactory(_given_basetemp=None, _trace=<pluggy._tracing.TagTracerSub object at 0x2aaac3d4d090>, _basetemp=PosixPath('/tmp/pytest-of-sloutro1/pytest-0'))

    @pytest.fixture(scope="session")
    def spc_water_box_collection(gmxcli, tmp_path_factory):
        """Provide a collection of simulation input items for a simple simulation.

        Prepare the MD input in a freshly created working directory.
        Solvate a 5nm cubic box with spc water. Return a dictionary of the artifacts produced.
        """
        import gmxapi as gmx
        from gmxapi.testsupport import scoped_chdir

        # TODO: (#2896) Fetch MD input from package / library data.
        # Example:
        #     import pkg_resources
        #     # Note: importing pkg_resources means setuptools is required for running this test.
        #     # Get or build TPR file from data bundled via setup(package_data=...)
        #     # Ref https://setuptools.readthedocs.io/en/latest/setuptools.html#including-data-files
        #     from gmx.data import tprfilename

        with scoped_chdir(tmp_path_factory.mktemp("spc_water_box")) as tempdir:

            testdir = os.path.dirname(__file__)
            with open(os.path.join(testdir, "testdata.json"), "r") as fh:
                testdata = json.load(fh)

            # TODO: (#2756) Don't rely on so many automagical behaviors (as described in comments below)

            structurefile = os.path.join(tempdir, "structure.gro")
            # We let `gmx solvate` use the default solvent. Otherwise, we would do
            #     gro_input = testdata['solvent_structure']
            #     with open(structurefile, 'w') as fh:
            #         fh.write('\n'.join(gro_input))
            #         fh.write('\n')

            topfile = os.path.join(tempdir, "topology.top")
            top_input = testdata["solvent_topology"]
            # `gmx solvate` will append a line to the provided file with the molecule count,
            # so we strip the last line from the input topology.
            with open(topfile, "w") as fh:
                fh.write("\n".join(top_input[:-1]))
                fh.write("\n")

            assert os.path.exists(topfile)
            solvate = gmx.commandline_operation(
                gmxcli,
                arguments=["solvate", "-box", "5", "5", "5"],
                # We use the default solvent instead of specifying one.
                # input_files={'-cs': structurefile},
                output_files={
                    "-p": topfile,
                    "-o": structurefile,
                },
                env={"PATH": os.getenv("PATH")},
            )
            assert os.path.exists(topfile)

            if solvate.output.returncode.result() != 0:
                logging.debug(solvate.output.stderr.result())
>               raise RuntimeError("solvate failed in spc_water_box testing fixture.")
E               RuntimeError: solvate failed in spc_water_box testing fixture.

test/conftest.py:126: RuntimeError
_________________________________ ERROR at setup of test_core_read_and_write_tpr_file __________________________________

gmxcli = PosixPath('/home/sloutro1/software/forGROMACS/gromacs/2023.0/AVX-512/Xeon-Gold-6132_noGPU/install/bin/gmx')
tmp_path_factory = TempPathFactory(_given_basetemp=None, _trace=<pluggy._tracing.TagTracerSub object at 0x2aaac3d4d090>, _basetemp=PosixPath('/tmp/pytest-of-sloutro1/pytest-0'))

    @pytest.fixture(scope="session")
    def spc_water_box_collection(gmxcli, tmp_path_factory):
        """Provide a collection of simulation input items for a simple simulation.

        Prepare the MD input in a freshly created working directory.
        Solvate a 5nm cubic box with spc water. Return a dictionary of the artifacts produced.
        """
        import gmxapi as gmx
        from gmxapi.testsupport import scoped_chdir

        # TODO: (#2896) Fetch MD input from package / library data.
        # Example:
        #     import pkg_resources
        #     # Note: importing pkg_resources means setuptools is required for running this test.
        #     # Get or build TPR file from data bundled via setup(package_data=...)
        #     # Ref https://setuptools.readthedocs.io/en/latest/setuptools.html#including-data-files
        #     from gmx.data import tprfilename

        with scoped_chdir(tmp_path_factory.mktemp("spc_water_box")) as tempdir:

            testdir = os.path.dirname(__file__)
            with open(os.path.join(testdir, "testdata.json"), "r") as fh:
                testdata = json.load(fh)

            # TODO: (#2756) Don't rely on so many automagical behaviors (as described in comments below)

            structurefile = os.path.join(tempdir, "structure.gro")
            # We let `gmx solvate` use the default solvent. Otherwise, we would do
            #     gro_input = testdata['solvent_structure']
            #     with open(structurefile, 'w') as fh:
            #         fh.write('\n'.join(gro_input))
            #         fh.write('\n')

            topfile = os.path.join(tempdir, "topology.top")
            top_input = testdata["solvent_topology"]
            # `gmx solvate` will append a line to the provided file with the molecule count,
            # so we strip the last line from the input topology.
            with open(topfile, "w") as fh:
                fh.write("\n".join(top_input[:-1]))
                fh.write("\n")

            assert os.path.exists(topfile)
            solvate = gmx.commandline_operation(
                gmxcli,
                arguments=["solvate", "-box", "5", "5", "5"],
                # We use the default solvent instead of specifying one.
                # input_files={'-cs': structurefile},
                output_files={
                    "-p": topfile,
                    "-o": structurefile,
                },
                env={"PATH": os.getenv("PATH")},
            )
            assert os.path.exists(topfile)

            if solvate.output.returncode.result() != 0:
                logging.debug(solvate.output.stderr.result())
>               raise RuntimeError("solvate failed in spc_water_box testing fixture.")
E               RuntimeError: solvate failed in spc_water_box testing fixture.

test/conftest.py:126: RuntimeError
=============================================== short test summary info ================================================
ERROR test/test_fileio.py::test_tprfile_read_old - RuntimeError: solvate failed in spc_water_box testing fixture.
ERROR test/test_fileio.py::test_read_tpr - RuntimeError: solvate failed in spc_water_box testing fixture.
ERROR test/test_fileio.py::test_write_tpr_file - RuntimeError: solvate failed in spc_water_box testing fixture.
ERROR test/test_fileio_low_level.py::test_core_read_tpr - RuntimeError: solvate failed in spc_water_box testing fixture.
ERROR test/test_fileio_low_level.py::test_core_rewrite_tprfile - RuntimeError: solvate failed in spc_water_box testin...
ERROR test/test_fileio_low_level.py::test_core_read_and_write_tpr_file - RuntimeError: solvate failed in spc_water_bo...
ERROR test/test_mdrun.py::test_run_from_tpr - RuntimeError: solvate failed in spc_water_box testing fixture.
ERROR test/test_mdrun.py::test_mdrun_runtime_args - RuntimeError: solvate failed in spc_water_box testing fixture.
ERROR test/test_mdrun.py::test_extend_simulation_via_checkpoint - RuntimeError: solvate failed in spc_water_box testi...
ERROR test/test_mdrun.py::test_run_from_read_tpr_op - RuntimeError: solvate failed in spc_water_box testing fixture.
ERROR test/test_mdrun.py::test_run_from_modify_input_op - RuntimeError: solvate failed in spc_water_box testing fixture.
ERROR test/test_subgraph.py::test_subgraph_simulation_extension - RuntimeError: solvate failed in spc_water_box testi...
======================================= 23 passed, 4 skipped, 12 errors in 0.95s =======================================

I just realized that the output from failed tests run automatically by make check might be more informative. It specifies that MPI_ABORT was invoked, but I’m not sure if that’s a consequence of how the tests were run, or the result of the actual error.

Consolidate compiler generated dependencies of target _gmxapi
[ 64%] Built target _gmxapi
============================= test session starts ==============================
platform linux -- Python 3.10.10, pytest-7.1.2, pluggy-1.0.0
============================= test session starts ==============================
platform linux -- Python 3.10.10, pytest-7.1.2, pluggy-1.0.0
rootdir: /home/sloutro1/software/forGROMACS/gromacs/2023.0/gromacs-2023/python_packaging/sample_restraint/tests, configfile: pytest.ini
============================= test session starts ==============================
rootdir: /home/sloutro1/software/forGROMACS/gromacs/2023.0/gromacs-2023/python_packaging/sample_restraint/tests, configfile: pytest.ini
collecting ... collecting ... ============================= test session starts ==============================
platform linux -- Python 3.10.10, pytest-7.1.2, pluggy-1.0.0
platform linux -- Python 3.10.10, pytest-7.1.2, pluggy-1.0.0
rootdir: /home/sloutro1/software/forGROMACS/gromacs/2023.0/gromacs-2023/python_packaging/sample_restraint/tests, configfile: pytest.ini
rootdir: /home/sloutro1/software/forGROMACS/gromacs/2023.0/gromacs-2023/python_packaging/sample_restraint/tests, configfile: pytest.ini
collected 4 items
collected 4 items
collected 4 items
collected 4 items

../../../../../../../../../../../../../../home/sloutro1/software/forGROMACS/gromacs/2023.0/gromacs-2023/python_packaging/sample_restraint/tests/test_plugin.py::test_import
../../../../../../../../../../../../../../home/sloutro1/software/forGROMACS/gromacs/2023.0/gromacs-2023/python_packaging/sample_restraint/tests/test_plugin.py::test_import
../../../../../../../../../../../../../../home/sloutro1/software/forGROMACS/gromacs/2023.0/gromacs-2023/python_packaging/sample_restraint/tests/test_plugin.py::test_import
../../../../../../../../../../../../../../home/sloutro1/software/forGROMACS/gromacs/2023.0/gromacs-2023/python_packaging/sample_restraint/tests/test_plugin.py::test_import PASSED [ 25%]PASSED [ 25%]PASSED [ 25%]PASSED [ 25%]
../../../../../../../../../../../../../../home/sloutro1/software/forGROMACS/gromacs/2023.0/gromacs-2023/python_packaging/sample_restraint/tests/test_plugin.py::test_binding_protocol
../../../../../../../../../../../../../../home/sloutro1/software/forGROMACS/gromacs/2023.0/gromacs-2023/python_packaging/sample_restraint/tests/test_plugin.py::test_binding_protocol
../../../../../../../../../../../../../../home/sloutro1/software/forGROMACS/gromacs/2023.0/gromacs-2023/python_packaging/sample_restraint/tests/test_plugin.py::test_binding_protocol
../../../../../../../../../../../../../../home/sloutro1/software/forGROMACS/gromacs/2023.0/gromacs-2023/python_packaging/sample_restraint/tests/test_plugin.py::test_binding_protocol ERROR [ 50%]ERROR [ 50%]ERROR [ 50%]ERROR [ 50%]

==================================== ERRORS ====================================
___________________ ERROR at setup of test_binding_protocol ____________________

gmxcli = PosixPath('/home/sloutro1/software/forGROMACS/gromacs/2023.0/AVX-512/Xeon-Gold-6132_noGPU/build/bin/gmx')
tmp_path_factory = TempPathFactory(_given_basetemp=None, _trace=<pluggy._tracing.TagTracerSub object at 0x2aaab2b2cf10>, _basetemp=PosixPath('/scratch/tmp/24483130.1.default.q/pytest-of-sloutro1/pytest-3'))



==================================== ERRORS ====================================
___________________ ERROR at setup of test_binding_protocol ____________________

gmxcli = PosixPath('/home/sloutro1/software/forGROMACS/gromacs/2023.0/AVX-512/Xeon-Gold-6132_noGPU/build/bin/gmx')
tmp_path_factory = TempPathFactory(_given_basetemp=None, _trace=<pluggy._tracing.TagTracerSub object at 0x2aaab2b2cee0>, _basetemp=PosixPath('/scratch/tmp/24483130.1.default.q/pytest-of-sloutro1/pytest-2'))



==================================== ERRORS ====================================
___________________ ERROR at setup of test_binding_protocol ____________________


gmxcli = PosixPath('/home/sloutro1/software/forGROMACS/gromacs/2023.0/AVX-512/Xeon-Gold-6132_noGPU/build/bin/gmx')
tmp_path_factory = TempPathFactory(_given_basetemp=None, _trace=<pluggy._tracing.TagTracerSub object at 0x2aaab2b2ce80>, _basetemp=PosixPath('/scratch/tmp/24483130.1.default.q/pytest-of-sloutro1/pytest-0'))


==================================== ERRORS ====================================
___________________ ERROR at setup of test_binding_protocol ____________________

gmxcli = PosixPath('/home/sloutro1/software/forGROMACS/gromacs/2023.0/AVX-512/Xeon-Gold-6132_noGPU/build/bin/gmx')
tmp_path_factory = TempPathFactory(_given_basetemp=None, _trace=<pluggy._tracing.TagTracerSub object at 0x2aaab2c16ad0>, _basetemp=PosixPath('/scratch/tmp/24483130.1.default.q/pytest-of-sloutro1/pytest-1'))

    @pytest.fixture(scope="class")
    def spc_water_box(gmxcli, tmp_path_factory):
        """Provide a TPR input file for a simple simulation.

        Prepare the MD input in a freshly created working directory.
        """
        import gmxapi as gmx
        from gmxapi.testsupport import scoped_chdir

        # TODO: (#2896) Fetch MD input from package / library data.
        # Example:
        #     import pkg_resources
        #     # Note: importing pkg_resources means setuptools is required for running this test.
        #     # Get or build TPR file from data bundled via setup(package_data=...)
        #     # Ref https://setuptools.readthedocs.io/en/latest/setuptools.html#including-data-files
        #     from gmx.data import tprfilename

        with scoped_chdir(tmp_path_factory.mktemp("spc_water_box")) as tempdir:

            testdir = os.path.dirname(__file__)
            with open(os.path.join(testdir, "testdata.json"), "r") as fh:
                testdata = json.load(fh)

            # TODO: (#2756) Don't rely on so many automagical behaviors (as described in comments below)

            structurefile = os.path.join(tempdir, "structure.gro")
            # We let `gmx solvate` use the default solvent. Otherwise, we would do
            #     gro_input = testdata['solvent_structure']
            #     with open(structurefile, 'w') as fh:
            #         fh.write('\n'.join(gro_input))
            #         fh.write('\n')

            topfile = os.path.join(tempdir, "topology.top")
            top_input = testdata["solvent_topology"]
            # `gmx solvate` will append a line to the provided file with the molecule count,
            # so we strip the last line from the input topology.
            with open(topfile, "w") as fh:
    @pytest.fixture(scope="class")
                fh.write("\n".join(top_input[:-1]))
                fh.write("\n")

    def spc_water_box(gmxcli, tmp_path_factory):
        """Provide a TPR input file for a simple simulation.
            assert os.path.exists(topfile)
            assert gmx.version.api_is_at_least(0, 3, 1)

        Prepare the MD input in a freshly created working directory.
            solvate = gmx.commandline_operation(
                gmxcli,
        """
        import gmxapi as gmx
                arguments=["solvate", "-box", "5", "5", "5"],
                # We use the default solvent instead of specifying one.
                # input_files={'-cs': structurefile},
                output_files={
        from gmxapi.testsupport import scoped_chdir

        # TODO: (#2896) Fetch MD input from package / library data.
                    "-p": topfile,
        # Example:
        #     import pkg_resources
                    "-o": structurefile,
                },
        #     # Note: importing pkg_resources means setuptools is required for running this test.
        #     # Get or build TPR file from data bundled via setup(package_data=...)
                env={"PATH": os.getenv("PATH")},
            )
        #     # Ref https://setuptools.readthedocs.io/en/latest/setuptools.html#including-data-files
        #     from gmx.data import tprfilename

            assert os.path.exists(topfile)

            if solvate.output.returncode.result() != 0:
        with scoped_chdir(tmp_path_factory.mktemp("spc_water_box")) as tempdir:

                logging.debug(solvate.output.stderr.result())
>               raise RuntimeError("solvate failed in spc_water_box testing fixture.")
            testdir = os.path.dirname(__file__)
            with open(os.path.join(testdir, "testdata.json"), "r") as fh:
                testdata = json.load(fh)

E               RuntimeError: solvate failed in spc_water_box testing fixture.
            # TODO: (#2756) Don't rely on so many automagical behaviors (as described in comments below)


            structurefile = os.path.join(tempdir, "structure.gro")
            # We let `gmx solvate` use the default solvent. Otherwise, we would do
/home/sloutro1/software/forGROMACS/gromacs/2023.0/gromacs-2023/python_packaging/sample_restraint/tests/conftest.py:102: RuntimeError
            #     gro_input = testdata['solvent_structure']
            #     with open(structurefile, 'w') as fh:
            #         fh.write('\n'.join(gro_input))
            #         fh.write('\n')

            topfile = os.path.join(tempdir, "topology.top")
            top_input = testdata["solvent_topology"]
            # `gmx solvate` will append a line to the provided file with the molecule count,
            # so we strip the last line from the input topology.
            with open(topfile, "w") as fh:
                fh.write("\n".join(top_input[:-1]))
                fh.write("\n")

            assert os.path.exists(topfile)
            assert gmx.version.api_is_at_least(0, 3, 1)
            solvate = gmx.commandline_operation(
                gmxcli,
                arguments=["solvate", "-box", "5", "5", "5"],
                # We use the default solvent instead of specifying one.
                # input_files={'-cs': structurefile},
                output_files={
                    "-p": topfile,
                    "-o": structurefile,
                },
                env={"PATH": os.getenv("PATH")},
            )
            assert os.path.exists(topfile)

            if solvate.output.returncode.result() != 0:
                logging.debug(solvate.output.stderr.result())
>               raise RuntimeError("solvate failed in spc_water_box testing fixture.")
=========================== short test summary info ============================
E               RuntimeError: solvate failed in spc_water_box testing fixture.

ERROR ../../../../../../../../../../../../../../home/sloutro1/software/forGROMACS/gromacs/2023.0/gromacs-2023/python_packaging/sample_restraint/tests/test_plugin.py::test_binding_protocol
/home/sloutro1/software/forGROMACS/gromacs/2023.0/gromacs-2023/python_packaging/sample_restraint/tests/conftest.py:102: RuntimeError
!!!!!!!!!!!!!!!!!!!!!!!!!! stopping after 1 failures !!!!!!!!!!!!!!!!!!!!!!!!!!!
========================== 1 passed, 1 error in 0.40s ==========================
=========================== short test summary info ============================
ERROR ../../../../../../../../../../../../../../home/sloutro1/software/forGROMACS/gromacs/2023.0/gromacs-2023/python_packaging/sample_restraint/tests/test_plugin.py::test_binding_protocol
!!!!!!!!!!!!!!!!!!!!!!!!!! stopping after 1 failures !!!!!!!!!!!!!!!!!!!!!!!!!!!
========================== 1 passed, 1 error in 0.40s ==========================
    @pytest.fixture(scope="class")
    def spc_water_box(gmxcli, tmp_path_factory):
        """Provide a TPR input file for a simple simulation.

        Prepare the MD input in a freshly created working directory.
        """
        import gmxapi as gmx
        from gmxapi.testsupport import scoped_chdir

        # TODO: (#2896) Fetch MD input from package / library data.
        # Example:
        #     import pkg_resources
        #     # Note: importing pkg_resources means setuptools is required for running this test.
        #     # Get or build TPR file from data bundled via setup(package_data=...)
        #     # Ref https://setuptools.readthedocs.io/en/latest/setuptools.html#including-data-files
        #     from gmx.data import tprfilename

        with scoped_chdir(tmp_path_factory.mktemp("spc_water_box")) as tempdir:

            testdir = os.path.dirname(__file__)
            with open(os.path.join(testdir, "testdata.json"), "r") as fh:
                testdata = json.load(fh)

            # TODO: (#2756) Don't rely on so many automagical behaviors (as described in comments below)

            structurefile = os.path.join(tempdir, "structure.gro")
            # We let `gmx solvate` use the default solvent. Otherwise, we would do
            #     gro_input = testdata['solvent_structure']
            #     with open(structurefile, 'w') as fh:
            #         fh.write('\n'.join(gro_input))
            #         fh.write('\n')

            topfile = os.path.join(tempdir, "topology.top")
            top_input = testdata["solvent_topology"]
            # `gmx solvate` will append a line to the provided file with the molecule count,
            # so we strip the last line from the input topology.
            with open(topfile, "w") as fh:
                fh.write("\n".join(top_input[:-1]))
                fh.write("\n")

            assert os.path.exists(topfile)
            assert gmx.version.api_is_at_least(0, 3, 1)
            solvate = gmx.commandline_operation(
                gmxcli,
                arguments=["solvate", "-box", "5", "5", "5"],
                # We use the default solvent instead of specifying one.
                # input_files={'-cs': structurefile},
                output_files={
                    "-p": topfile,
                    "-o": structurefile,
                },
                env={"PATH": os.getenv("PATH")},
            )
            assert os.path.exists(topfile)

            if solvate.output.returncode.result() != 0:
                logging.debug(solvate.output.stderr.result())
>               raise RuntimeError("solvate failed in spc_water_box testing fixture.")
E               RuntimeError: solvate failed in spc_water_box testing fixture.

/home/sloutro1/software/forGROMACS/gromacs/2023.0/gromacs-2023/python_packaging/sample_restraint/tests/conftest.py:102: RuntimeError
=========================== short test summary info ============================
ERROR ../../../../../../../../../../../../../../home/sloutro1/software/forGROMACS/gromacs/2023.0/gromacs-2023/python_packaging/sample_restraint/tests/test_plugin.py::test_binding_protocol
!!!!!!!!!!!!!!!!!!!!!!!!!! stopping after 1 failures !!!!!!!!!!!!!!!!!!!!!!!!!!!
========================== 1 passed, 1 error in 0.40s ==========================
    @pytest.fixture(scope="class")
    def spc_water_box(gmxcli, tmp_path_factory):
        """Provide a TPR input file for a simple simulation.

        Prepare the MD input in a freshly created working directory.
        """
        import gmxapi as gmx
        from gmxapi.testsupport import scoped_chdir

        # TODO: (#2896) Fetch MD input from package / library data.
        # Example:
        #     import pkg_resources
        #     # Note: importing pkg_resources means setuptools is required for running this test.
        #     # Get or build TPR file from data bundled via setup(package_data=...)
        #     # Ref https://setuptools.readthedocs.io/en/latest/setuptools.html#including-data-files
        #     from gmx.data import tprfilename

        with scoped_chdir(tmp_path_factory.mktemp("spc_water_box")) as tempdir:

            testdir = os.path.dirname(__file__)
            with open(os.path.join(testdir, "testdata.json"), "r") as fh:
                testdata = json.load(fh)

            # TODO: (#2756) Don't rely on so many automagical behaviors (as described in comments below)

            structurefile = os.path.join(tempdir, "structure.gro")
            # We let `gmx solvate` use the default solvent. Otherwise, we would do
            #     gro_input = testdata['solvent_structure']
            #     with open(structurefile, 'w') as fh:
            #         fh.write('\n'.join(gro_input))
            #         fh.write('\n')

            topfile = os.path.join(tempdir, "topology.top")
            top_input = testdata["solvent_topology"]
            # `gmx solvate` will append a line to the provided file with the molecule count,
            # so we strip the last line from the input topology.
            with open(topfile, "w") as fh:
                fh.write("\n".join(top_input[:-1]))
                fh.write("\n")

            assert os.path.exists(topfile)
            assert gmx.version.api_is_at_least(0, 3, 1)
            solvate = gmx.commandline_operation(
                gmxcli,
                arguments=["solvate", "-box", "5", "5", "5"],
                # We use the default solvent instead of specifying one.
                # input_files={'-cs': structurefile},
                output_files={
                    "-p": topfile,
                    "-o": structurefile,
                },
                env={"PATH": os.getenv("PATH")},
            )
            assert os.path.exists(topfile)

            if solvate.output.returncode.result() != 0:
                logging.debug(solvate.output.stderr.result())
>               raise RuntimeError("solvate failed in spc_water_box testing fixture.")
E               RuntimeError: solvate failed in spc_water_box testing fixture.

/home/sloutro1/software/forGROMACS/gromacs/2023.0/gromacs-2023/python_packaging/sample_restraint/tests/conftest.py:102: RuntimeError
=========================== short test summary info ============================
ERROR ../../../../../../../../../../../../../../home/sloutro1/software/forGROMACS/gromacs/2023.0/gromacs-2023/python_packaging/sample_restraint/tests/test_plugin.py::test_binding_protocol
!!!!!!!!!!!!!!!!!!!!!!!!!! stopping after 1 failures !!!!!!!!!!!!!!!!!!!!!!!!!!!
========================== 1 passed, 1 error in 0.41s ==========================
--------------------------------------------------------------------------
MPI_ABORT was invoked on rank 1 in communicator MPI_COMM_WORLD
with errorcode 1.

NOTE: invoking MPI_ABORT causes Open MPI to kill all MPI processes.
You may or may not see output from other processes, depending on
exactly when Open MPI kills them.
--------------------------------------------------------------------------
[uscacl-1-23:31692] 3 more processes have sent help message help-mpi-api.txt / mpi-abort
[uscacl-1-23:31692] Set MCA parameter "orte_base_help_aggregate" to 0 to see all help / error messages
make[3]: *** [python_packaging/sample_restraint/tests/CMakeFiles/gmxapi_extension_pytest_mpi] Error 1
make[2]: *** [python_packaging/sample_restraint/tests/CMakeFiles/gmxapi_extension_pytest_mpi.dir/all] Error 2
make[1]: *** [CMakeFiles/check.dir/rule] Error 2
make: *** [check] Error 2

make check runs several test suites, including with MPI, when possible. The MPI_ABORT is probably just because of the same problem, but in an MPI context.

Let’s find out why solvate is failing.

If you are running pytest directly, you could add -x -rA -l --log-cli-level debug.

If you like make check, then you can edit python_packaging/gmxapi/test/CMakeLists.txt and change --log-cli-level error to --log-cli-level debug.

I appologize in advance for the verbosity. You could specify just a single failing test and focus on the logged error output from the wrapped solvate command line tool.

Also, can you please note anything else interesting about your computing environment that would help explain why we haven’t seen this problem before?

Thank you Eric! I’ve selected what seem like the relevant error messages from the verbose output – please see below.

Since solvate shouldn’t use any power-features like FFT and CUDA, I’m at a bit of a loss about what might be unusual about my environment. It’s an HPC environment with a module system, and there are multiple GCC modules available. I used gcc 11.2.0. As you can see below, there are some CXXABI and GLIBCXX versions missing from the system libstdc++ against which GROMACS was linked. Does this mean I should compile my own libstdc++ with the same compiler I use for GROMACS? However, all GROMACS tests besides gmxapi pass. Would this not be caught by the rest of the test suite?

DEBUG gmxapi.commandline:commandline.py:283 rank0:install/bin/gmx: /lib64/libstdc++.so.6: version `CXXABI_1.3.9' not found (required by install/bin/gmx)
DEBUG gmxapi.commandline:commandline.py:283 rank0:install/bin/gmx: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by install/bin/gmx)
DEBUG gmxapi.commandline:commandline.py:283 rank0:install/bin/gmx: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.29' not found (required by install/bin/gmx)
DEBUG gmxapi.commandline:commandline.py:283 rank0:install/bin/gmx: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.26' not found (required by install/bin/../lib64/libgromacs.so.8)
DEBUG gmxapi.commandline:commandline.py:283 rank0:install/bin/gmx: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by install/bin/../lib64/libgromacs.so.8)
DEBUG gmxapi.commandline:commandline.py:283 rank0:install/bin/gmx: /lib64/libstdc++.so.6: version `CXXABI_1.3.13' not found (required by install/bin/../lib64/libgromacs.so.8)
DEBUG gmxapi.commandline:commandline.py:283 rank0:install/bin/gmx: /lib64/libstdc++.so.6: version `CXXABI_1.3.9' not found (required by install/bin/../lib64/libgromacs.so.8)
DEBUG gmxapi.commandline:commandline.py:283 install/bin/gmx: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.22' not found (required by install/bin/../lib64/libgromacs.so.8)
DEBUG gmxapi.commandline:commandline.py:283 rank0:install/bin/gmx: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.29' not found (required by install/bin/../lib64/libgromacs.so.8)
DEBUG gmxapi.commandline:commandline.py:283 rank0:install/bin/gmx: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.20' not found (required by install/bin/../lib64/libgromacs.so.8)
DEBUG gmxapi.commandline:commandline.py:283 rank0:install/bin/gmx: /lib64/libstdc++.so.6: version `CXXABI_1.3.8' not found (required by install/bin/../lib64/libgromacs.so.8)
DEBUG gmxapi.commandline:commandline.py:283 rank0:install/bin/gmx: /lib64/libstdc++.so.6: version `CXXABI_1.3.11' not found (required by install/bin/../lib64/libgromacs.so.8)
DEBUG gmxapi.commandline:commandline.py:283 rank0:install/bin/gmx: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.20' not found (required by install/bin/../lib64/../lib64/libmuparser.so.2)
DEBUG gmxapi.commandline:commandline.py:283 rank0:install/bin/gmx: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by install/bin/../lib64/../lib64/libmuparser.so.2)
DEBUG gmxapi.commandline:commandline.py:283 rank0:install/bin/gmx: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.29' not found (required by install/bin/../lib64/../lib64/libmuparser.so.2)
DEBUG gmxapi.commandline:commandline.py:283 rank0:install/bin/gmx: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.26' not found (required by install/bin/../lib64/../lib64/libmuparser.so.2)
DEBUG gmxapi.commandline:commandline.py:283 rank0:
DEBUG root:conftest.py:125 rank0:install/bin/gmx: /lib64/libstdc++.so.6: version `CXXABI_1.3.9' not found (required by install/bin/gmx)
install/bin/gmx: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by install/bin/gmx)
install/bin/gmx: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.29' not found (required by install/bin/gmx)
install/bin/gmx: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.26' not found (required by install/bin/../lib64/libgromacs.so.8)
install/bin/gmx: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by install/bin/../lib64/libgromacs.so.8)
install/bin/gmx: /lib64/libstdc++.so.6: version `CXXABI_1.3.13' not found (required by install/bin/../lib64/libgromacs.so.8)
install/bin/gmx: /lib64/libstdc++.so.6: version `CXXABI_1.3.9' not found (required by install/bin/../lib64/libgromacs.so.8)
install/bin/gmx: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.22' not found (required by install/bin/../lib64/libgromacs.so.8)
install/bin/gmx: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.29' not found (required by install/bin/../lib64/libgromacs.so.8)
install/bin/gmx: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.20' not found (required by install/bin/../lib64/libgromacs.so.8)
install/bin/gmx: /lib64/libstdc++.so.6: version `CXXABI_1.3.8' not found (required by install/bin/../lib64/libgromacs.so.8)
install/bin/gmx: /lib64/libstdc++.so.6: version `CXXABI_1.3.11' not found (required by install/bin/../lib64/libgromacs.so.8)
install/bin/gmx: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.20' not found (required by install/bin/../lib64/../lib64/libmuparser.so.2)
install/bin/gmx: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by install/bin/../lib64/../lib64/libmuparser.so.2)
install/bin/gmx: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.29' not found (required by install/bin/../lib64/../lib64/libmuparser.so.2)
install/bin/gmx: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.26' not found (required by install/bin/../lib64/../lib64/libmuparser.so.2)

ERROR                                                                                                            [100%]

======================================================== ERRORS ========================================================
_________________________________ ERROR at setup of test_subgraph_simulation_extension _________________________________

gmxcli = PosixPath('install/bin/gmx')
tmp_path_factory = TempPathFactory(_given_basetemp=None, _trace=<pluggy._tracing.TagTracerSub object at 0x2aaab2aa2200>, _basetemp=PosixPath('/tmp/pytest-of-sloutro1/pytest-11'))

    @pytest.fixture(scope="session")
    def spc_water_box_collection(gmxcli, tmp_path_factory):
        """Provide a collection of simulation input items for a simple simulation.

        Prepare the MD input in a freshly created working directory.
        Solvate a 5nm cubic box with spc water. Return a dictionary of the artifacts produced.
        """
        import gmxapi as gmx
        from gmxapi.testsupport import scoped_chdir

        # TODO: (#2896) Fetch MD input from package / library data.
        # Example:
        #     import pkg_resources
        #     # Note: importing pkg_resources means setuptools is required for running this test.
        #     # Get or build TPR file from data bundled via setup(package_data=...)
        #     # Ref https://setuptools.readthedocs.io/en/latest/setuptools.html#including-data-files
        #     from gmx.data import tprfilename

        with scoped_chdir(tmp_path_factory.mktemp("spc_water_box")) as tempdir:

            testdir = os.path.dirname(__file__)
            with open(os.path.join(testdir, "testdata.json"), "r") as fh:
                testdata = json.load(fh)

            # TODO: (#2756) Don't rely on so many automagical behaviors (as described in comments below)

            structurefile = os.path.join(tempdir, "structure.gro")
            # We let `gmx solvate` use the default solvent. Otherwise, we would do
            #     gro_input = testdata['solvent_structure']
            #     with open(structurefile, 'w') as fh:
            #         fh.write('\n'.join(gro_input))
            #         fh.write('\n')

            topfile = os.path.join(tempdir, "topology.top")
            top_input = testdata["solvent_topology"]
            # `gmx solvate` will append a line to the provided file with the molecule count,
            # so we strip the last line from the input topology.
            with open(topfile, "w") as fh:
                fh.write("\n".join(top_input[:-1]))
                fh.write("\n")

            assert os.path.exists(topfile)
            solvate = gmx.commandline_operation(
                gmxcli,
                arguments=["solvate", "-box", "5", "5", "5"],
                # We use the default solvent instead of specifying one.
                # input_files={'-cs': structurefile},
                output_files={
                    "-p": topfile,
                    "-o": structurefile,
                },
                env={"PATH": os.getenv("PATH")},
            )
            assert os.path.exists(topfile)

            if solvate.output.returncode.result() != 0:
                logging.debug(solvate.output.stderr.result())
>               raise RuntimeError("solvate failed in spc_water_box testing fixture.")
E               RuntimeError: solvate failed in spc_water_box testing fixture.

fh         = <_io.TextIOWrapper name='/tmp/pytest-of-sloutro1/pytest-11/spc_water_box0/topology.top' mode='w' encoding='UTF-8'>
gmx        = <module 'gmxapi' from 'install/gmx_conda_env/lib/python3.10/site-packages/gmxapi/__init__.py'>
gmxcli     = PosixPath('install/bin/gmx')
scoped_chdir = <function scoped_chdir at 0x2aaac3d23be0>
solvate    = <OperationHandle (<ResourceManager gmxapi.commandline.commandline_operation.<locals>.merged_ops0_i0: width=1, director...../lib64/../lib64/libmuparser.so.2)\n"]>, stdout: <OutputData(ResultDescription(dtype=str, width=1)) "stdout": ['']>>)>
structurefile = '/tmp/pytest-of-sloutro1/pytest-11/spc_water_box0/structure.gro'
tempdir    = PosixPath('/tmp/pytest-of-sloutro1/pytest-11/spc_water_box0')
testdata   = {'datasource': {'solvent_structure': 'src/testutils/simulationdatabase/spc216.gro', 'solvent_topology': 'src/testutils... "oplsaa.ff/forcefield.itp"', '', '; Include water topology', '#include "oplsaa.ff/tip3p.itp"', '', '[ system ]', ...]}
testdir    = 'build/python_packaging/gmxapi/test'
tmp_path_factory = TempPathFactory(_given_basetemp=None, _trace=<pluggy._tracing.TagTracerSub object at 0x2aaab2aa2200>, _basetemp=PosixPath('/tmp/pytest-of-sloutro1/pytest-11'))
top_input  = ['#include "oplsaa.ff/forcefield.itp"', '', '; Include water topology', '#include "oplsaa.ff/tip3p.itp"', '', '[ system ]', ...]
topfile    = '/tmp/pytest-of-sloutro1/pytest-11/spc_water_box0/topology.top'

test/conftest.py:126: RuntimeError
-------------------------------------------------- Captured log setup --------------------------------------------------

Thanks. It appears that the linked dependencies rely on LD_LIBRARY_PATH or other environment variables that are getting stripped out of the environment passed to commandline_operation in the test fixture that runs solvate, like in the issue i linked.

I guess we’d better address it. Can you attach the output of the env command with whatever modules loaded that allow the other tests to pass? You can strip out anything sensitive.

I’m not sure what I’m looking for. I just want to see if anything other than LD_LIBRARY_PATH jumps out at me as “necessary”.

On the other hand, maybe the resolution will be to take a subtractive instead of an additive approach. I tend to think that when you activate a venv, software should just work, so I’m tempted to record the necessary environment variables as they were at configure time, but i think the reality is that many hpc environments still require specific module loads for a venv to work, so filtering the current environment at run time makes more sense. It’s more brittle to implement, but i think i chased down all of the MPI related environment variables on an earlier occasion, so i should be able to write such a filter.

The good news for you is that you probably don’t need to wait for a patch. There are some usage notes about the env key word argument to gmxapi.commandline_operation that are apparently not quite right, and a logic error in the test fixture. But for a thread-mpi gromacs build, you can just let the complete os.environ mapping go through, and scripts should just work.

But I’ll try to have a patch available for the docs and test suite in a day or two.

Here are some env variables that I could imagine being necessary. I ignored variables having to do with the module system and the EasyBuild system, but let me know if those might be of interest as well.

PKG_CONFIG_PATH -> pkgconfig directories for software / libraries loaded as modules
CMAKE_PREFIX_PATH
LIBRARY_PATH -> lib directories for software / libraries loaded as modules
CPATH -> include directories
CMAKE_LIBRARY_PATH

Since I’m in the middle of building several GROMACS versions right now, I would be happy to try your patch(es), if you like.

I see. Yes, I think that is sufficiently messy that gmxapi.commandline_operation should just filter out known problematic variables.

A candidate for gmxapi 0.4.1 is available for review at !3574 (merge request from the 4736-subprocess-env branch)

You could clone that branch and install from source, or you can try the source distribution I just pushed to the pypi test server:

pip install --extra-index https://test.pypi.org/simple/ gmxapi==0.4.1rc1

Unfortunately I got the same errors after updating to this patched version, but I no longer believe my issue is gmxapi-specific. I was able to elicit a related error (see below) while configuring the build with CMake, prior to installing gmxapi. As far as I can tell, under certain circumstances having to do with conda environments the correct libstdc++ (the one associated with the loaded GCC module) is not located. Clearly the one in /lib64 is not compatible. I am investigating the issue further, but I have a question in the meantime: how important is it that the PYTHON_EXECUTABLE identified (or passed to) CMake match the python into which gmxapi had been installed?

The reason I am asking is that I have been building in the following order:

  1. Create conda environment, including all gmxapi dependencies
  2. Activate conda environment – this allows the GROMACS build to detect the correct python, and also (because of how I set up the environment) loads a number of modules necessary for GROMACS: GCC, CUDA, etc.
  3. Build GROMACS (cmake → make → make check → make install) with GMXAPI=ON
  4. Install gmxapi into the conda environment and run gmxapi tests, which have been failing as we have discussed.

Now I am wondering whether it’s necessary to have the conda environment prepared and activated while building GROMACS. Not doing so would not address the root issue causing libstdc++ not to be found, but it may be a workaround.

cmake: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.26' not found (required by cmake)
cmake: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by cmake)
cmake: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.20' not found (required by cmake)
cmake: /lib64/libstdc++.so.6: version `CXXABI_1.3.9' not found (required by cmake)
cmake: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.29' not found (required by cmake)
cmake: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.22' not found (required by cmake)

how important is it that the PYTHON_EXECUTABLE identified (or passed to) CMake match the python into which gmxapi had been installed?

The PYTHON_EXECUTABLE used by the gromacs CMake configuration has no impact outside of the gromacs build tree.

Now I am wondering whether it’s necessary to have the conda environment prepared and activated while building GROMACS.

That is a good question. In practice, I find that conda environments often have separate, incompatible versions of important libraries like zlib and libstdc++. If gromacs is built with different core libraries than the Python interpreter and Python extension modules, it will almost certainly be a problem. I would be interested to hear if anyone has mitigating strategies, but I have never succeeded in linking large leaky research software libraries that mix conda builds with non-conda builds.

As an alternative to conda, the devel branch of spack has a py-gmxapi recipe that should work with a variety of gromacs configurations (version>=2022.1)

It could be problematic to have CMAKE variables in your environment that affect the build system as well as loader-related variables like LD_LIBRARY_PATH. I think the gromacs and gmxapi libraries will set sufficient rpaths in their binaries, but their dependencies might not.

cmake: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.29’ not found (required by cmake)

Is that the cmake that is getting installed in the isolated build environment for pip install gmxapi? You might try telling pip not to use an isolated build environment: --no-build-isolation. You also might try the scikit-build-core build back-end that we are migrating to, which tries to use existing cmake installations where possible instead of installing the “cmake” python package: Replace gmxapi Python package build back-end. (!3531) · Merge requests · GROMACS / GROMACS · GitLab (the mei-scikit-build-core branch from gitlab)

Can I ask what HPC environment this is?

A note of caution (just in case): watch out for cached builds or configuration details as you try different combinations of modules and such. make clean may not be enough. It’s best to use a fresh build directory for gromacs and a completely fresh cmake invocation. For Python, watch out for pip caching incompatible binaries from previous environments. You can use pip cache purge to wipe the cache and/or take precautions along the way (like the --no-cache-dir option to pip install).

After some investigating, I am back to thinking this might be gmxapi related. More specifically, I think it’s related to where gmxapi looks for libstdc++.

I’m doing some of my own LD_LIBRARY_PATH manipulation, both through loading modules (most notably CUDA and OpenMPI for gmxapi, and the support modules those modules load … it gets to be quite a few) and directly in .bash_profile and build scripts. This is what I observed when I encountered the CMake problem – the correct compiler module wasn’t loaded, so an out-of-date libstdc++ was used by CMake.

However, I believe I’ve resolved those issues, and it looks to me like gmx is finding the correct libraries when my conda environment is activated, which also loads the correct modules. Here is the output of ldd in that environment:

$ ldd install/bin/gmx
	linux-vdso.so.1 =>  (0x00002aaaaaacd000)
	libgromacs.so.8 => install/lib64/libgromacs.so.8 (0x00002aaaaaccf000)
	libgomp.so.1 => GCC/11.2.0/lib64/libgomp.so.1 (0x00002aaaaaad3000) <- from loaded GCC module
	libpthread.so.0 => /lib64/libpthread.so.0 (0x00002aaaabf27000)
	libstdc++.so.6 => GCC/11.2.0/lib64/libstdc++.so.6 (0x00002aaaac143000) <- from loaded GCC module
	libm.so.6 => /lib64/libm.so.6 (0x00002aaaac368000)
	libgcc_s.so.1 => GCC/11.2.0/lib64/libgcc_s.so.1 (0x00002aaaaab3c000) <- from loaded GCC module
	libc.so.6 => /lib64/libc.so.6 (0x00002aaaac66a000)
	librt.so.1 => /lib64/librt.so.1 (0x00002aaaaca38000)
	libfftw3f.so.3 => fftw3/3.3.10/lib/libfftw3f.so.3 (0x00002aaaacc40000) <- my own build of FFTW3
	libblas.so.3 => /lib64/libblas.so.3 (0x00002aaaad01a000)
	libmuparser.so.2 => install/lib64/libmuparser.so.2 (0x00002aaaaab58000)
	libdl.so.2 => /lib64/libdl.so.2 (0x00002aaaad273000)
	/lib64/ld-linux-x86-64.so.2 (0x00002aaaaaaab000)
	libgfortran.so.3 => /lib64/libgfortran.so.3 (0x00002aaaad477000)
	libquadmath.so.0 => GCC/11.2.0/lib64/libquadmath.so.0 (0x00002aaaaabd6000) <- from loaded GCC module

$ ldd install/lib64/libgromacs.so.8
	linux-vdso.so.1 =>  (0x00002aaaaaacd000)
	librt.so.1 => /lib64/librt.so.1 (0x00002aaaabf27000)
	libfftw3f.so.3 => fftw3/3.3.10/lib/libfftw3f.so.3 (0x00002aaaac12f000) <- my own build of FFTW3
	libblas.so.3 => /lib64/libblas.so.3 (0x00002aaaac509000)
	libpthread.so.0 => /lib64/libpthread.so.0 (0x00002aaaac762000)
	libm.so.6 => /lib64/libm.so.6 (0x00002aaaac97e000)
	libmuparser.so.2 => install/lib64/libmuparser.so.2 (0x00002aaaaaaf8000)
	libgomp.so.1 => GCC/11.2.0/lib64/libgomp.so.1 (0x00002aaaaab75000) <- from loaded GCC module
	libstdc++.so.6 => /usr/prog/GCCcore/11.2.0/lib64/libstdc++.so.6 (0x00002aaaacc80000) <- from loaded GCC module
	libgcc_s.so.1 => /usr/prog/GCCcore/11.2.0/lib64/libgcc_s.so.1 (0x00002aaaaabba000) <- from loaded GCC module
	libc.so.6 => /lib64/libc.so.6 (0x00002aaaacea5000)
	libgfortran.so.3 => /lib64/libgfortran.so.3 (0x00002aaaad273000)
	/lib64/ld-linux-x86-64.so.2 (0x00002aaaaaaab000)
	libdl.so.2 => /lib64/libdl.so.2 (0x00002aaaad595000)
	libquadmath.so.0 => GCC/11.2.0/lib64/libquadmath.so.0 (0x00002aaaaabd6000) <- from loaded GCC module

$ ldd install/lib64/libgmxapi.so
	linux-vdso.so.1 =>  (0x00002aaaaaacd000)
	libgromacs.so.8 => install/lib64/libgromacs.so.8 (0x00002aaaaaccf000)
	libgomp.so.1 => GCC/11.2.0/lib64/libgomp.so.1 (0x00002aaaaab0c000) <- from loaded GCC module
	libpthread.so.0 => /lib64/libpthread.so.0 (0x00002aaaabf27000)
	libstdc++.so.6 => GCC/11.2.0/lib64/libstdc++.so.6 (0x00002aaaac143000) <- from loaded GCC module
	libm.so.6 => /lib64/libm.so.6 (0x00002aaaac368000)
	libgcc_s.so.1 => GCC/11.2.0/lib64/libgcc_s.so.1 (0x00002aaaaab75000) <- from loaded GCC module
	libc.so.6 => /lib64/libc.so.6 (0x00002aaaac66a000)
	librt.so.1 => /lib64/librt.so.1 (0x00002aaaaca38000)
	libfftw3f.so.3 => fftw3/3.3.10/lib/libfftw3f.so.3 (0x00002aaaacc40000) <- my own build of FFTW3
	libblas.so.3 => /lib64/libblas.so.3 (0x00002aaaad01a000)
	libmuparser.so.2 => install/lib64/libmuparser.so.2 (0x00002aaaaab91000)
	libdl.so.2 => /lib64/libdl.so.2 (0x00002aaaad273000)
	/lib64/ld-linux-x86-64.so.2 (0x00002aaaaaaab000)
	libgfortran.so.3 => /lib64/libgfortran.so.3 (0x00002aaaad477000)
	libquadmath.so.0 => GCC/11.2.0/lib64/libquadmath.so.0 (0x00002aaaaac0f000) <- from loaded GCC module

As you can see, both gmx and gmxapi link against the libstdc++ from the correct GCC module. But when gmxapi tests are running, /lib64/libstdc++ is used instead. Given the complexity of the environment, I’m not sure this necessarily has to do with MPI environment variables. If the test suite output LD_LIBRARY_PATH before and after modification, I would be able to see if the compiler module’s lib64 location is missing from the updated LD_LIBRARY_PATH.

However, I did wonder about CMake itself vs the python cmake … addons(?) installed by pip. This is not what conda installs as cmake – that’s, again, just CMake itself. Clearly pip’s cmake installation includes a different CMake, installed (in my case) into the conda environment. To answer your question, I’m using CMake from a module to build GROMACS, including the cpp part of gmxapi, not the isolated cmake from the conda environment install (I just confirmed this):

Is that the cmake that is getting installed in the isolated build environment for pip install gmxapi?

I did install cmake using pip, to conform to the specified requirements, but now I have no way of knowing whether 1) the python part of gmxapi uses CMake at all, and 2) which CMake it uses, if it does so. Could this be a problem?

On the other hand, as you said earlier, it’s possible all of this is limited to gmxapi tests, and the python module itself will function correctly. I still haven’t gotten to testing that part, but I will try to do that ASAP :)

To answer your question:

Can I ask what HPC environment this is?

I’m not sure which part of the environment is of interest, but it’s my employer’s private HPC environment. Which details would be relevant?

Quick update: after building GROMACS + gmxapi as described above, I succeeded in running “by hand” a very basic version of solvate from python using gmxapi, like this: gmxapi.commandline_operation('install/bin/gmx',arguments=('solvate','-box','5','5','5')),
which returned with code 0 and produced an out.gro output file. I’m not sure if this call would result in loading libstdc++.so, but if so, then this path resolution issue does not seem to exist outside of the test suite.

Oh, I’m sorry if that wasn’t clear. The reason that gmxapi rewrites the environment variables for subprocesses is because it can be inappropriate for environment variables related to an MPI context to propagate to processes forked for gmxapi.commandline_operation(). However, other environment variables should be propagated to child processes.

In other words, my initial thought was that the fix for a bug (which shouldn’t have been relevant to you) had itself caused a bug.

If it was a public HPC system, I could have tried to get a developer account if I didn’t already have one. If it is a private system, it could be useful to know what distribution it is based on, how you build packages (spack?), what environment module system it uses, if any, and what queuing system it uses, if any.

Ah… When you updated to the patched gmxapi, did you also update the test suite? I removed the env kwarg in the conftest.py with my patch, but you wouldn’t have received that change if you just did the pip install of from test.pypi.org. If you still have the old test suite, could you please update to the branch I linked or remove the env kwarg?

The patch did two things:

  • It updated the way env is handled internally to try to address the previous (unrelated) bug without causing new bugs.
  • It removed the heavy-handed env environment override from the test suite, which is what I had suspected was causing your problem.

My expectation is that the updated conftest.py should work (for you, for thread-MPI gromacs) with gmxapi 0.4.0 or with gmxapi 0.4.1rc1, but that the updated conftest.py would break gmxapi 0.4.0 for MPI-gromacs.

If the updated conftest.py does not work for you in the same environment that your by-hand solvate works, then we need to find what else is different in the pytest environment. Please let me know.

I removed the env kwarg in both conftest.py files (in gmxapi/src/gmxapi and in sample_restraint/tests), and all tests now pass. Thank you!

The distribution is CentOS 7, the packages are built (as far as I know – I am strictly a user, trying to compile my own fast version of GROMACS) with EasyBuild, Lmod 8.7.7 is used for environment management, and UGE 8.6.4 is job scheduler. I think the module system is the source of complexity, possibly together with the way conda environments manage the shell environment. The interconnections between modules are particularly complex here, with many modules depending on certain versions of GCC modules – some very outdated ones. Depending on the order in which other modules are loaded, it’s possible to end up with an unexpected version of GCC. This is why I really appreciate the detailed output of CMake (and particularly the ccmake interface), though with dynamic library loading this is not foolproof.

Great news! I will upgrade issue 4736 to a “bug” and try to get !3574 merged for a gmxapi 0.4.1 release as soon as possilble.

Thank you. It is good to have such details recorded.