20.6.11.1. U Function
U Function block enables user to make a special block to simulate user’s equations in the CoLink model. The equation that user is able to use in U Function block is differential equations and the relational expression of input and output between inputs and outputs.
In order to use U Function block, you should make DLL file with the regular format for U Function and written C or C++ language.
In DLL file, the below functions should be disclosed as “C” __declspec(dllexport) type.
void simInitializes(CSys *CS)
void simInitialConditions(CSys *CS)
void simUpdateParameters(CSys *CS)
void simJacobians(CSys *CS)
void simDerivatives(CSys *CS)
void simOutputs(CSys *CS)
void simTerminates(CSys *CS)
CoLink solver loads the defined DLL file and calls the above functions in a DLL file made by the user during simulation. CSys is the class and you can get or set information of U Function block where CSys is.
20.6.11.1.1. U Function Block
If you use the U Function icon of the User Function group in the Connector tab, you can create a U Function block in the modeling window.
Dialog box
Parameter(s) |
Description |
Dll File |
Defines a DLL file name which is used in the U Function block made by the rule of U Function. |
Parameters |
Defines the values of inputting parameters which can be used in U Function DLL. (ex:0.4, 1.0) |
Password |
Inputs the password which is defined in the DLL file. |
20.6.11.1.2. Function List
The following functions should be defined in U Function and the codes are performed a simulation by the CoLink solver.
void simInitializes(CSys *CS)
void simInitialConditions(CSys *CS)
void simUpdateParameters(CSys *CS)
void simJacobians(CSys *CS)
void simDerivatives(CSys *CS)
void simOutputs(CSys *CS)
void simTerminates(CSys *CS)
CSys class
The CSys class is the opened class in the CoLink solver. You can set or get desired values by the member function of CSys.
U Function Operation Flow
The CoLink solver is divided into three big processes - the initialization process, the simulation loop process, and the termination process. The defined functions by the user are called by the each process.
Initialization |
simInitializes |
Required |
sim InitialConditions |
Required |
|
Simulation Loop |
si mUpdateParameters |
Optional |
simJacobians |
Optional |
|
simDerivatives |
Optional (If there are the differential equations, it should certainly exist.) |
|
simOutputs |
Required |
|
Termination |
CSubTerminate |
Optional |
Initialization Process
Before the first simulation loop, U Function block is initialized by CoLink solver to call simInitializes and simInitialConditions.
Works in simInitializes
SetNumInputPort: Defines the number of input port.
SetInputPortSize: Defines the size of each input port.
SetNumOutputPort: Defines the number of output port.
SetOutputPortSize: Defines the size of output port.
SetNumDiffStates: Defines the number of differential equations.
SetSampleTime: Defines the sample time.
extern "C" __declspec(dllexport) void simInitializes(CSys *CS) { CS->SetNumInputPort(1); CS->SetInputPortSize(0,1); CS->SetNumOutputPort(1); CS->SetOutputPortSize(0,1); CS->SetNumDiffStates(3); CS->SetSampleTime(-1.0); }
Works in simInitialConditions
Define initial conditions of differential states.
GetNumDiffStates: Get the number of differential states.
GetDiffStates: Get the data array of differential sates.
SetJacobianMethod: Define the method to calculate Jacobian of differential states.
SetNumRWork: Define double data array to use in U Function.
SetNumIWork: Define integer data array to use in U Function.
SetPassword: Define a password to lock a DLL file. The user can use this DLL file if the password inputted in U Function block is matched with this password.
extern "C" __declspec(dllexport) void simInitialConditions(CSys *CS) { double* Beta; int nDiff; nDiff = CS->GetNumDiffStates(); Beta = CS->GetDiffStates(); for( int i=0 ; i<nDiff ; i++ ) { Beta[i] = 0.0; } CS->SetJacobianMethod(2); // 1:FDM 2:Analytical CS->SetNumRWork(nDiff*nDiff); CS->SetNumIWork(0); CS->WriteToMessageFile("U Function Sample Code.\n"); }
Simulation Loop Process
In simulation loop process, simUpdateParameters, simJacobians, simDerivatives, and simOutputs are called by the CoLink solver.
Works in simUpdateParameters
SetParameter: Changes the input parameters in the U Function block.
SetParameterWithName: Changes the input parameters in the U Function block.
If there are the defined functions, simUpdateParameters is called.If there are not the defined functions, simUpdateParameters is skipped.
extern "C" __declspec(dllexport) void simUpdateParameters(CSys *CS) { double simtime; simtime = CS->GetSimTime(); if( simtime > 1.0 ) CS->SetParameter(0,0.2); }
Works in simJacobians
SetJacobian: Sets the values of Jaconbian matrix
simJacobians is called by the implicit integrator(ADVHYBRID).
If there are not the defined functions, solver calculates the Jacobian matrix using FDM method.
extern "C" __declspec(dllexport) void simJacobians(CSys *CS) { double Ra,La,Ke,Inertia; double *Jac; int nDiff; Ke = CS->GetParameter(0); Ra = CS->GetParameter(2); La = CS->GetParameter(3); Inertia = CS->GetParameter(4); Jac = CS->GetRWorkPtr(); Jac[0] = -Ra/La; Jac[1] = 0.0; Jac[2] = -Ke/La; Jac[3] = 0.0; Jac[4] = 0.0; Jac[5] = 1.0; Jac[6] = Ke/Inertia; Jac[7] = 0.0; Jac[8] = 0.0; CS->SetJacobian(Jac); }
Works in simDerivatives
Define the derivative values of differential states.
GetDiffStates: Get the data point of differential states.
GetDotDiffStates: Get the data point of derivatives of differential states.
If there are the differential equations in U Function, it should be defined.
extern "C" __declspec(dllexport) void simDerivatives(CSys *CS) { double Ra,La,Ke,Kt,angle,omega,Ia,Va,E,Te,Tfric,Td; double Inertia,Bm,Tf,TL; double simtime; int npole; double *Uin; double *dBeta,*Beta; // Parameter Ke = CS->GetParameter(0); npole = (int) CS->GetParameter(1); Ra = CS->GetParameter(2); La = CS->GetParameter(3); Inertia = CS->GetParameter(4); Bm = CS->GetParameter(5); Tf = CS->GetParameter(6); // Input Uin = CS->GetInputPortData(0); // Diff eqn. Beta = CS->GetDiffStates(); dBeta = CS->GetDotDiffStates(); TL = 0.0; Va = Uin[0]; Ia = Beta[0]; angle = Beta[1]; omega = Beta[2]; // Motor eqn. E = Ke*omega; Kt = Ke; Te = Kt*Ia; Tfric = (omega>=0?1:-1)*(Bm*fabs(omega)+Tf); Td = Te-Tfric; // Result dBeta[0] = (Va-Ra*Ia-E)/La; dBeta[1] = omega; dBeta[2] = 1/Inertia*(Td - TL); Output_Te = Te; }
Works in simOutputs:
Sets the values of output of U Function block.
GetOutputPortData: Gets the data pointer of output port.
extern "C" __declspec(dllexport) void simOutputs(CSys *CS) { double *Yout; Yout = CS->GetOutputPortData(0); Yout[0] = Output_Te; }
Works in Termination Process
The CoLink Solver calls simTerminates when the simulation is quitted. You can use the needed code when the simulation is quitted.
extern "C" __declspec(dllexport) void simTerminates(CSys *CS) { }
20.6.11.1.3. Making U Function DLL
This chapter explains making a DLL file of U Function in Visual Studio environment.
Include File
There is uFunction.h as an included file in <Install Dir>\Toolkits\U_Function\extern\include and it must be needed when you create a DLL file. A class called CSys is defined in the function of uFunction.h. It is the imported class based on the type like __declspec(dllimport) and it is used when you create each function in U Function. The uFunction.h file can be available to Windows 32 bit and Windows 64bit.
Library Files
There is CoLinkSolver_x64.lib in the installed folder. (<Install Dir>\Toolkits\U_Function\extern\lib.) They are the library files which have the information of opened CSys class. When DLL is linked, you should add the library files.
Exported Functions
The below functions are exported as “C” __declspec(dllexport) type in source code.
void simInitializes(CSys *CS)
void simInitialConditions(CSys *CS)
void simUpdateParameters(CSys *CS)
void simJacobians(CSys *CS )
void simDerivatives(CSys *CS)
void simOutputs(CSys *CS)
void simTerminates(CSys *CS)
Building Dll
If you use the U Function sample solution file which is made in Visual Studio in the installed folder (<Install Dir>\Help\U_Function\UFunction_Sample), you can easily use U Function. Also, if you want to create a new project in Visual Studio, you should build it after checking the following information.
Define Project Configuration Type as Dynamic Library (.dll)
Copy the header file and library file to the location which is included the cpp file.
Location of Original File
<Install Dir>\Toolkits\U_Function\extern\include
<Install Dir>\Toolkits\U_Function\extern\lib
Add the uFunction.h file to Head Files.
Enter the following information in Additional Dependencies of Linear.
If Windows is 64bit, enter CoLinkSolver_X64.lib.
Note
If you use the U Function solution file which is made in Visual Studio in the installed folder (<Install Dir>\Help\U_Function\UFunction_Sample), you can easily use U Function.
20.6.11.1.4. Available Member Functions of CSys in U Function
Member function |
Input data |
Output data |
double GetSimTime() |
void |
Double value
|
double GetStartTime() |
Void |
Double value
|
double GetEndTime() |
void |
Double value
|
void SetSampleTime(const double dvalue); |
Double value Sample time |
void |
double GetSampleTime(); |
void |
Double value
|
bool IsSampleHit(); |
Void |
Bool value
|
bool IsSimulationConvergence(); |
Void |
Bool value
|
Member function |
Input data |
Output data |
void SetNumInputPort(int) |
Integer value - Defines the number of input port. |
void |
void SetInputPortSize(int, int); |
Integer value - Defines the port to set the data size. |
void |
Integer value - Defines the size of data of specified port. |
||
int GetNumInputPort(); |
void |
Integer value
|
int GetInputPortSize(int); |
Integer value - Inputs the port number. |
Integer value
|
double* GetInputPortData(int); |
Integer - Inputs the port number. |
Double pointer
|
MemberFunction |
Input data |
Output data |
Void SetNumOutputPort(int) |
Integer value - Defines the number of output port. |
void |
void SetOutputPortSize(int, int); |
Integer value - Defines the port to set the size of data. |
void |
Integer value - Defines the data size of specified port. |
||
int GetNumOutputPort(); |
void |
Integer value
|
int GetOutputPortSize(int); |
Integer value - Outputs the port number. |
Integer value
|
double* GetOutputPortData(int); |
Integer - Outputs the port number. |
Double pointer
|
Member function |
Input data |
Output data |
void SetParameter(const int, const double); |
Integer value - Defines the parameter order. |
Void |
Double value - Defines the parameter Value. |
||
double GetParameter(const int); |
Integer value - Defines the parameter order. |
Double value
|
void SetPassword(char *) |
String pointer - Defines the string for password. |
void |
double GetDoubleFromChVariable(char *name) |
String pointer - Defines the name of ToChvariable block. |
void |
Member Function |
Input Data |
Output Data |
void SetJacobianMethod(const int); |
Integer value - Defines the Jacobian method (1.FDM, 2.Analytical) |
void |
void SetJacobian(const double *); |
Double pointer - Defines the array of Jacobian value. |
void |
Member Function |
Input Data |
Output Data |
void SetNumDiffStates(const int); |
Integer value - Defines the number of differential equation. |
void |
void SetDiffStates(const double*); |
Double pointer - Defines the array of differential states value. |
void |
int GetNumDiffStates(); |
void |
Integer value
|
double* GetDiffStates(void); |
void |
Double pointer
|
double* GetDotDiffStates(void); |
void |
Double pointer
|
Member function |
Input Data |
Output Data |
void SetNumRWork(const int); |
Integer value - Defines the size of creating double array. |
void |
void SetNumIWork(const int); |
Integer value - Defines the size of creating integer array. |
void |
double *GetRWorkPtr(void); |
void |
Double pointer
|
int *GetIWorkPtr(void); |
void |
Integer pointer
|
Member Function |
Input Data |
Output Data |
void WriteToMessageFile(char *string); |
String pointer
|
void |
void SetErrorStatus(char *string); |
String pointer
|
void |
20.6.11.1.5. Example
The example using U Function is modeled by the equation of PMDC motor. (It is compared the result of PMDC in Actuator of CoLink.) The related data is UFunction_Sample.clk in <Install Dir>\Help\U_Function\UFunction_Sample. There is UFunction_Sample.dll in the file path and it is made by the file of <Install Dir>\Help\U_Function\UFunction_Sample in Visual Studio.
The below PMDC block is made by the PMDC block in Actuator and the below UFunction_PMDC is used by the DLL of U Function. Also, UFunction_Sample is made by the motor equation and the rotor equation.
PMDC Equations
The voltage equations of PMDC are as follows.
\(V_a=R_aI_a+L_a\frac{dI_a}{dt}+E\)
- where,
- \({{V}_{a}}\) is the input voltage.\({{R}_{a}}\) is the armature resistance.\({{L}_{a}}\) is the armature inductance.\({{I}_{a}}\) is the armature current.\(E\) is the back electromotive force.
The armature winding is connected to the outside terminal. This block is very similar to a shunt connected DC motor. A back electromotive force (BEMF) by magnet, which is generated between the armature terminals, is proportional to the machine speed.
\(E=K_E\omega_m\)
- where,
- \({{K}_{E}}\) is the voltage (BEMF) constant.\({{\omega }_{m}}\) is the mechanical angular speed.
The electrical torque, which is developed by PMDC motor, is proportional to the armature current \({{I}_{a}}\).
\(T_e=K_EI_a=K_TI_a\)
The torque constant \({{K}_{T}}\) is equal to the voltage (BEMF) constant \({{K}_{E}}\).
When the machine is in generator mode, the sign of torque is positive. In motor mode, the sign of torque is negative.
Rotor Equations
\(\begin{aligned} & J\ddot{\theta }={{T}_{e}} \\ & \left[ \begin{matrix} {\dot{\theta }} \\ {\dot{\omega }} \\ \end{matrix} \right]=\left[ \begin{matrix} 0 & 1 \\ 0 & 0 \\ \end{matrix} \right]\left[ \begin{matrix} \theta \\ \omega \\ \end{matrix} \right]+\left[ \begin{matrix} 0 \\ {}^{{{T}_{e}}}\!\!\diagup\!\!{}_{J}\; \\ \end{matrix} \right] \\ \end{aligned}\)
- where,
- \(J\) is the inertia of rotor.\(\theta\) is the rotational angle.\(\omega\) is the rotational velocity of rotor.
extern "C" __declspec(dllexport) void simInitializes( CSys *CS )
{
// Port Number and Size
// No. eqn
// Sample time
CS->SetNumInputPort(1); → The number of input port is 1.
CS->SetInputPortSize(0,1); →The data size to the first input port is 1.
CS->SetNumOutputPort(1); →The number of out port is 1.
CS->SetOutputPortSize(0,1); →The data size to the first output port is 1.
CS->SetNumDiffStates(3); → The number of different equation is 3.
CS->SetSampleTime(-1.0); → Do not use the sample time.
}
extern "C" __declspec(dllexport) void simInitialConditions( CSys *CS )
{
double* Beta;
int nDiff;
nDiff = CS->GetNumDiffStates();→ Get the number of different equation.
Beta = CS->GetDiffStates();→Get the data pointer of differential state.
for( int i=0 ; i<nDiff ; i++ ) {
Beta[i] = 0.0; → Set the initial value of differential state.
}
// 1:FDM 2:Analytical
CS->SetJacobianMethod(2); → Input the analytical Jacobian.
// For jacobian matrix
CS->SetNumRWork(nDiff*nDiff); →Define the array of Jacobian matrix.
CS->SetNumIWork(0); →Do not use IWork.
CS->WriteToMessageFile("U Function Sample Code.\n"); →Output the string to the message file.
}
// Optional
extern "C" __declspec(dllexport) void simUpdateParameters( CSys *CS )
{
double simtime;
simtime = CS->GetSimTime(); →Get the current simulation time.
//if( simtime > 1.0 ) CS->SetParameter(0,0.2); → Change the first parameter after 1 second in the simulation.
}
extern "C" __declspec(dllexport) void simJacobians( CSys *CS )
{
Size
// Sample time
double Ra,La,Ke,Inertia;
double *Jac;
int nDiff;
Ke = CS->GetParameter(0); →Get the value of first parameter.
Ra = CS->GetParameter(2); →Get the value of third parameter.
La = CS->GetParameter(3); →Get the value of fourth parameter.
Inertia = CS->GetParameter(4); →Get the value of fifth parameter.
Jac = CS->GetRWorkPtr();→Get the pointer of RWork.
Jac[0] = -Ra/La; →Calculate the Jacobian matrix.
Jac[1] = 0.0; →Calculate the Jacobian matrix.
Jac[2] = -Ke/La; →Calculate the Jacobian matrix.
Jac[3] = 0.0; →Calculate the Jacobian matrix.
Jac[4] = 0.0; →Calculate the Jacobian matrix.
Jac[5] = 1.0; →Calculate the Jacobian matrix.
Jac[6] = Ke/Inertia; →Calculate the Jacobian matrix.
Jac[7] = 0.0; →Calculate the Jacobian matrix.
Jac[8] = 0.0; →Calculate the Jacobian matrix.
CS->SetJacobian(Jac); →Defines the Jacobian matrix.
}
// Optional
extern "C" __declspec(dllexport) void simDerivatives( CSys *CS )
{
double Ra,La,Ke,Kt,angle,omega,Ia,Va,E,Te,Tfric,Td;
double Inertia,Bm,Tf,TL;
double simtime;
int npole;
double *Uin;
double *dBeta,*Beta;
// Parameter
Ke = CS->GetParameter(0); →Get the value of first parameter.
npole = (int) CS->GetParameter(1); →Get the value of second parameter.
Ra = CS->GetParameter(2); →Get the value of third parameter.
La = CS->GetParameter(3); →Get the value of fourth parameter.
Inertia = CS->GetParameter(4); →Get the value of fifth parameter.
Bm = CS->GetParameter(5); →Get the value of sixth parameter.
Tf = CS->GetParameter(6); →Get the value of seventh parameter.
// Input
Uin = CS->GetInputPortData(0); →Get the value of input port.
// Diff eqn.
Beta = CS->GetDiffStates(); →Get the pointer of differential state.
dBeta = CS->GetDotDiffStates(); →Get the pointer to the differential value of differential state.
TL = 0.0;
Va = Uin[0];
Ia = Beta[0];
angle = Beta[1];
omega = Beta[2];
// Motor eqn.
E = Ke*omega;
Kt = Ke;
Te = Kt*Ia;
Tfric = (omega>=0?1:-1)*(Bm*fabs(omega)+Tf);
Td = Te-Tfric;
// Result
dBeta[0] = (Va-Ra*Ia-E)/La; →Set the differential value of differential state by the equation.
dBeta[1] = omega; →Set the differential value of differential state by the equation.
dBeta[2] = 1/Inertia*(Td - TL); →Set the differential value of differential state by the equation.
Output_Te = Te; →Set the differential value of differential state by the equation.
}
extern "C" __declspec(dllexport) void simOutputs( CSys *CS )
{
double *Yout;
Yout = CS->GetOutputPortData(0); →Get the pointer of output.
Yout[0] = Output_Te; →Output Te.
}
extern "C" __declspec(dllexport) void simTerminates( CSys *CS )
{
}