# MV-1024: Using User Subroutines in MotionSolve Models

In this tutorial, you will learn about the benefits of user subroutines in defining motion.

User subroutines are created for various reasons. Some include:
• To describe a physical phenomenon that is determined by non-trivial logical conditions.
• When it is impractical to formulate a complicated expressions in an explicit form.
• To take full advantage of a programming language like C/C++ or Fortran and simpler programming with interpreters like Tcl, Python, and Ruby.

1. Create a C/C++, FORTRAN, Tcl, or Python source file that contains the user-defined modeling entity.

Refer to the MotionSolve User's Guide for a list of supported solver subroutines and a general guideline on setting up and using subroutines in your model.

2. Obtain a DLL by compiling and linking your user subroutine(s) for C/C++ or Fortran, or use the source file directly for Tcl or Python.
MotionSolve supports two separate levels of user DLLs and the algorithm attempts to resolve the symbols, starting from the most specific library.
1. Element Level DLL (most specific)

Specify the name of the DLL in the modeling element definition.

2. Machine Level DLL

You can create an environment variable called MS_USERSUBDLL and set it to the DLL file. This environment variable is not defined automatically when MotionSolve is installed. However, Fortran, and C/C++ DLLs are provided in the installation folder <installation_directory>\hwsolvers\usersub\subdll\win32\. This allows you to run some of the test models that use user subroutine DLLs.

Note: The DLL that is loaded is based on the "most specific" rule: number one overrides number two.
3. Modify the corresponding entity in your multibody model to be "user defined" and point it to your DLL. This can be done in two ways:
1. By modifying the entity in the MotionView interface.
2. By editing the MotionSolve XML file.

Regardless of the method you select, you will end up with an XML file where one or more entities are now user defined.

For example, consider the coupler modeling element in the XML file:

 <Constraint_Coupler
id                  = "1"
type                = "TwoJoint"
i_marker_id_joint1  = "30603030"
j_marker_id_joint1  = "30602031"
body1_id_joint1     = "30603"
body2_id_joint1     = "30602"
joint_type_joint1   = " "
i_marker_id_joint2  = "30603040"
j_marker_id_joint2  = "30604040"
body1_id_joint2     = "30603"
body2_id_joint2     = "30604"
joint_type_joint2   = " "
usrsub_param_string = "USER(-8.5)"
usrsub_dll_name     = "C:/work/testsub.dll">
</Constraint_Coupler>

The usrsub_dll_name argument defines C:/work/testsub.dll as the element level DLL for this coupler element. Any element can be defined by pointing to a different DLL.

The coupler modeling element in the XML file can also be defined as:

 <Constraint_Coupler
id                  = "1"
type                = "TwoJoint"
i_marker_id_joint1  = "30603030"
j_marker_id_joint1  = "30602031"
body1_id_joint1     = "30603"
body2_id_joint1     = "30602"
joint_type_joint1   = " "
i_marker_id_joint2  = "30603040"
j_marker_id_joint2  = "30604040"
body1_id_joint2     = "30603"
body2_id_joint2     = "30604"
joint_type_joint2   = " "
usrsub_param_string = "USER(-8.5)"
usrsub_dll_name     = "NULL">
</Constraint_Coupler>

In this case, MotionSolve looks for a machine level DLL as defined by the value of the MS_USERSUBDLL environment variable.

4. Run MotionSolve, verifying that it picks up the appropriate DLL during simulation.

Copy the model file required for this exercise, Pendu_model.mdl, from the mbd_modeling\motionsolve to your <working directory>.

## Use an Expression to Define Motion

1. Launch a new MotionView session.
3. From the Project Browser, right-click on Model and select Add Constraint > Motions (or right-click Motions from the toolbar).
4. Add a Displacement motion to the revolute joint between the pendulum body and the ground body.
5. Click the Properties tab.
6. Set an expression of 3.142* TIME for the displacement motion.
7. Click Outputs to access the Outputs panel.
Review the output request.
8. Click Run , to access the Run panel.
9. Click Save and run current model and browse to your <working directory>. Specify the name as Pendu_model.xml for the MotionSolve input XML file.
10. Confirm that the Simulation type is set to Transient.
11. Specify 1 as the End Time.
12. Click Check to check for any modeling errors.
13. After verifying that there are no errors, click Run.
14. Once the run is complete, the Animate button is activated. Click Animate to view the animation of the simulation.
15. From the Run panel, click Plot to view the time-histories of the output request.

## Use the MOTSUB User Subroutine to Define Motion

In this step, you will use the user subroutine MOTSUB. This user subroutine has been compiled and linked in the DLL ms_csubdll.dll. This machine level DLL is provided in the HyperWorks installation. For the Windows 64-bit platform, the DLL is located at: <installation_directory>\hwsolvers\motionsolve\usersub\subdll\win64\.

You will use the ms_csubdll.dll as a machine level DLL.

1. Create an environment variable MS_USERSUBDLL and set the value to the DLL file.
1. For Windows 64-bit platform users, set the value to <installation_directory>\hwsolvers\motionsolve\usersub\subdll\win64\ms_csubdll.dll.
2. Right-click on the My Computer icon. From the Advanced tab, select Environment variables > New (under User variables).
3. Set Variable name to MS_USERSUBDLL.
4. Set Variable value to <installation_directory>\hwsolvers\motionsolve\usersub\subdll\win64\ms_csubdll.dll.
2. With the Pendu_model.mdl from the previous step open in the MotionView model window, go to the Motions panel, .
3. From the Connectivity tab, check the User-defined properties check box.
4. Click the User-Defined tab and enter USER(100001,5,2) in the text-box.
Note: To use an element level (specific) DLL/Interpreter function, you can check the Use local dll and function name check-box and point to the DLL using the folder icon, .

The string USER(100001,5,2) is used to pass arguments to the MOTSUB user subroutine. The MOTSUB user subroutine calculates motion using the parameters par1 and par2 in USER(branch_id, par1, par2) as follows:

motion_val= par1*TIME^par2
5. From the File menu, select Export > Model.
The Export Model panel is displayed.
6. Specify the file name as Pendu_model_usersub.mdl.
7. Close the current session of MotionView and launch a new session. Open the saved model: Pendu_model_usersub.mdl.
8. Click Run to access the Run panel.
9. Click Save and run current model and browse to your working directory. Specify Pendu_model_usersub.xml for the MotionSolve input XML file.
10. Confirm that the Simulation type is set to Transient.
11. Specify 1 as the End Time.
12. From the Main tab, click Check to check for any modeling errors.
13. After verifying that there are no errors, click Run.
14. In the plot window, plot the results from the ABF file Pendu_model_usersub.abf to overlay the results on top of the results from the Pendu_model.abf file
15. In the animation window, check the Overlay option on the Load Model panel.
16. Select the file Pendu_model_usersub.h3d using the Load model folder icon .
17. Click Apply.
This will overlay the new animation over the existing animation.
Note: If the value of the usrsub_param_string is set as "USER(3.142, 1)" the results from step 2 will be the same as results from step 1.
18. Open the MotionSolve XML file Pendu_model.xml (saved in step 1) from the working directory.
19. Browse through the XML file to locate the Motion_Joint block.
<Motion_Joint
id                  = "301001"
label               = "Motion 0"
type                = "EXPRESSION"
val_type            = "D"
expr                = "3.142*TIME"
joint_id            = "301001"
joint_type          = "R"
/>
20. Open the MotionSolve XML file Pendu_model_usersub.xml from the working directory.
21. Browse through the XML file to locate the Motion_Joint block.
<Motion_Joint
id                  = "301001"
label               = "Motion 0"
type                = "USERSUB"
val_type            = "D"
usrsub_param_string = "USER(100001,5,2)"
usrsub_dll_name     = "NULL"
usrsub_fnc_name     = "MOTSUB"
joint_id            = "301001"
joint_type          = "R"
/> 
Note: When the value for the usrsub_dll_name parameter in the above block is set to NULL, MotionSolve looks for the subroutine in a machine level DLL. This DLL is passed to MotionSolve by the MS_USERSUBDLL environment variable.
22. To use an element level DLL, set the value of the usrsub_dll_name parameter to point to the DLL.
The usrsub_param_string parameter is used to pass arguments to the user subroutine.
For example, the MOTSUB user subroutine calculates motion using the parameters par1 and par2 in USER(branch_id, par1, par2) as follows:
motion_val= par1*TIME^par2
MotionSolve uses the value returned from the user subroutine to calculate the motion.