3737
3838from ._platforms import create_backend as _create_backend
3939from ._platforms ._rng import RNGManager as _RNGManager
40+ from ._softcore import SoftcoreForm as _SoftcoreForm
4041
4142
4243def _as_float32 (arr : _np .ndarray ) -> _np .ndarray :
@@ -81,6 +82,8 @@ def __init__(
8182 coulomb_power : float = 0.0 ,
8283 shift_coulomb : str = "1 A" ,
8384 shift_delta : str = "1.5 A" ,
85+ softcore_form : str = "zacharias" ,
86+ taylor_power : int = 1 ,
8487 swap_end_states : bool = False ,
8588 restart : bool = False ,
8689 overwrite : bool = False ,
@@ -207,6 +210,17 @@ def __init__(
207210 The soft-core shift-delta parameter. This is used to soften the
208211 Lennard-Jones interaction.
209212
213+ softcore_form : str
214+ The soft-core potential form to use for alchemical interactions.
215+ This can be either 'zacharias' or 'taylor'. The default is
216+ 'zacharias'.
217+
218+ taylor_power : int
219+ The power to use for the alpha term in the Taylor soft-core LJ
220+ expression, i.e. sig6 = sigma^6 / (alpha^m * sigma^6 + r^6).
221+ Must be between 0 and 4. The default is 1. Only used when
222+ softcore_form is 'taylor'.
223+
210224 swap_end_states: bool
211225 Whether to swap the end states of the alchemical systems.
212226
@@ -495,6 +509,26 @@ def __init__(
495509 except Exception as e :
496510 raise ValueError (f"Could not validate the 'shift_delta': { e } " )
497511
512+ if not isinstance (softcore_form , str ):
513+ raise TypeError ("'softcore_form' must be of type 'str'" )
514+ softcore_form = softcore_form .lower ().replace (" " , "" )
515+ _valid_softcore_forms = {m .name .lower (): m for m in _SoftcoreForm }
516+ if softcore_form not in _valid_softcore_forms :
517+ raise ValueError (
518+ f"'softcore_form' not recognised. Valid forms are: "
519+ f"{ ', ' .join (_valid_softcore_forms )} "
520+ )
521+ self ._softcore_form = _valid_softcore_forms [softcore_form ]
522+
523+ if not isinstance (taylor_power , int ):
524+ try :
525+ taylor_power = int (taylor_power )
526+ except Exception :
527+ raise ValueError ("'taylor_power' must be of type 'int'" )
528+ if not 0 <= taylor_power <= 4 :
529+ raise ValueError ("'taylor_power' must be between 0 and 4" )
530+ self ._taylor_power = taylor_power
531+
498532 if not isinstance (swap_end_states , bool ):
499533 raise ValueError ("'swap_end_states' must be of type 'bool'" )
500534 self ._swap_end_states = swap_end_states
@@ -1323,9 +1357,11 @@ def move(self, context: _openmm.Context) -> list[int]:
13231357 self ._rf_cutoff ,
13241358 self ._rf_kappa ,
13251359 self ._rf_correction ,
1360+ self ._sc_softcore_form ,
13261361 self ._sc_coulomb_power ,
13271362 self ._sc_shift_coulomb ,
13281363 self ._sc_shift_delta ,
1364+ self ._sc_taylor_power ,
13291365 block = (self ._num_threads , 1 , 1 ),
13301366 grid = (self ._atom_blocks , self ._batch_size , 1 ),
13311367 )
@@ -1902,6 +1938,12 @@ def _initialise_gpu_memory(self):
19021938 # Link to the reference state.
19031939 mols = _sr .morph .link_to_reference (self ._system )
19041940
1941+ # Build map of extra options for the dynamics object.
1942+ _map = {}
1943+ if self ._softcore_form == _SoftcoreForm .TAYLOR :
1944+ _map ["use_taylor_softening" ] = True
1945+ _map ["taylor_power" ] = self ._taylor_power
1946+
19051947 # Create a dynamics object.
19061948 d = mols .dynamics (
19071949 cutoff_type = self ._cutoff ,
@@ -1916,6 +1958,7 @@ def _initialise_gpu_memory(self):
19161958 rest2_selection = self ._rest2_selection ,
19171959 swap_end_states = self ._swap_end_states ,
19181960 platform = "cpu" ,
1961+ map = _map ,
19191962 )
19201963
19211964 # Flags for the required force.
@@ -2059,9 +2102,11 @@ def _initialise_gpu_memory(self):
20592102 )
20602103
20612104 # Store soft-core parameters as scalars.
2105+ self ._sc_softcore_form = _np .int32 (int (self ._softcore_form ))
20622106 self ._sc_coulomb_power = _np .float32 (self ._coulomb_power )
20632107 self ._sc_shift_coulomb = _np .float32 (self ._shift_coulomb .value ())
20642108 self ._sc_shift_delta = _np .float32 (self ._shift_delta .value ())
2109+ self ._sc_taylor_power = _np .int32 (self ._taylor_power )
20652110
20662111 # Store immutable per-atom buffers on GPU.
20672112 self ._gpu_sigma = sigmas
0 commit comments