def test_generate_ode_function(self): m, k, c, g, F, x, v = np.random.random(7) args = {'constants': np.array([m, k, c, g]), 'specified': np.array([F])} states = np.array([x, v]) mass_matrix, forcing_vector, constants, coordinates, speeds, specified = \ generate_mass_spring_damper_equations_of_motion() expected_dx = np.array([v, 1.0 / m * (-c * v + m * g - k * x + F)]) backends = ['lambdify', 'theano', 'cython'] for backend in backends: rhs = generate_ode_function(mass_matrix, forcing_vector, constants, coordinates, speeds, specified, generator=backend) dx = rhs(states, 0.0, args) testing.assert_allclose(dx, expected_dx) # Now try it with a function defining the specified quantities. args['specified'] = lambda x, t: np.sin(t) t = 14.345 expected_dx = np.array([v, 1.0 / m * (-c * v + m * g - k * x + np.sin(t))]) for backend in backends: rhs = generate_ode_function(mass_matrix, forcing_vector, constants, coordinates, speeds, specified, generator=backend) dx = rhs(states, t, args) testing.assert_allclose(dx, expected_dx) # Now try it without specified values. mass_matrix, forcing_vector, constants, coordinates, speeds, specified = \ generate_mass_spring_damper_equations_of_motion(external_force=False) expected_dx = np.array([v, 1.0 / m * (-c * v + m * g - k * x)]) for backend in backends: rhs = generate_ode_function(mass_matrix, forcing_vector, constants, coordinates, speeds, specified, generator=backend) dx = rhs(states, 0.0, args) testing.assert_allclose(dx, expected_dx)
def run_benchmark(max_num_links, num_time_steps=1000): """Runs the n link pendulum derivation, code generation, and integration for each n up to the max number provided and generates a plot of the results.""" methods = ['lambdify', 'theano', 'cython'] link_numbers = range(1, max_num_links + 1) derivation_times = zeros(len(link_numbers)) integration_times = zeros((max_num_links, len(methods))) code_generation_times = zeros_like(integration_times) for j, n in enumerate(link_numbers): title = "Pendulum with {} links.".format(n) print(title) print('=' * len(title)) start = time.time() results = \ generate_n_link_pendulum_on_cart_equations_of_motion(n, cart_force=False) derivation_times[j] = time.time() - start print('The derivation took {:1.5f} seconds.\n'.format(derivation_times[j])) # Define the numerical values: parameters, time, and initial conditions arm_length = 1. / n bob_mass = 0.01 / n parameter_vals = [9.81, 0.01 / n] for i in range(n): parameter_vals += [arm_length, bob_mass] # odeint arguments x0 = hstack((0, pi / 2 * ones(len(results[3]) - 1), 1e-3 * ones(len(results[4])))) args = {'constants': array(parameter_vals)} t = linspace(0, 10, num_time_steps) for k, method in enumerate(methods): subtitle = "Generating with {} method.".format(method) print(subtitle) print('-' * len(subtitle)) start = time.time() evaluate_ode = generate_ode_function(*results, generator=method) code_generation_times[j, k] = time.time() - start print('The code generation took {:1.5f} seconds.'.format( code_generation_times[j, k])) start = time.time() odeint(evaluate_ode, x0, t, args=(args,)) integration_times[j, k] = time.time() - start print('ODE integration took {:1.5f} seconds.\n'.format( integration_times[j, k])) del results, evaluate_ode # clean up the cython crud files = glob.glob('multibody_system*') for f in files: os.remove(f) shutil.rmtree('build') # plot the results fig, ax = plt.subplots(3, 1, sharex=True) ax[0].plot(link_numbers, derivation_times) ax[0].set_title('Symbolic Derivation Time') ax[1].plot(link_numbers, code_generation_times) ax[1].set_title('Code Generation Time') ax[1].legend(methods, loc=2) ax[2].plot(link_numbers, integration_times) ax[2].set_title('Integration Time') ax[2].legend(methods, loc=2) for a in ax.flatten(): a.set_ylabel('Time [s]') ax[-1].set_xlabel('Number of links') plt.tight_layout() fig.savefig('benchmark-results.png')
g, ] # Time Varying # ------------ coordinates = [theta1, theta2, theta3] speeds = [omega1, omega2, omega3] specified = [ankle_torque, knee_torque, hip_torque] # Generate RHS Function # ===================== right_hand_side = generate_ode_function(mass_matrix, forcing_vector, constants, coordinates, speeds, specified) # Specify Numerical Quantities # ============================ initial_coordinates = deg2rad(5.0) * array([-1, 1, -1]) initial_speeds = deg2rad(-5.0) * ones(len(speeds)) x0 = concatenate((initial_coordinates, initial_speeds), axis=1) # taken from male1.txt in yeadon (maybe I should use the values in Winters). numerical_constants = array( [ 0.611, # lower_leg_length [m] 0.387, # lower_leg_com_length [m] 6.769, # lower_leg_mass [kg] 0.101, # lower_leg_inertia [kg*m^2]
for k, bv in basu_output.items(): mv = float(moore_output_basu[k]) try: testing.assert_allclose(bv, mv) except AssertionError: print('Failed: {} is supposed to be {} but is {}'.format(k, bv, mv)) # Try with lambdify from pydy_code_gen.code import generate_ode_function parameters = constant_substitutions.keys() parameters.sort() print('Generating a numeric right hand side function.') rhs = generate_ode_function(kane, parameters, specified=[T4, T6, T7], generator="lambdify") state_values = [] for state in kane._q + kane._u: state_values.append(substitutions[state]) parameter_values = [0.0, 0.0, 0.0] + [ constant_substitutions[k] for k in sorted(constant_substitutions.keys()) ] print('Evaluating the right hand side.') xd = rhs(state_values, 0.0, parameter_values) # yaw rate, and wheel contact diff equations # kinetic and potential energy, and energy # contact forces #set_trace()
torso_com_length, torso_mass, torso_inertia, g ] # Time Varying # ------------ coordinates = [theta1, theta2, theta3] speeds = [omega1, omega2, omega3] specified = [ankle_torque, knee_torque, hip_torque] # Generate RHS Function # ===================== right_hand_side = generate_ode_function(mass_matrix, forcing_vector, constants, coordinates, speeds, specified) # Specify Numerical Quantities # ============================ initial_coordinates = deg2rad(5.0) * array([-1, 1, -1]) initial_speeds = deg2rad(-5.0) * ones(len(speeds)) x0 = concatenate((initial_coordinates, initial_speeds), axis=1) # taken from male1.txt in yeadon (maybe I should use the values in Winters). numerical_constants = array( [ 0.611, # lower_leg_length [m] 0.387, # lower_leg_com_length [m] 6.769, # lower_leg_mass [kg] 0.101, # lower_leg_inertia [kg*m^2]
from numpy import testing for k, bv in basu_output.items(): mv = float(moore_output_basu[k]) try: testing.assert_allclose(bv, mv) except AssertionError: print('Failed: {} is supposed to be {} but is {}'.format(k, bv, mv)) # Try with lambdify from pydy_code_gen.code import generate_ode_function parameters = constant_substitutions.keys() parameters.sort() print('Generating a numeric right hand side function.') rhs = generate_ode_function(kane, parameters, specified=[T4, T6, T7], generator="lambdify") state_values = [] for state in kane._q + kane._u: state_values.append(substitutions[state]) parameter_values = [0.0, 0.0, 0.0] + [constant_substitutions[k] for k in sorted(constant_substitutions.keys())] print('Evaluating the right hand side.') xd = rhs(state_values, 0.0, parameter_values) # yaw rate, and wheel contact diff equations # kinetic and potential energy, and energy # contact forces #set_trace() #def print_if(display, message): #if display == True:
def run_benchmark(max_num_links, num_time_steps=1000): """Runs the n link pendulum derivation, code generation, and integration for each n up to the max number provided and generates a plot of the results.""" methods = ['lambdify', 'theano', 'cython'] link_numbers = range(1, max_num_links + 1) derivation_times = zeros(len(link_numbers)) integration_times = zeros((max_num_links, len(methods))) code_generation_times = zeros_like(integration_times) for j, n in enumerate(link_numbers): title = "Pendulum with {} links.".format(n) print(title) print('=' * len(title)) start = time.time() results = \ generate_n_link_pendulum_on_cart_equations_of_motion(n, cart_force=False) derivation_times[j] = time.time() - start print('The derivation took {:1.5f} seconds.\n'.format( derivation_times[j])) # Define the numerical values: parameters, time, and initial conditions arm_length = 1. / n bob_mass = 0.01 / n parameter_vals = [9.81, 0.01 / n] for i in range(n): parameter_vals += [arm_length, bob_mass] # odeint arguments x0 = hstack((0, pi / 2 * ones(len(results[3]) - 1), 1e-3 * ones(len(results[4])))) args = {'constants': array(parameter_vals)} t = linspace(0, 10, num_time_steps) for k, method in enumerate(methods): subtitle = "Generating with {} method.".format(method) print(subtitle) print('-' * len(subtitle)) start = time.time() evaluate_ode = generate_ode_function(*results, generator=method) code_generation_times[j, k] = time.time() - start print('The code generation took {:1.5f} seconds.'.format( code_generation_times[j, k])) start = time.time() odeint(evaluate_ode, x0, t, args=(args, )) integration_times[j, k] = time.time() - start print('ODE integration took {:1.5f} seconds.\n'.format( integration_times[j, k])) del results, evaluate_ode # clean up the cython crud files = glob.glob('multibody_system*') for f in files: os.remove(f) shutil.rmtree('build') # plot the results fig, ax = plt.subplots(3, 1, sharex=True) ax[0].plot(link_numbers, derivation_times) ax[0].set_title('Symbolic Derivation Time') ax[1].plot(link_numbers, code_generation_times) ax[1].set_title('Code Generation Time') ax[1].legend(methods, loc=2) ax[2].plot(link_numbers, integration_times) ax[2].set_title('Integration Time') ax[2].legend(methods, loc=2) for a in ax.flatten(): a.set_ylabel('Time [s]') ax[-1].set_xlabel('Number of links') plt.tight_layout() fig.savefig('benchmark-results.png')
def test_generate_ode_function(self): m, k, c, g, F, x, v = np.random.random(7) args = { 'constants': np.array([m, k, c, g]), 'specified': np.array([F]) } states = np.array([x, v]) mass_matrix, forcing_vector, constants, coordinates, speeds, specified = \ generate_mass_spring_damper_equations_of_motion() expected_dx = np.array([v, 1.0 / m * (-c * v + m * g - k * x + F)]) backends = ['lambdify', 'theano', 'cython'] for backend in backends: rhs = generate_ode_function(mass_matrix, forcing_vector, constants, coordinates, speeds, specified, generator=backend) dx = rhs(states, 0.0, args) testing.assert_allclose(dx, expected_dx) # Now try it with a function defining the specified quantities. args['specified'] = lambda x, t: np.sin(t) t = 14.345 expected_dx = np.array( [v, 1.0 / m * (-c * v + m * g - k * x + np.sin(t))]) for backend in backends: rhs = generate_ode_function(mass_matrix, forcing_vector, constants, coordinates, speeds, specified, generator=backend) dx = rhs(states, t, args) testing.assert_allclose(dx, expected_dx) # Now try it without specified values. mass_matrix, forcing_vector, constants, coordinates, speeds, specified = \ generate_mass_spring_damper_equations_of_motion(external_force=False) expected_dx = np.array([v, 1.0 / m * (-c * v + m * g - k * x)]) for backend in backends: rhs = generate_ode_function(mass_matrix, forcing_vector, constants, coordinates, speeds, specified, generator=backend) dx = rhs(states, 0.0, args) testing.assert_allclose(dx, expected_dx)