@@ -151,7 +151,7 @@ def ring_break_morph():
151151 """
152152 Build a lambda schedule for ring-breaking perturbations.
153153
154- Three stages: potential_swap → restraints_off → morph.
154+ Four stages: potential_swap → restraints_off → ring_open → morph.
155155
156156 Returns
157157 -------
@@ -162,8 +162,36 @@ def ring_break_morph():
162162 from sire .cas import LambdaSchedule as _LambdaSchedule
163163
164164 s = _LambdaSchedule .standard_morph ()
165+ s .set_stage_weight ("morph" , 2 )
166+
167+ # ring_open: Morse is already off; ring-break nonbonded interaction ramps
168+ # on (alpha: 1→0, kappa: 0→1) while non-bonded terms stay at initial and
169+ # bonded terms remain at final. The softcore interaction gently pushes the
170+ # atoms into the open-chain geometry before the full nonbonded morph begins,
171+ # improving HREX overlap at the ring-break boundary.
172+ s .prepend_stage ("ring_open" , s .initial (), weight = 1 )
173+ s .set_equation (stage = "ring_open" , lever = "morse_hard" , equation = 0 )
174+ s .set_equation (stage = "ring_open" , lever = "morse_soft" , equation = 0 )
175+ s .set_equation (stage = "ring_open" , lever = "bond_k" , equation = s .final ())
176+ s .set_equation (stage = "ring_open" , lever = "bond_length" , equation = s .final ())
177+ s .set_equation (stage = "ring_open" , lever = "angle_k" , equation = s .final ())
178+ s .set_equation (stage = "ring_open" , lever = "angle_size" , equation = s .final ())
179+ s .set_equation (stage = "ring_open" , lever = "torsion_k" , equation = s .final ())
180+ s .set_equation (stage = "ring_open" , lever = "torsion_phase" , equation = s .final ())
181+ s .set_equation (
182+ stage = "ring_open" , force = "ring-break" , lever = "alpha" , equation = 1 - s .lam ()
183+ )
184+ s .set_equation (
185+ stage = "ring_open" , force = "ring-break" , lever = "kappa" , equation = s .lam ()
186+ )
187+ s .set_equation (
188+ stage = "ring_open" , force = "ring-make" , lever = "alpha" , equation = s .lam ()
189+ )
190+ s .set_equation (
191+ stage = "ring_open" , force = "ring-make" , lever = "kappa" , equation = 1 - s .lam ()
192+ )
165193
166- s .prepend_stage ("restraints_off" , s .initial ())
194+ s .prepend_stage ("restraints_off" , s .initial (), weight = 1 )
167195 s .set_equation (stage = "restraints_off" , lever = "morse_soft" , equation = 1 - s .lam ())
168196 s .set_equation (stage = "restraints_off" , lever = "morse_hard" , equation = 0 )
169197 s .set_equation (stage = "restraints_off" , lever = "bond_k" , equation = s .final ())
@@ -189,7 +217,7 @@ def ring_break_morph():
189217 equation = (1 - s .lam ()) * s .initial () + s .lam () * s .final (),
190218 )
191219
192- s .prepend_stage ("potential_swap" , s .initial ())
220+ s .prepend_stage ("potential_swap" , s .initial (), weight = 2 )
193221 s .set_equation (stage = "potential_swap" , lever = "morse_hard" , equation = 1 - s .lam ())
194222 s .set_equation (stage = "potential_swap" , lever = "morse_soft" , equation = 0 + s .lam ())
195223 s .set_equation (
@@ -207,6 +235,8 @@ def ring_break_morph():
207235 s .set_equation (stage = "potential_swap" , lever = "torsion_k" , equation = s .initial ())
208236 s .set_equation (stage = "potential_swap" , lever = "torsion_phase" , equation = s .initial ())
209237
238+ # morph: standard nonbonded morphing. Ring-break is fixed at fully open
239+ # (kappa=1, alpha=0) since geometry has already relaxed in ring_open.
210240 s .set_equation (stage = "morph" , lever = "morse_hard" , equation = 0 )
211241 s .set_equation (stage = "morph" , lever = "morse_soft" , equation = 0 )
212242 s .set_equation (stage = "morph" , lever = "bond_k" , equation = s .final ())
@@ -215,6 +245,10 @@ def ring_break_morph():
215245 s .set_equation (stage = "morph" , lever = "angle_size" , equation = s .final ())
216246 s .set_equation (stage = "morph" , lever = "torsion_k" , equation = s .final ())
217247 s .set_equation (stage = "morph" , lever = "torsion_phase" , equation = s .final ())
248+ s .set_equation (stage = "morph" , force = "ring-break" , lever = "alpha" , equation = 0 )
249+ s .set_equation (stage = "morph" , force = "ring-break" , lever = "kappa" , equation = 1 )
250+ s .set_equation (stage = "morph" , force = "ring-make" , lever = "alpha" , equation = 1 )
251+ s .set_equation (stage = "morph" , force = "ring-make" , lever = "kappa" , equation = 0 )
218252
219253 return s
220254
@@ -223,7 +257,7 @@ def reverse_ring_break_morph():
223257 """
224258 Build a lambda schedule for reverse ring-breaking perturbations.
225259
226- Three stages: morph → bonded_perturb → potential_swap.
260+ Four stages: morph → ring_close → bonded_perturb → potential_swap.
227261
228262 Returns
229263 -------
@@ -234,7 +268,10 @@ def reverse_ring_break_morph():
234268 from sire .cas import LambdaSchedule as _LambdaSchedule
235269
236270 s = _LambdaSchedule .standard_morph ()
271+ s .set_stage_weight ("morph" , 2 )
237272
273+ # morph: standard nonbonded morphing. Ring-break fixed at fully open
274+ # (kappa=1, alpha=0); ring-make fixed at full interaction (kappa=1, alpha=0).
238275 s .set_equation (stage = "morph" , lever = "morse_hard" , equation = 0 )
239276 s .set_equation (stage = "morph" , lever = "morse_soft" , equation = 0 )
240277 s .set_equation (stage = "morph" , lever = "bond_k" , equation = s .initial ())
@@ -243,8 +280,36 @@ def reverse_ring_break_morph():
243280 s .set_equation (stage = "morph" , lever = "angle_size" , equation = s .initial ())
244281 s .set_equation (stage = "morph" , lever = "torsion_k" , equation = s .initial ())
245282 s .set_equation (stage = "morph" , lever = "torsion_phase" , equation = s .initial ())
283+ s .set_equation (stage = "morph" , force = "ring-break" , lever = "alpha" , equation = 1 )
284+ s .set_equation (stage = "morph" , force = "ring-break" , lever = "kappa" , equation = 0 )
285+ s .set_equation (stage = "morph" , force = "ring-make" , lever = "alpha" , equation = 0 )
286+ s .set_equation (stage = "morph" , force = "ring-make" , lever = "kappa" , equation = 1 )
287+
288+ # ring_close: non-bonded terms fixed at final; ring-make interaction ramps
289+ # off (alpha: 0→1, kappa: 1→0) to allow atoms to relax into ring geometry
290+ # before Morse is applied. Symmetric counterpart to ring_open.
291+ s .append_stage ("ring_close" , s .final (), weight = 1 )
292+ s .set_equation (stage = "ring_close" , lever = "morse_hard" , equation = 0 )
293+ s .set_equation (stage = "ring_close" , lever = "morse_soft" , equation = 0 )
294+ s .set_equation (stage = "ring_close" , lever = "bond_k" , equation = s .initial ())
295+ s .set_equation (stage = "ring_close" , lever = "bond_length" , equation = s .initial ())
296+ s .set_equation (stage = "ring_close" , lever = "angle_k" , equation = s .initial ())
297+ s .set_equation (stage = "ring_close" , lever = "angle_size" , equation = s .initial ())
298+ s .set_equation (stage = "ring_close" , lever = "torsion_k" , equation = s .initial ())
299+ s .set_equation (stage = "ring_close" , lever = "torsion_phase" , equation = s .initial ())
300+ s .set_equation (stage = "ring_close" , force = "ring-break" , lever = "alpha" , equation = 1 )
301+ s .set_equation (stage = "ring_close" , force = "ring-break" , lever = "kappa" , equation = 0 )
302+ s .set_equation (
303+ stage = "ring_close" , force = "ring-make" , lever = "alpha" , equation = s .lam ()
304+ )
305+ s .set_equation (
306+ stage = "ring_close" , force = "ring-make" , lever = "kappa" , equation = 1 - s .lam ()
307+ )
246308
247- s .append_stage ("bonded_perturb" , s .final ())
309+ # bonded_perturb: Morse soft ramps on; ring-make already off from ring_close.
310+ # Ring-break softcore turns on as any ring-break bond opens (alpha: 1→0,
311+ # kappa: 0→1); ring-make stays off (kappa=0, alpha=1).
312+ s .append_stage ("bonded_perturb" , s .final (), weight = 1 )
248313 s .set_equation (stage = "bonded_perturb" , lever = "morse_soft" , equation = 0 + s .lam ())
249314 s .set_equation (stage = "bonded_perturb" , lever = "morse_hard" , equation = 0 )
250315 s .set_equation (stage = "bonded_perturb" , lever = "bond_k" , equation = s .initial ())
@@ -269,8 +334,16 @@ def reverse_ring_break_morph():
269334 lever = "torsion_phase" ,
270335 equation = (1 - s .lam ()) * s .initial () + s .lam () * s .final (),
271336 )
337+ s .set_equation (
338+ stage = "bonded_perturb" , force = "ring-break" , lever = "alpha" , equation = 1 - s .lam ()
339+ )
340+ s .set_equation (
341+ stage = "bonded_perturb" , force = "ring-break" , lever = "kappa" , equation = s .lam ()
342+ )
343+ s .set_equation (stage = "bonded_perturb" , force = "ring-make" , lever = "alpha" , equation = 1 )
344+ s .set_equation (stage = "bonded_perturb" , force = "ring-make" , lever = "kappa" , equation = 0 )
272345
273- s .append_stage ("potential_swap" , s .final ())
346+ s .append_stage ("potential_swap" , s .final (), weight = 2 )
274347 s .set_equation (stage = "potential_swap" , lever = "morse_hard" , equation = 0 + s .lam ())
275348 s .set_equation (stage = "potential_swap" , lever = "morse_soft" , equation = 1 - s .lam ())
276349 s .set_equation (
0 commit comments