Сконфигурируйте варианты размерности для блоков s-function

Чтобы сконфигурировать символьные размерности для блоков s-function, можно использовать следующие функции C/C + +. Можно сконфигурировать S-функции для поддержки прямого распространения, обратного распространения или прямого и обратного распространения символических размерностей во время симуляции.

Многие из этих функций возвращают переменную SymbDimsId. A SymbDimsId является уникальным целым значением. Это значение соответствует каждой символьной спецификации размерности, которую вы создаете или является результатом математической операции, которую вы выполняете с символьными размерностями.

Функции C/C + + SЦель

ssSetSymbolicDimsSupport

Задайте, поддерживает ли S-функция символьные размерности.

mdlSetInputPortSymbolicDimensions

Задайте символические размерности входного порта и то, как эти размерности распространяются вперед.

mdlSetOutputPortSymbolicDimensions

Задайте символические размерности выходного порта и способ распространения этих размерностей назад.

ssRegisterSymbolicDimsExpr

Создайте SymbDimsId из строки выражения (aExpr). Строка выражения должна сформировать допустимый синтаксис в C.

ssRegisterSymbolicDims

Создайте SymbDimsId из вектора SymbDimsIdс.

ssRegisterSymbolicDimsString

Создайте SymbDimsId из строки идентификатора (aString).

ssRegisterSymbolicDimsIntValue

Создайте SymbDimsId от целого значения (aIntValue)

ssRegisterSymbolicDimsPlus

Создайте SymbDimsId путем добавления двух символьных размерностей.

ssRegisterSymbolicDimsMinus

Создайте SymbDimsId путем вычитания двух символьных размерностей.

ssRegisterSymbolicDimsMultiply

Создайте SymbDimsId путем умножения двух символьных размерностей.

ssRegisterSymbolicDimsDivide

Создайте SymbDimsId путем деления двух символьных размерностей.

ssGetNumSymbolicDims

Получите количество размерностей для SymbDimsId.

ssGetSymbolicDim

Получите SymbDimsId из вектора SymbDimsIdс.

ssSetInputPortSymbolicDimsId

Установите предварительно скомпилированный SymbDimsId порта входа. Вы можете вызвать эту функцию из mdlInitializeSizes функция.

ssGetCompInputPortSymbolicDimsId

Получите скомпилированный SymbDimsId порта входа.

ssSetCompInputPortSymbolicDimsId

Установите скомпилированный SymbDimsId порта входа.

ssSetOutputPortSymbolicDimsId

Установите предварительно скомпилированный SymbDimsId порта выхода. Вы можете вызвать эту функцию из mdlInitializeSizes функция.

ssGetCompOutputPortSymbolicDimsId

Получите скомпилированный SymbDimsId порта выхода.

ssSetCompOutputPortSymbolicDimsId

Установите скомпилированный SymbDimsId порта выхода.

ssSetCompDWorkSymbolicDimsId

Установите скомпилированный SymbDimsId индекса работающего типа данных блока (DWork) вектор.

S-функция, которая поддерживает прямое распространение символьных размерностей

Модель ex_msymbdims_sfcn_one содержит S-функцию, которая вычитает символическую размерность B от символьной входной размерности, A + B. Он не поддерживает распространение символьных размерностей назад, потому что скомпилированные символьные размерности input ports не заданы. Символьные размерности заданы для output port, поэтому происходит прямое распространение.

После симуляции модель показывает распространенные размерности.

Model with an S-function and symbolic dimensions

The sfun_symbdims_sfcn_one.c файл содержит этот код.

#define S_FUNCTION_NAME  sfun_symbdims_sfcn_one
#define S_FUNCTION_LEVEL 2

#include "simstruc.h"

#include <assert.h>

/* Function: mdlInitializeSizes ===============================================
 * Abstract:
 *   Setup sizes of the various vectors.
 */
static void mdlInitializeSizes(SimStruct *S)
{
    ssSetNumSFcnParams(S, 0); /* Number of expected parameters */
    
    ssSetNumContStates(S, 0);
    ssSetNumDiscStates(S, 0);

    if (!ssSetNumInputPorts(S, 1)) return;
    ssSetInputPortDirectFeedThrough(S, 0, 1);
    ssSetInputPortDimensionInfo(S, 0, DYNAMIC_DIMENSION);
    ssSetInputPortRequiredContiguous(S, 0, 1);
    
    if (!ssSetNumOutputPorts(S,1)) return;
    ssSetOutputPortDimensionInfo(S, 0, DYNAMIC_DIMENSION);   
    ssSetNumSampleTimes(S, 1);

    ssSetNumRWork(S, 0);
    ssSetNumIWork(S, 0);
    ssSetNumPWork(S, 0);

    ssSetNumModes(S, 0);
    ssSetNumNonsampledZCs( S, 0);
    
    ssAllowSignalsWithMoreThan2D(S);
    
    ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE);
    
    ssSetSymbolicDimsSupport(S, true);
}


/*If underspecified for propagation, say i/o are scalars.*/
#if defined(MATLAB_MEX_FILE)
#define MDL_SET_DEFAULT_PORT_DIMENSION_INFO
static void mdlSetDefaultPortDimensionInfo(SimStruct *S)
{
    if( (ssGetOutputPortWidth(S, 0) == DYNAMICALLY_SIZED) 
        && (ssGetInputPortWidth(S, 0) == DYNAMICALLY_SIZED) ) {
        ssSetOutputPortMatrixDimensions(S, 0, 1, 1 );
    }
}
#endif

#if defined(MATLAB_MEX_FILE)
#define MDL_SET_INPUT_PORT_SYMBOLIC_DIMENSIONS
static void mdlSetInputPortSymbolicDimensions(SimStruct* S, 
   int_T portIndex, SymbDimsId symbDimsId)
{
    assert(0 == portIndex);
    // Set the compiled input symbolic dimension.
    ssSetCompInputPortSymbolicDimsId(S,  portIndex, symbDimsId);
	// Register "B" and get its symbolic dimensions id.
    const SymbDimsId symbolId = ssRegisterSymbolicDimsString(S, "B");
	// Subtract "B" from the input symbolic dimension.
    const SymbDimsId outputDimsId = 
       ssRegisterSymbolicDimsMinus(S, symbDimsId, symbolId);
    ssSetCompOutputPortSymbolicDimsId(S, portIndex, outputDimsId);
}
#endif

#if defined(MATLAB_MEX_FILE)
#define MDL_SET_OUTPUT_PORT_SYMBOLIC_DIMENSIONS
static void mdlSetOutputPortSymbolicDimensions(SimStruct *S, 
   int_T portIndex, SymbDimsId symbDimsId)
{
    assert(0 == portIndex);
   // The input dimensions are not set, so this S-function only
	// supports forward propagation.
    ssSetCompOutputPortSymbolicDimsId(S, portIndex, symbDimsId);
}
#endif

/* Function: mdlInitializeSampleTimes =========================================
 * Abstract:
 *    Specify that we inherit our sample time from the driving block.
 *    However, we don't execute in minor steps.
 */
static void mdlInitializeSampleTimes(SimStruct *S)
{
    ssSetSampleTime(S, 0, INHERITED_SAMPLE_TIME);
    ssSetOffsetTime(S, 0, 0.0);
    ssSetModelReferenceSampleTimeDefaultInheritance(S);    
}
/* Function: mdlOutputs =======================================================
 * Abstract:
 *    y=u';
 */
static void mdlOutputs(SimStruct *S, int_T tid)
{
}

/* Function: mdlTerminate =====================================================
 * Abstract:
 *    No termination needed, but we are required to have this routine.
 */
static void mdlTerminate(SimStruct *S)
{
    UNUSED_ARG(S); /* unused input argument */
}

#ifdef  MATLAB_MEX_FILE    /* Is this file being compiled as a MEX-file? */
#include "simulink.c"      /* MEX-file interface mechanism */
#else
#include "cg_sfun.h"       /* Code generation registration function */
#endif

The Simulink.Parameter объекты A и B содержат эти определения.

A = Simulink.Parameter;
A.DataType = 'int32';
A.Value = 6;
A.Min=5;
A.Max=7;
A.CoderInfo.StorageClass = 'Custom';
A.CoderInfo.CustomStorageClass = 'ImportedDefine';
A.CoderInfo.CustomAttributes.HeaderFile = 'ImportedDefinitions.h';

B = Simulink.Parameter;
B.DataType = 'int32';
B.Value = 10;
B.Min=9;
B.Max=11;
B.CoderInfo.StorageClass = 'Custom';
B.CoderInfo.CustomStorageClass = 'ImportedDefine';
B.CoderInfo.CustomAttributes.HeaderFile = 'ImportedDefinitions.h';
The ImportedDefinitions заголовочный файл содержит этот код.
#ifndef _IMPORTEDDEFINITIONS_H_
#define _IMPORTEDDEFINITIONS_H_
#define A 6
#define B 10
#endif

В диалоговом окне Параметров конфигурации панель Custom Code содержит #include оператор.

#include "ImportedDefinitions.h"

The sfun_symbdims_sfcn_one S-функция встроена, поэтому TLC файл с этим кодом должен присутствовать в пути с моделью и другими вспомогательными файлами.

%implements "sfun_symbdims_sfcn_two" "C"

%function BlockInstanceSetup(block, system) void
%endfunction

%% Function: BlockOutputSignal =================================================
%function BlockOutputSignal(block,system,portIdx,ucv,lcv,idx,retType) void
%endfunction

%% Function: Outputs ===========================================================
%%
%function Outputs(block, system) Output


  %assign rollVars = ["U", "Y"]
  %roll idx = RollRegions, lcv = RollThreshold, block, "Roller", rollVars
    %%
    %assign u  = LibBlockInputSignal( 0, "", lcv, idx)
    %assign y  = LibBlockOutputSignal(0, "", lcv, idx)
                                                           
    %<y> = %<u>;
                                                      
  %endroll

%endfunction %% Outputs

Чтобы сгенерировать MEX-функцию, в командной строке введите эту команду:

mex sfun_symbdims_sfcn_one.c

Сгенерируйте код для модели. The ex_msymbdims_sfcn_one_step функция содержит этот код. Код S-функции установлен в строке.

/* Model step function */
void ex_msymbdims_sfcn_one_step(void)
{
  int32_T i;

  /* Gain: '<Root>/Gain' incorporates:
   *  Inport: '<Root>/In1'
   */
  for (i = 0; i < A; i++) {
    ex_msymbdims_sfcn_one_B.MatrixConcatenate[i] = 2.0 *
      ex_msymbdims_sfcn_one_U.In1[i];
  }

  /* End of Gain: '<Root>/Gain' */

  /* Gain: '<Root>/Gain2' incorporates:
   *  Inport: '<Root>/In2'
   */
  for (i = 0; i < B; i++) {
    ex_msymbdims_sfcn_one_B.MatrixConcatenate[A + i] = 2.0 *
      ex_msymbdims_sfcn_one_U.In2[i];
  }

  /* End of Gain: '<Root>/Gain2' */

  /* S-Function (sfun_symbdims_sfcn_one): '<Root>/Minus' incorporates:
   *  Outport: '<Root>/Out7'
   */
  {
    int_T i1;
    const real_T *u0 = &ex_msymbdims_sfcn_one_B.MatrixConcatenate[0];
    real_T *y0 = &ex_msymbdims_sfcn_one_Y.Out7[0];
    for (i1=0; i1 < ((A + B)); i1++) {
      y0[i1] = u0[i1];
    }
  }
}

S-функция, которая поддерживает прямое и обратное распространение символьных размерностей

Эта S-функция транспонирует две символьные размерности. Он поддерживает прямое и обратное распространение символьных размерностей, потому что скомпилированная символьная размерность как входного, так и выхода портов задана.

static void mdlInitializeSizes(SimStruct *S)
{
     // Enable symbolic dimensions for the s-function.
     ssSetSymbolicDimsSupport(S, true);
}

#if defined(MATLAB_MEX_FILE)
#define MDL_SET_INPUT_PORT_SYMBOLIC_DIMENSIONS
static void mdlSetInputPortSymbolicDimensions(SimStruct* S, 
   int_T portIndex, SymbDimsId symbDimsId)
{
    assert(0 == portIndex);
    
    ssSetCompInputPortSymbolicDimsId(S,  portIndex, symbDimsId);
    
    assert(2U == ssGetNumSymbolicDims(S, symbDimsId));
    
    if (SL_INHERIT == 
        ssGetCompOutputPortSymbolicDimsId(S, portIndex)) {

        const SymbDimsId idVec[] = {
            ssGetSymbolicDim(S, symbDimsId, 1),
            ssGetSymbolicDim(S, symbDimsId, 0)};
        // Register the transposed dimensions.
       // Set the output symbolic dimension to the resulting id.
  const SymbDimsId outputDimsId = 
            ssRegisterSymbolicDims(S, idVec, 2U);

        ssSetCompOutputPortSymbolicDimsId(S, portIndex, 
           outputDimsId);
    }
}
#endif

#if defined(MATLAB_MEX_FILE)
#define MDL_SET_OUTPUT_PORT_SYMBOLIC_DIMENSIONS
static void mdlSetOutputPortSymbolicDimensions(SimStruct *S, 
    int_T portIndex, SymbDimsId symbDimsId)
{
    assert(0 == portIndex);
    ssSetCompOutputPortSymbolicDimsId(S, portIndex, symbDimsId);

    assert(2U == ssGetNumSymbolicDims(S, symbDimsId));
    
    if (SL_INHERIT == 
        ssGetCompInputPortSymbolicDimsId(S, portIndex)) {

        const SymbDimsId idVec[] = {
            ssGetSymbolicDim(S, symbDimsId, 1),
            ssGetSymbolicDim(S, symbDimsId, 0)};
        const SymbDimsId inputDimsId = 
            ssRegisterSymbolicDims(S, idVec, 2U);
        // Register the transposed dimensions.
       // Set the input symbolic dimension to the resulting id.
        ssSetCompInputPortSymbolicDimsId(S, portIndex, inputDimsId);
    }
}
#endif

Похожие темы