@@ -310,140 +310,120 @@ def __init__(self,
310310 nsteps_neq = 0 ,
311311 nprop = 1 ,
312312 prop_lambda = 0.3 ,
313- lambda_restraints = 'max(0, 1 - 2*abs(lambda - 0.5))' , # tent fn (0→1 at 0.5→0)
313+ lambda_restraints = 'max(0, 1-(1/0.10)*abs(lambda-0.5))' ,
314+ #relax_steps=500, #'max(0, 1-(1/0.10)*abs(lambda-0.5))', #"3*lambda^2 - 2*lambda^3", # old: 'max(0, 1-(1/0.10)*abs(lambda-0.5))'
314315 relax_steps = 50 ,
315316 * args , ** kwargs ):
316-
317- # Store the expression string separately to avoid name collisions
318- self .lambda_restraints_expr = lambda_restraints
319-
320- # Which energy group holds the restraint energy (so we can subtract it cleanly)
321- self .restraint_energy_group = str (restraint_group )
322- self .restraint_energy_ref = f"energy{ self .restraint_energy_group } "
323-
324- super ().__init__ (
325- alchemical_functions = alchemical_functions ,
326- splitting = splitting ,
327- temperature = temperature ,
328- collision_rate = collision_rate ,
329- timestep = timestep ,
330- constraint_tolerance = constraint_tolerance ,
331- measure_shadow_work = measure_shadow_work ,
332- measure_heat = measure_heat ,
333- nsteps_neq = nsteps_neq ,
334- nprop = nprop ,
335- prop_lambda = prop_lambda ,
336- * args , ** kwargs
337- )
338-
317+
318+ self .lambda_restraints = lambda_restraints
319+ self .restraint_energy = "energy" + str (restraint_group )
320+
321+ super (AlchemicalExternalRestrainedLangevinIntegrator , self ).__init__ (
322+ alchemical_functions ,
323+ splitting ,
324+ temperature ,
325+ collision_rate ,
326+ timestep ,
327+ constraint_tolerance ,
328+ measure_shadow_work ,
329+ measure_heat ,
330+ nsteps_neq ,
331+ nprop ,
332+ prop_lambda ,
333+ * args , ** kwargs )
334+
335+ try :
336+ self .addGlobalVariable ("restraint_energy" , 0 )
337+ except :
338+ pass
339339 logger .info (f'[LAMBDA STEPS] N_lambda_steps: { self ._n_lambda_steps } ' )
340-
341- # === Declare NEW integrator globals (names MUST match force globals if you want propagation) ===
340+ # Only declare NEW variables
342341 self .addGlobalVariable ("debug_lambda" , 0.0 )
343- self .addGlobalVariable ("restraint_energy" , 0.0 ) # running value read via energy group
342+ # self.addGlobalVariable("restraint_energy", 0.0)
344343
344+ # Set existing globals from parent
345+ # self.setGlobalVariableByName("lambda_step", 0.0)
346+ # self.setGlobalVariableByName("lambda", 0.0)
345347
346348 # Optional debug
347349 self .addComputeGlobal ("debug_lambda" , "lambda" )
348350
349- logger .info (f"Current nsteps_neq: { nsteps_neq } " )
350- logger .info (f'lambda_restraints expression: { self .lambda_restraints_expr } ' )
351-
351+ # Now safe to use lambda_restraints in update
352+ #self.updateRestraints()
352353
354+ logger .info (f"Current nsteps_neq: { nsteps_neq } " )
355+ logger .info (f'lambda_restraints selected: { self .lambda_restraints } ' )
356+ # compute the mid‐point slice index once
357+ mid = int (self ._n_lambda_steps / 2 )
358+ self .addGlobalVariable ("mid_step" , float (mid ))
359+ self .addGlobalVariable ("relax_counter" , 0.0 )
360+ self .addGlobalVariable ("relax_steps" , float (relax_steps ))
353361
354- # ---- Helper: recompute + propagate lambda_restraints each time lambda changes ----
355- def _recompute_and_push_lambda_restraints (self ):
356- # 1) Recompute integrator global from current 'lambda'
357- self .addComputeGlobal ('lambda_restraints' , self .lambda_restraints_expr )
358- # 2) Propagate integrator globals -> Context parameters (names must match in forces)
359- self .addUpdateContextState ()
362+ def updateRestraints (self ):
363+ logger .info (f"UPDATE RESTAINTS: { self .lambda_restraints } " )
364+ self .addComputeGlobal ('lambda_restraints' , self .lambda_restraints )
360365
361- # ---- Helper: refresh restraint energy and split PE bookkeeping ----
362- def _refresh_restraint_and_pes (self ):
363- self .addComputeGlobal ("restraint_energy" , self .restraint_energy_ref )
364- # Exclude restraint energy so protocol work uses only alchemical parts
365- self .addComputeGlobal ("perturbed_pe" , "energy - restraint_energy" )
366- self .addComputeGlobal ("unperturbed_pe" , "energy - restraint_energy" )
367366
368367 def _add_integrator_steps (self ):
369368 """
370- Override to insert (a) consistent initialization and (b) frequent
371- lambda_restraints recompute + propagation around each propagation call.
369+ Override the base class to insert reset steps around the integrator.
372370 """
373-
374- # =========================
375- # Initialization (step == 0)
376- # =========================
371+
372+ # First step: Constrain positions and velocities and reset work accumulators and alchemical integrators
373+ logger .info ("sams protocol" )
377374 self .beginIfBlock ('step = 0' )
378-
379- # Make sure restraints start consistent with lambda=0
380- self ._recompute_and_push_lambda_restraints ()
381- self ._refresh_restraint_and_pes ()
382-
383- # Usual initialization: constrain and reset accumulators
375+ self .addComputeGlobal ("restraint_energy" , self .restraint_energy )
376+ self .addComputeGlobal ("perturbed_pe" , "energy - restraint_energy" )
377+ self .addComputeGlobal ("unperturbed_pe" , "energy - restraint_energy" )
384378 self .addConstrainPositions ()
385379 self .addConstrainVelocities ()
386380 self ._add_reset_protocol_work_step ()
387381 self ._add_alchemical_reset_step ()
382+ self .endBlock ()
388383
389- self .endBlock () # end init
390-
391- # =========================
392384 # Main body
393- # =========================
385+
394386 if self ._n_steps_neq == 0 :
395- # Force a single execution on first step
387+ # If nsteps = 0, we need to force execution on the first step only.
396388 self .beginIfBlock ('step = 0' )
397- # Track lambda_restraints before the parent propagation
398- self ._recompute_and_push_lambda_restraints ()
399- self ._refresh_restraint_and_pes ()
400- super ()._add_integrator_steps () # call parent’s propagation
389+ super (AlchemicalNonequilibriumLangevinIntegrator , self )._add_integrator_steps ()
401390 self .addComputeGlobal ("step" , "step + 1" )
402391 self .endBlock ()
403- return
404-
405- # NEQ loop
406- self .beginIfBlock ("step < n_lambda_steps" )
407-
408- # --- First substep at this NEQ step ---
409- # Update lambda_restraints to track the *new* lambda for this substep
410- self ._recompute_and_push_lambda_restraints ()
411- self ._refresh_restraint_and_pes ()
412-
413- # First-step bookkeeping (only once)
414- self .beginIfBlock ("first_step < 1" )
415- self .addComputeGlobal ("first_step" , "1" )
416- self ._refresh_restraint_and_pes ()
417- self .endBlock ()
418-
419- # Protocol work increment (before propagation) using split PEs
420- self .addComputeGlobal ("protocol_work" , "protocol_work + (perturbed_pe - unperturbed_pe)" )
421-
422- # === Primary propagation for this lambda value ===
423- self ._recompute_and_push_lambda_restraints ()
424- super ()._add_integrator_steps () # parent does the actual R/V/O/H... steps
425-
426- # ============ Optional extra propagation windows at same lambda ============
427- self .beginIfBlock ("lambda > prop_lambda_min" )
428- self .beginIfBlock ("lambda <= prop_lambda_max" )
429-
430- self .beginWhileBlock ("prop < nprop" )
431- self .addComputeGlobal ("prop" , "prop + 1" )
432-
433- self ._recompute_and_push_lambda_restraints ()
434- super ()._add_integrator_steps ()
435-
436- self .endBlock () # while
437- self .endBlock () # if <= prop_lambda_max
438- self .endBlock () # if > prop_lambda_min
392+ else :
393+ #call the superclass function to insert the appropriate steps, provided the step number is less than n_steps
394+ self .beginIfBlock ("step < n_lambda_steps" )#
395+ self .addComputeGlobal ("restraint_energy" , self .restraint_energy )
396+ self .addComputeGlobal ("perturbed_pe" , "energy - restraint_energy" )
397+ self .beginIfBlock ("first_step < 1" )##
398+ #TODO write better test that checks that the initial work isn't gigantic
399+ self .addComputeGlobal ("first_step" , "1" )
400+ self .addComputeGlobal ("restraint_energy" , self .restraint_energy )
401+ self .addComputeGlobal ("unperturbed_pe" , "energy-restraint_energy" )
402+ self .endBlock ()##
403+ #initial iteration
404+ # Gill put this first:
405+ self .addComputeGlobal ("protocol_work" ,
406+ "protocol_work + (perturbed_pe - unperturbed_pe)"
407+ )
408+ super (AlchemicalNonequilibriumLangevinIntegrator , self )._add_integrator_steps ()
409+ logger .info ("COMPUTE WORKSSSS" )
410+ #if more propogation steps are requested
411+ self .beginIfBlock ("lambda > prop_lambda_min" )###
412+ self .beginIfBlock ("lambda <= prop_lambda_max" )####
439413
440- # ---- End-of-step bookkeeping ----
441- # Recompute to ensure end-of-step energies are coherent
442- self ._recompute_and_push_lambda_restraints ()
443- self ._refresh_restraint_and_pes ()
414+ self .beginWhileBlock ("prop < nprop" )#####
415+ self .addComputeGlobal ("prop" , "prop + 1" )
444416
445- self .addComputeGlobal ("step" , "step + 1" )
446- self .addComputeGlobal ("prop" , "1" )
417+ super (AlchemicalNonequilibriumLangevinIntegrator , self )._add_integrator_steps ()
418+ self .endBlock ()#####
419+ self .endBlock ()####
420+ self .endBlock ()###
421+ #ending variables to reset
422+ self .updateRestraints ()
423+ self .addComputeGlobal ("restraint_energy" , self .restraint_energy )
424+ self .addComputeGlobal ("unperturbed_pe" , "energy-restraint_energy" )
425+ self .addComputeGlobal ("step" , "step + 1" )
426+ self .addComputeGlobal ("prop" , "1" )
447427
448- self .endBlock () # if step < n_lambda_steps
428+ self .endBlock ()#
449429
0 commit comments