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 unpractical to formulate a complicated expression in an explicit form. |
• | To take full advantage of a programming language like C/C++ or Fortran or a scripting language like Python or MATLAB. |
Note | Using user subroutines adds a level of complexity to your multi-body model. We recommend using the built-in functions to model your system before using subroutines unless it is necessary or more convenient to use subroutines. |
To use your own subroutines in MotionSolve, follow these steps:
1. | Create a Python, MATLAB, C/C++ or FORTRAN source file that contains the user defined modeling entity. |
2. | Obtain a Dynamic-Link Library (DLL) or Shared Object (SO) by compiling and linking your user subroutine(s) – only for C/C++ or FORTRAN source code. No compiling is required for Python or MATLAB source code. Python routines are automatically compiled, and you can use compiled Python files with MotionSolve without the source files. |
3. | Modify the corresponding entity in your multi-body model to be "user defined" and to point to your DLL/SO or script file. |
4. | Run MotionSolve, verifying that it picks up the appropriate DLL/SO or script file during simulation. |
The above steps are described in detail in the sections below.
To write a user subroutine, you first have to determine which user subroutine you need to use and select a programming language. Listed below are supported solver subroutines and the corresponding user defined entity.
To help you create a user subroutine, included in the installation is a series of simple routine templates (one for each supported routine) in FORTRAN, C/C++, Python and MATLAB programming/scripting languages. These templates are located in the following installation directories: <install-path>\hwsolvers\motionsolve\usersub\f_src <install-path>\hwsolvers\motionsolve\usersub\c_src <install-path>\hwsolvers\motionsolve\usersub\mex <install-path>\hwsolvers\motionsolve\usersub\py_src Also included in the installation directory is a Microsoft Visual Studio Project file that can be optionally used to create your user library (DLL, Dynamic-Link Library). The C/C++ simple routine templates included in the installation contain the required include statements:
This external file is used to resolve the symbols of the various utility functions that can be invoked. They contain the function prototypes of utility functions like SYSFNC, AKISPL, and all other utility functions that can be used to access system states (displacement, velocity, acceleration, forces, and so on) and MotionSolve states (current simulation time, solver mode, and so on). You can simplify the process of creating the DLL by using Microsoft Visual Studio with the supplied project file which contains all compiler and linker options, the name of the generated DLL, and the pointers to all source files used for generating the DLL. Below is an example of how to do this with the FORTRAN or C/C++ projects. |
|
When editing the FORTRAN or C/C++ subroutine(s), you have to observe certain guidelines regarding assigning arguments, variable declarations, and calls to utility functions. User written subroutines have input and output arguments. Typically, the output arguments are the result of the computation performed in your routine, while input arguments provide a communication between the multi-body model (and its solver representation, the MotionSolve XML file) and the routine itself. You can use parameters as input arguments to make subroutines more general. In other words, do not use hard coded entity IDs, but instead use them as input parameters to your routine. To make sure that your subroutine(s) are effectively interfaced with MotionSolve, you need to accurately declare the input and output variables according to the guidelines provided in the subroutine templates. In other words, you should use the supplied routine templates where variables are already declared directly in the subroutine declaration (C/C++): void STDCALL REQSUB(int *id, double *time, double *par, int *npar, int *iflag, double *results) Or, declared shortly after the subroutine declaration (FORTRAN): SUBROUTINE REQSUB (ID, TIME, PAR, NPAR, IFLAG, RESULTS) DOUBLE PRECISION STATES(6) INTEGER ITYPE, IPAR(10), NSTATES LOGICAL ERRFLG In addition to subroutine templates, MotionSolve also offers utility subroutines if you need to call them from your routines. These utility subroutines provide system states like displacement, velocity, acceleration, and force on various entities of your mechanical multi-body system, allowing your routine(s) to accurately define and compute outputs based on system states. For information about the available utility functions and how to call them from your subroutine(s), please refer to Utility Subroutines in the XML Format Reference Guide. |
MotionSolve supports two separate levels of user DLLs/SOs and the algorithm attempts to resolve the symbols, starting from the most specific library. It is possible to specify an Element Level DLL/SO (most specific) and a Machine Level DLL/SO. They can be defined as follows:
<Constraint_Coupler id = "1" label = "TwoJoint" joint1_id = "30603030" joint2_id = "30602031" freedom_1 = "T" freedom_2 = "T" usrsub_param_string = "USER(-8.5)" usrsub_dll_name = "C:/work/testsub.dll" usrsub_fnc_name = “coupler_function” > </Constraint_Coupler> The usrsub_dll_name argument defines C:/work/testsub.dll as the element level DLL/SO for this coupler element. Any element can be defined pointing to a different DLL/SO.
You can create an environment variable called MS_USERSUBDLL and set it to the DLL/SO file. This environment variable is not defined automatically when MotionSolve is installed. However, FORTRAN and C/C++ DLLs/SOs are provided in the installation in folder <install-path>\hwsolvers\usersub\subdll\<platform>. This is so you can run some of the test models that use user subroutine DLLs. The selection of what DLL/SO is loaded and used is based on the "most specific" rule: number one overrides number two. |
In addition to writing your solver subroutine, you also have to modify the corresponding modeling element in your multi-body model so that it receives output value(s) from the user subroutine. This can be done in two ways:
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, the following motion entity: <Motion_Joint id = "101001" type = "EXPRESSION" val_type = "D" expr = "-.2*TIME" joint_id = "101002" joint_type = "R" motion_type = "R" ic_disp = "0." ic_vel = "0."> </Motion_Joint> can be modified in the following manner to indicate that the motion value is computed in a user subroutine, as opposed to an explicit function expression. <Motion_Joint id = "101001" type = "USERSUB" val_type = "D" usrsub_param_string = "USER(5,2)" usrsub_dll_name = “C:/work/testsub.dll" joint_id = "101002" joint_type = "R" motion_type = "R" ic_disp = "0." ic_vel = "0."> </Motion_Joint> |
At runtime, MotionSolve loads the appropriate user DLL/SO, according to the rules described above (most specific among "element" and "machine level" DLL/SO). For verification purposes, MotionSolve outputs the DLL/SO that loaded at runtime immediately after the initialization of the model. User Subroutine DLL [C:/work/testsub.dll] Loaded The above message is displayed in the analysis log file. After the analysis is completed, a similar message informs the user that MotionSolve has unloaded the user subroutine DLL/SO. Unloading User Subroutine DLL [C:/work/testsub.dll] |