1 # The myplugin module must be locatable by Python.
2 # If you configured CMake in the build directory ``/path/to/repo/build`` then,
3 # assuming you are in ``/path/to/repo``, run the tests with something like
4 # PYTHONPATH=./cmake-build-debug/src/pythonmodule mpiexec -n 2 python -m mpi4py -m pytest tests/
6 # This test is not currently run automatically in any way. Build the module, point your PYTHONPATH at it,
7 # and run pytest in the tests directory.
13 import mpi4py.MPI as _MPI
14 except (ImportError, ModuleNotFoundError):
18 from gmxapi.simulation.context import Context
19 from gmxapi.simulation.workflow import WorkElement, from_tpr
20 from gmxapi import version as gmx_version
23 # create console handler
24 ch = logging.StreamHandler()
25 ch.setLevel(logging.DEBUG)
26 # create formatter and add it to the handler
27 formatter = logging.Formatter('%(asctime)s:%(name)s:%(levelname)s: %(message)s')
28 ch.setFormatter(formatter)
29 # add the handlers to the logger
30 logging.getLogger().addHandler(ch)
32 logger = logging.getLogger()
36 # Suppress inspection warning outside of testing context.
37 # noinspection PyUnresolvedReferences
42 @pytest.mark.usefixtures("cleandir")
43 def test_binding_protocol(spc_water_box, mdrun_kwargs):
44 """Test that gmxapi successfully attaches MD plugins."""
48 _size = _MPI.COMM_WORLD.Get_size()
49 _rank = _MPI.COMM_WORLD.Get_rank()
54 tpr_filename = spc_water_box
55 logger.info("Testing plugin potential with input file {}".format(os.path.abspath(tpr_filename)))
57 assert gmx.version.api_is_at_least(0, 2, 1)
58 md = from_tpr([tpr_filename] * _size, append_output=False, **mdrun_kwargs)
60 potential = WorkElement(namespace="myplugin",
61 operation="null_restraint",
62 params={'sites': [1, 4]})
63 potential.name = "null restraint"
64 md.add_dependency(potential)
68 with context as session:
71 # See also #3038, #3145, #4079
72 assert isinstance(context.potentials, list)
73 assert len(context.potentials) > 0
74 for restraint in context.potentials:
75 if isinstance(restraint, myplugin.NullRestraint):
76 assert restraint.count() > 1
79 @pytest.mark.usefixtures("cleandir")
80 def test_ensemble_potential_nompi(spc_water_box, mdrun_kwargs):
81 """Test ensemble potential without an ensemble.
83 tpr_filename = spc_water_box
84 logger.info("Testing plugin potential with input file {}".format(os.path.abspath(tpr_filename)))
86 assert gmx.version.api_is_at_least(0, 0, 5)
87 md = from_tpr([tpr_filename], append_output=False, **mdrun_kwargs)
89 # Create a WorkElement for the potential
90 params = {'sites': [1, 4],
95 'experimental': [1.] * 10,
97 'sample_period': 0.001,
101 potential = WorkElement(namespace="myplugin",
102 operation="ensemble_restraint",
104 # Note that we could flexibly capture accessor methods as workflow elements, too. Maybe we can
105 # hide the extra Python bindings by letting myplugin.HarmonicRestraint automatically convert
106 # to a WorkElement when add_dependency is called on it.
107 potential.name = "ensemble_restraint"
108 md.add_dependency(potential)
110 context = Context(md)
112 with context as session:
116 @pytest.mark.withmpi_only
117 @pytest.mark.usefixtures("cleandir")
118 def test_ensemble_potential_withmpi(spc_water_box, mdrun_kwargs):
119 tpr_filename = spc_water_box
121 logger.info("Testing plugin potential with input file {}".format(os.path.abspath(tpr_filename)))
123 assert gmx_version.api_is_at_least(0, 0, 5)
124 md = from_tpr([tpr_filename, tpr_filename], append_output=False, **mdrun_kwargs)
126 # Create a WorkElement for the potential
127 params = {'sites': [1, 4],
132 'experimental': [0.5] * 10,
134 'sample_period': 0.001,
139 potential = WorkElement(namespace="myplugin",
140 operation="ensemble_restraint",
142 # Note that we could flexibly capture accessor methods as workflow elements, too. Maybe we can
143 # hide the extra Python bindings by letting myplugin.HarmonicRestraint automatically convert
144 # to a WorkElement when add_dependency is called on it.
145 potential.name = "ensemble_restraint"
146 md.add_dependency(potential)
148 context = Context(md)
149 with context as session: