How to make simulation work with playback

I’ve figured out how to update the mesh but I’m now struggling to replicate the normal behavior of the simulation modifiers. I want to run a step when the user starts playback and for it to revert when going back to start. This code gives me the error ‘nonetype is not callable’

import bpy
import numpy as np

mesh_object = bpy.context.active_object

# Ensure it's a mesh and convert to numpy arrays
if mesh_object and mesh_object.type == 'MESH':
    mesh = mesh_object.data
    
    # Extract vertex coordinates as NumPy array
    #positions = np.array([v.co for v in mesh.vertices])

    length = len(mesh.vertices)
    positions = np.empty(length*3, dtype=np.float64)
    mesh.vertices.foreach_get('co', positions)
    positions.shape = (length, 3)
    
    # Extract edges as NumPy array
    #oldedges = np.array([(edge.vertices[0], edge.vertices[1]) for edge in mesh.edges])
    
    edgelength = len(mesh.edges)
    edges = np.empty(edgelength*2, dtype=np.uint8)
    mesh.edges.foreach_get('vertices', edges)
    edges.shape = (edgelength, 2)

else:
    print("Please select a valid mesh object.")


# Initialise timestep (seconds), vertex weight (kg), gravity
timestep = 0.2
weight = 0.05
gravity = np.array([0,0,-9.8])

#initialise velocities
velocities = np.zeros_like(positions)
#print(velocities)

def update(velocities, positions, timestep, weight, gravity):

    #Update velocities and positions
    velocities+= timestep*weight*gravity
    positions += timestep*velocities

    # Put it back into mesh
    positions.shape = length*3
    print(positions)
    mesh.vertices.foreach_set("co", positions)
    mesh.update()

bpy.app.handlers.frame_change_pre.append(update(velocities,positions,timestep,weight,gravity))
#bpy.app.handlers.frame_change_pre.clear()

I’m trying to call the function update() and pass it the variables that should have been set earlier in the script. I can just use ‘undo’ to reset it until i learn a bit more…

How do i control my simulation per frame? thanks