Skip to content

Commit 64e9b61

Browse files
authored
Drop support for ESPResSo 4.2 (#155)
* Drop support for ESPResSo 4.2 * Update changelog and readme
1 parent f20b221 commit 64e9b61

16 files changed

Lines changed: 128 additions & 216 deletions

.github/actions/dependencies/action.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ runs:
1111
using: "composite"
1212
steps:
1313
- run: |
14+
test "${RUNNER_ARCH}" = "X64" && module use /cvmfs/dev.eessi.io/espresso/versions/${EESSI_VERSION}/software/linux/x86_64/amd/zen2/modules/all
1415
module load ${{ inputs.modules }}
1516
module save pymbe
1617
python3 -m venv --system-site-packages venv

.github/workflows/samples.yml

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,28 +17,29 @@ jobs:
1717
OMPI_MCA_mtl_ofi_provider_exclude: psm3
1818
strategy:
1919
matrix:
20-
espresso:
21-
- version: "4.2.2"
22-
eessi_modules: ESPResSo/4.2.2-foss-2023b
23-
eessi_stack_version: "2023.06"
24-
upload_artifact: true
25-
- version: "5.0.1"
20+
software:
21+
- label: "ESPResSo 5.0.1"
2622
eessi_modules: ESPResSo/5.0.1-foss-2025a
2723
eessi_stack_version: "2025.06"
24+
upload_artifact: true
25+
- label: "ESPResSo 5.1-dev"
26+
eessi_modules: ESPResSo/cd7547c43b2dae8e96487bf149d049d701dddd43-foss-2025a
27+
eessi_stack_version: "2025.06"
2828
upload_artifact: false
29-
name: ubuntu - ESPResSo ${{ matrix.espresso.version }}
29+
name: ubuntu - ${{ matrix.software.label }}
3030
steps:
31+
- name: Checkout repository
32+
uses: actions/checkout@main
3133
- name: Setup EESSI
3234
uses: eessi/github-action-eessi@v3
3335
with:
34-
eessi_stack_version: ${{ matrix.espresso.eessi_stack_version }}
35-
- name: Checkout repository
36-
uses: actions/checkout@main
36+
eessi_stack_version: ${{ matrix.software.eessi_stack_version }}
37+
use_eessi_module: false
3738
- name: Install dependencies
3839
uses: ./.github/actions/dependencies
3940
with:
4041
modules: |-
41-
${{ matrix.espresso.eessi_modules }}
42+
${{ matrix.software.eessi_modules }}
4243
- name: Run testsuite
4344
run: |
4445
export NUM_PROC=$(nproc)

.github/workflows/testsuite.yml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ jobs:
1717
strategy:
1818
matrix:
1919
software:
20-
- label: "ESPResSo 4.2.2, LAMMPS 2024"
21-
eessi_modules: ESPResSo/4.2.2-foss-2023b LAMMPS/29Aug2024-foss-2023b-kokkos
22-
eessi_stack_version: "2023.06"
23-
upload_artifact: true
2420
- label: "ESPResSo 5.0.1"
2521
eessi_modules: ESPResSo/5.0.1-foss-2025a
2622
eessi_stack_version: "2025.06"
23+
upload_artifact: true
24+
- label: "ESPResSo 5.1-dev"
25+
eessi_modules: ESPResSo/cd7547c43b2dae8e96487bf149d049d701dddd43-foss-2025a
26+
eessi_stack_version: "2025.06"
2727
upload_artifact: false
2828
name: ubuntu - ${{ matrix.software.label }}
2929
steps:
@@ -37,6 +37,7 @@ jobs:
3737
uses: eessi/github-action-eessi@v3
3838
with:
3939
eessi_stack_version: ${{ matrix.software.eessi_stack_version }}
40+
use_eessi_module: false
4041
- name: Install dependencies
4142
uses: ./.github/actions/dependencies
4243
with:

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4545
- Methods that interact directly with the pyMBE dataframe. These methods have been replaced by private methods that instead interact with the new canonical pyMBE database in (`pyMBE/storage/manager`). This includes the methods: `add_bond_in_df`, `add_value_to_df`, `assign_molecule_id`, `check_if_df_cell_has_a_value`, `check_if_name_is_defined_in_df`, `check_if_multiple_pmb_types_for_name`, `clean_df_row`, `clean_ids_in_df_row`, `copy_df_entry`, `create_variable_with_units`, `convert_columns_to_original_format`, `convert_str_to_bond_object`, `delete_entries_in_df`, `find_bond_key`, `setup_df`, `define_particle_entry_in_df`, custom `NumpyEncoder`. (#145,#147)
4646
- Method `add_bonds_to_espresso` has been removed from the API. pyMBE now adds bonds internally to ESPResSo when molecule instances are created into ESPResSo. (#147)
4747
- Tutorial `lattice_builder.ipynb` has been removed because its content is redundant with sample script `build_hydrogel.py`. (#147)
48+
- Legacy ESPResSo 4.2-specific helper functions `do_reaction` and `get_number_of_particles` were removed from the API. ESPResSo 4.2 is no longer officially supported. (#155)
4849

4950

5051
## [1.0.0] - 2025-10-08

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ git clone git@github.com:pyMBE-dev/pyMBE.git
6868

6969
Please, be aware that pyMBE is intended to be a supporting tool to setup simulations with ESPResSo.
7070
Thus, for most of its functionalities ESPResSo must also be available.
71-
pyMBE supports ESPResSo 4.2 and ESPResSo 4.3-dev.
72-
Following the NEP29 guidelines, we recommend using Python3.10+.
71+
pyMBE supports ESPResSo 5.0 and ESPResSo 5.1-dev.
72+
Following the NEP29 guidelines, we recommend using Python3.11+.
7373
Both NumPy 1 and NumPy 2 are supported.
7474

7575
The pyMBE module needs a Python virtual environment to avoid compatibility issues with its dependencies.
@@ -99,7 +99,7 @@ python3 -m pip install -r requirements.txt "numpy>=2.1" "pandas>=2.0"
9999
We highlight that the path `/home/user/espresso/build` is just an example of a possible path to the ESPResSo build folder.
100100
The user should change this path to match the local absolute path where ESPResSo was built.
101101
Also, ESPResSo must be built with the same NumPy version as the one installed in the environment to avoid API version mismatch.
102-
For more details on how to install ESPResSo, please consult the [ESPResSo installation guide](https://espressomd.github.io/doc4.2.2/installation.html).
102+
For more details on how to install ESPResSo, please consult the [ESPResSo installation guide](https://espressomd.github.io/doc5.0.1/installation.html).
103103

104104
The pyMBE virtual environment can be deactivated at any moment as follows:
105105

@@ -111,7 +111,7 @@ Cluster users who rely on module files to load dependencies should opt for the
111111
following alternative:
112112

113113
```sh
114-
module load ESPResSo/4.2.2-foss-2023a # adapt release if needed
114+
module load ESPResSo/5.0.1-foss-2025a # adapt release if needed
115115
python3 -m venv --system-site-packages pymbe
116116
source pymbe/bin/activate
117117
python3 maintainer/configure_venv.py
@@ -128,7 +128,7 @@ Now you can use pyMBE and ESPResSo by activating the virtual environment:
128128
```sh
129129
$ source pymbe/bin/activate
130130
(pymbe) $ python3 -c "import espressomd.version; print(espressomd.version.friendly())"
131-
4.2
131+
5.0.1
132132
(pymbe) $ python3 -c "import pyMBE; print(pyMBE.__file__)"
133133
/home/user/Documents/pyMBE/pyMBE/__init__.py
134134
$ deactivate

pyMBE/simulation_builder/espresso_engine.py

Lines changed: 24 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ def __init__(self,box_l,db,espresso_system,units,kT,Kw,seed):
3737
self.kT=kT
3838
self.Kw=Kw
3939
self.seed=seed
40-
pass
4140

4241
def _add_angle(self,particle_id1,particle_id2,particle_id3, angle_inst):
4342
"""
@@ -365,36 +364,6 @@ def change_volume_and_rescale_particles(self, d_new, dir="xyz"):
365364

366365
self.espresso_system.change_volume_and_rescale_particles(d_new=d_new,
367366
dir=dir)
368-
369-
370-
def do_reaction(self,algorithm, steps):
371-
"""
372-
Executes reaction steps using an ESPResSo reaction algorithm with
373-
version-compatible calling semantics.
374-
375-
This function wraps the `reaction` method of an ESPResSo reaction
376-
algorithm to account for differences in the method signature between
377-
ESPResSo versions.
378-
379-
Args:
380-
algorithm ('espressomd.reaction_methods'):
381-
ESPResSo reaction algorithm object (e.g. constant pH,
382-
reaction ensemble, or similar).
383-
steps ('int'):
384-
Number of reaction steps to perform.
385-
386-
Notes:
387-
- In ESPResSo 4.2, the `reaction` method expects the number of steps
388-
to be passed as the keyword argument `reaction_steps`.
389-
- In newer ESPResSo versions, the keyword argument is `steps`.
390-
- This helper function provides a stable interface across ESPResSo
391-
versions by dispatching to the appropriate keyword internally.
392-
"""
393-
import espressomd.version
394-
if espressomd.version.friendly() == '4.2':
395-
algorithm.reaction(reaction_steps=steps)
396-
else:
397-
algorithm.reaction(steps=steps)
398367

399368
def enable_motion_of_rigid_object(self, instance_id, pmb_type):
400369
"""
@@ -442,35 +411,6 @@ def enable_motion_of_rigid_object(self, instance_id, pmb_type):
442411
pid = self.espresso_system.part.by_id(particle_id)
443412
pid.vs_auto_relate_to(rigid_object_center.id)
444413

445-
def get_number_of_particles(self, ptype):
446-
"""
447-
Returns the number of particles of a given ESPResSo particle type.
448-
449-
Args:
450-
ptype ('int'):
451-
ESPResSo particle type identifier.
452-
453-
Returns:
454-
('int'):
455-
Number of particles in `espresso_system` with particle type `ptype`.
456-
457-
Notes:
458-
- In ESPResSo 4.2, `number_of_particles` expects the particle type
459-
as a positional argument.
460-
- In later ESPResSo versions, the particle type must be passed as a
461-
keyword argument (`type=ptype`).
462-
- This helper function hides these API differences and provides
463-
a uniform interface across ESPResSo versions.
464-
"""
465-
import espressomd.version
466-
if espressomd.version.friendly() == "4.2":
467-
args = (ptype,)
468-
kwargs = {}
469-
else:
470-
args = ()
471-
kwargs = {"type": ptype}
472-
return self.espresso_system.number_of_particles(*args, **kwargs)
473-
474414
def relax_espresso_system(self, seed, gamma=1e-3, Nsteps_steepest_descent=5000, max_displacement=0.01, Nsteps_iter_relax=500):
475415
"""
476416
Relaxes the energy of the given ESPResSo system by performing the following steps:
@@ -610,19 +550,13 @@ def setup_electrostatic_interactions(self,units, kT, c_salt=None, solvent_permit
610550

611551
if tune_p3m:
612552
self.espresso_system.time_step=0.01
613-
if espressomd.version.friendly() == "4.2":
614-
self.espresso_system.actors.add(coulomb)
615-
else:
616-
self.espresso_system.electrostatics.solver = coulomb
553+
self.espresso_system.electrostatics.solver = coulomb
617554

618555

619556
# save the optimal parameters and add them by hand
620557

621558
p3m_params = coulomb.get_params()
622-
if espressomd.version.friendly() == "4.2":
623-
self.espresso_system.actors.remove(coulomb)
624-
else:
625-
self.espresso_system.electrostatics.solver = None
559+
self.espresso_system.electrostatics.solver = None
626560
coulomb = espressomd.electrostatics.P3M(prefactor = COULOMB_PREFACTOR.m_as("reduced_length * reduced_energy"),
627561
accuracy = accuracy,
628562
mesh = p3m_params['mesh'],
@@ -641,10 +575,7 @@ def setup_electrostatic_interactions(self,units, kT, c_salt=None, solvent_permit
641575
coulomb = espressomd.electrostatics.DH(prefactor = COULOMB_PREFACTOR.m_as("reduced_length * reduced_energy"),
642576
kappa = (1./KAPPA).to('1/ reduced_length').magnitude,
643577
r_cut = r_cut)
644-
if espressomd.version.friendly() == "4.2":
645-
self.espresso_system.actors.add(coulomb)
646-
else:
647-
self.espresso_system.electrostatics.solver = coulomb
578+
self.espresso_system.electrostatics.solver = coulomb
648579
logging.debug("*** Electrostatics successfully added to the system ***")
649580

650581
def setup_cpH (self, counter_ion, constant_pH, exclusion_range=None, use_exclusion_radius_per_type = False):
@@ -676,11 +607,15 @@ def setup_cpH (self, counter_ion, constant_pH, exclusion_range=None, use_exclusi
676607
exclusion_radius_per_type = self.db.get_radius_map()
677608
else:
678609
exclusion_radius_per_type = {}
610+
kwargs = {}
611+
if espressomd.version.version() >= (5, 1, 0):
612+
kwargs["system"] = self.espresso_system
679613
RE = reaction_methods.ConstantpHEnsemble(kT=self.kT.to('reduced_energy').magnitude,
680614
exclusion_range=exclusion_range,
681615
seed=self.seed,
682616
constant_pH=constant_pH,
683-
exclusion_radius_per_type = exclusion_radius_per_type)
617+
exclusion_radius_per_type = exclusion_radius_per_type,
618+
**kwargs)
684619
conterion_tpl = self.db.get_template(name=counter_ion,
685620
pmb_type="particle")
686621
conterion_state = self.db.get_template(name=conterion_tpl.initial_state,
@@ -749,10 +684,14 @@ def setup_gcmc(self, c_salt_res, salt_cation_name, salt_anion_name, activity_coe
749684
exclusion_radius_per_type = self.db.get_radius_map()
750685
else:
751686
exclusion_radius_per_type = {}
687+
kwargs = {}
688+
if espressomd.version.version() >= (5, 1, 0):
689+
kwargs["system"] = self.espresso_system
752690
RE = reaction_methods.ReactionEnsemble(kT=self.kT.to('reduced_energy').magnitude,
753691
exclusion_range=exclusion_range,
754692
seed=self.seed,
755-
exclusion_radius_per_type = exclusion_radius_per_type)
693+
exclusion_radius_per_type = exclusion_radius_per_type,
694+
**kwargs)
756695
# Determine the concentrations of the various species in the reservoir and the equilibrium constants
757696
determined_activity_coefficient = activity_coefficient(c_salt_res)
758697
K_salt = (c_salt_res.to('1/(N_A * reduced_length**3)')**2) * determined_activity_coefficient
@@ -846,10 +785,14 @@ def setup_grxmc_reactions(self, pH_res, c_salt_res, proton_name, hydroxide_name,
846785
exclusion_radius_per_type = self.db.get_radius_map()
847786
else:
848787
exclusion_radius_per_type = {}
788+
kwargs = {}
789+
if espressomd.version.version() >= (5, 1, 0):
790+
kwargs["system"] = self.espresso_system
849791
RE = reaction_methods.ReactionEnsemble(kT=self.kT.to('reduced_energy').magnitude,
850792
exclusion_range=exclusion_range,
851793
seed=self.seed,
852-
exclusion_radius_per_type = exclusion_radius_per_type)
794+
exclusion_radius_per_type = exclusion_radius_per_type,
795+
**kwargs)
853796
# Determine the concentrations of the various species in the reservoir and the equilibrium constants
854797
cH_res, cOH_res, cNa_res, cCl_res = self.determine_reservoir_concentrations(pH_res, c_salt_res, activity_coefficient)
855798
ionic_strength_res = 0.5*(cNa_res+cCl_res+cOH_res+cH_res)
@@ -1142,10 +1085,14 @@ def setup_grxmc_unified(self, pH_res, c_salt_res, cation_name, anion_name, activ
11421085
exclusion_radius_per_type = self.db.get_radius_map()
11431086
else:
11441087
exclusion_radius_per_type = {}
1088+
kwargs = {}
1089+
if espressomd.version.version() >= (5, 1, 0):
1090+
kwargs["system"] = self.espresso_system
11451091
RE = reaction_methods.ReactionEnsemble(kT=self.kT.to('reduced_energy').magnitude,
11461092
exclusion_range=exclusion_range,
11471093
seed=self.seed,
1148-
exclusion_radius_per_type = exclusion_radius_per_type)
1094+
exclusion_radius_per_type = exclusion_radius_per_type,
1095+
**kwargs)
11491096
# Determine the concentrations of the various species in the reservoir and the equilibrium constants
11501097
cH_res, cOH_res, cNa_res, cCl_res = self.determine_reservoir_concentrations(pH_res, c_salt_res, activity_coefficient)
11511098
ionic_strength_res = 0.5*(cNa_res+cCl_res+cOH_res+cH_res)
@@ -1319,7 +1266,7 @@ def setup_lj_interactions(self, shift_potential=True, combining_rule='Lorentz-Be
13191266
13201267
Notes:
13211268
- Currently, the only 'combining_rule' supported is Lorentz-Berthelot.
1322-
- Check the documentation of ESPResSo for more info about the potential https://espressomd.github.io/doc4.2.0/inter_non-bonded.html
1269+
- Check the documentation of ESPResSo for more info about the potential https://espressomd.github.io/doc5.0.1/inter_non-bonded.html
13231270
13241271
"""
13251272
from itertools import combinations_with_replacement

samples/Beyer2024/globular_protein.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from pathlib import Path
2020
import tqdm
2121
import espressomd
22+
import espressomd.version
2223
import argparse
2324
import numpy as np
2425
import pandas as pd
@@ -268,8 +269,8 @@
268269
print(pmb.get_reactions_df())
269270

270271
type_map = pmb.get_type_map()
271-
types = list (type_map.values())
272-
espresso_system.setup_type_map( type_list = types)
272+
if espressomd.version.version() < (5, 1, 0):
273+
espresso_system.setup_type_map(type_list = type_map.values())
273274

274275
# Setup the non-interacting type for speeding up the sampling of the reactions
275276
non_interacting_type = max(type_map.values())+1
@@ -320,7 +321,7 @@
320321

321322
for step in tqdm.trange(N_samples, disable=not verbose):
322323
espresso_system.integrator.run (steps = integ_steps)
323-
pmb.simulation_engine.do_reaction(cpH, steps=total_ionisable_groups)
324+
cpH.reaction(steps=total_ionisable_groups)
324325
protein_net_charge = pmb.calculate_net_charge(
325326
object_name=protein_name,
326327
pmb_type="protein",

samples/Beyer2024/peptide.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
# Load espresso, pyMBE and other necessary libraries
2020
from pathlib import Path
2121
import espressomd
22+
import espressomd.version
2223
import pandas as pd
2324
import argparse
2425
import tqdm
@@ -184,11 +185,11 @@
184185
print(pmb.get_reactions_df())
185186

186187
# Setup espresso to track the ionization of the acid/basic groups in peptide
187-
type_map =pmb.get_type_map()
188-
espresso_system.setup_type_map(type_list = list(type_map.values()))
188+
if espressomd.version.version() < (5, 1, 0):
189+
espresso_system.setup_type_map(type_list = pmb.get_type_map().values())
189190

190191
# Setup the non-interacting type for speeding up the sampling of the reactions
191-
non_interacting_type = max(type_map.values())+1
192+
non_interacting_type = max(pmb.get_type_map().values())+1
192193
cpH.set_non_interacting_type (type=non_interacting_type)
193194
if verbose:
194195
print(f"The non-interacting type is set to {non_interacting_type}")
@@ -224,7 +225,7 @@
224225
# Run LD
225226
espresso_system.integrator.run(steps=MD_steps_per_sample)
226227
# Run MC
227-
pmb.simulation_engine.do_reaction(cpH, steps=len(sequence))
228+
cpH.reaction(steps=len(sequence))
228229
# Sample observables
229230
charge_dict=pmb.calculate_net_charge(
230231
object_name=sequence,

0 commit comments

Comments
 (0)