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

../_images/image241.png

Figure 20.167 U Function dialog box

Table 20.101 Parameter

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.

Table 20.102 Functions

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.

  1. Define Project Configuration Type as Dynamic Library (.dll)

../_images/image242.png

Figure 20.168 UFunction_Sample property Pages dialog box

  1. 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

        ../_images/image243.png

        Figure 20.169 Copying the Header File and Library File

  2. Add the uFunction.h file to Head Files.

    ../_images/image244.png

    Figure 20.170 Adding the uFunction.h file

  3. Enter the following information in Additional Dependencies of Linear.

    • If Windows is 64bit, enter CoLinkSolver_X64.lib.

    ../_images/image245.png

    Figure 20.171 Setting the Additional Dependencies

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

Table 20.103 Time Functions

Member function

Input data

Output data

double GetSimTime()

void

Double value

  • Defines the current simulation time.

double GetStartTime()

Void

Double value

  • Defines the start time of simulation.

double GetEndTime()

void

Double value

  • Defines the end time of simulation.

void SetSampleTime(const double dvalue);

Double value Sample time

void

double GetSampleTime();

void

Double value

  • Defines the sample time.

bool IsSampleHit();

Void

Bool value

  • If the hit is occurred as the sample time, it is true.

  • If the hit is not occurred as the sample time, it is false.

bool IsSimulationConvergence();

Void

Bool value

  • If the simulation loop is called after the convergence, it is true.

  • If the simulation loop is called during the convergence, it is false.

Table 20.104 Input Port Functions

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

  • Defines the number of Input port.

int GetInputPortSize(int);

Integer value - Inputs the port number.

Integer value

  • Defines the size of input data.

double* GetInputPortData(int);

Integer - Inputs the port number.

Double pointer

  • Inputs the data.

Table 20.105 Output Port Functions

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

  • Defines the number of output port.

int GetOutputPortSize(int);

Integer value - Outputs the port number.

Integer value

  • Defines the size of output data.

double* GetOutputPortData(int);

Integer - Outputs the port number.

Double pointer

  • Outputs the data.

Table 20.106 Parameter Functions

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

  • Defines the value of parameter.

void SetPassword(char *)

String pointer - Defines the string for password.

void

double GetDoubleFromChVariable(char *name)

String pointer - Defines the name of ToChvariable block.

void

Table 20.107 Parameter Functions

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

Table 20.108 Differential Equation Functions

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

  • Defines the number of differential equation

double* GetDiffStates(void);

void

Double pointer

  • Defines the array differential states value.

double* GetDotDiffStates(void);

void

Double pointer

  • Derivatives the array of differential states value.

Table 20.109 Work Array Functions

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

  • Defines the array of RWork.

int *GetIWorkPtr(void);

void

Integer pointer

  • Defines the array of IWork.

Table 20.110 Message functions

Member Function

Input Data

Output Data

void WriteToMessageFile(char *string);

String pointer

  • Defines the string to output the message file.

void

void SetErrorStatus(char *string);

String pointer

  • Defines the error string to output the message file.

  • If the function is called, the simulation is quitted.

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.

../_images/image246.png

Figure 20.172 PMDC Block & UFunction_Sample block

../_images/image247.png

Figure 20.173 PMDC dialog box

../_images/image241.png

Figure 20.174 U Function dialog box

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 )
{

}