⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scsb_sfun.c

📁 一个matlab的将军模型
💻 C
📖 第 1 页 / 共 3 页
字号:
     there is no reset signal.  Note that the sampled-data clock input is now the first
     input port after the discrete-location inputs. */
  if (use_reset)
    reset_port = sd_port + 1;
  else
    reset_port = -1;
  
  ninput = (nu > 0) + use_sd + use_reset;
   
  if (!ssSetNumInputPorts(S,ninput)) return;

  /* Initialize size and direct feedthrough status for u port. */
  if (u_port != -1) {
    ssSetInputPortWidth(S,u_port,nu);
    ssSetInputPortDirectFeedThrough(S,u_port,0);
  }

  /* Initialize size and direct feedthrough status for sampled-data clock input port. */
  if (use_sd) {
    ssSetInputPortWidth(S,sd_port,1);
    ssSetInputPortDirectFeedThrough(S,sd_port,0);
  }

  /* Initialize size, type, and direct feedthrough status for reset port. */
  if (reset_port != -1) {
    ssSetInputPortWidth(S,reset_port,1);
    ssSetInputPortDirectFeedThrough(S,reset_port,0);
   
    ssSetInputPortDataType(S,reset_port,DYNAMICALLY_TYPED);
  }

  /* Compute port index for the state output port x. Port index is -1
     if the output x is not available. */
  if ((nx > 0)||(nz>0))
    x_port = 0;
  else
    x_port = -1;

  noutput = (nx > 0)||(nz > 0);

  if (!ssSetNumOutputPorts(S,noutput)) return;
  
  /* Initialize the size for the x port.  If sampled-data analysis is used,
  then make the output the continuous-time state, the controller output, and 
  the discrete-time controller state.*/
  if (x_port != -1) {
    if (use_sd)
        ssSetOutputPortWidth(S,x_port,nx+nz);
    else
        ssSetOutputPortWidth(S,x_port,nx);
   }
        
  ssSetNumSampleTimes(S,1);
  ssSetNumRWork(S,0);
  ssSetNumDWork(S,0);
  ssSetNumIWork(S,NIWORK);
  ssSetNumPWork(S,NPWORK);

  
  zero_crossings = 0;
  if (use_reset) {
    /* Declare that we will track one zero crossing signal, namely the
       reset signal. */
    zero_crossings = 1;   
  }
  if (use_sd) {
    zero_crossings++;
  }
  ssSetNumNonsampledZCs(S,zero_crossings);  
  
}


/* Function: mdlInitializeSampleTimes =========================================
 * Abstract:
 *
 *    This function is used to specify the sample time(s) for your S-function.
 *    You must register the same number of sample times as specified in
 *    ssSetNumSampleTimes. If you specify that you have no sample times, then
 *    the S-function is assumed to have one inherited sample time.
 *
 *    The sample times are specified as pairs "[sample_time, offset_time]"
 *    via the following macros:
 *      ssSetSampleTime(S, sampleTimePairIndex, sample_time)
 *      ssSetOffsetTime(S, offsetTimePairIndex, offset_time)
 *    Where sampleTimePairIndex starts at 0.
 *
 *    The valid sample time pairs are (upper case values are macros defined
 *    in simstruc.h):
 *
 *      [CONTINUOUS_SAMPLE_TIME,  0.0                       ]
 *      [CONTINUOUS_SAMPLE_TIME,  FIXED_IN_MINOR_STEP_OFFSET]
 *      [discrete_sample_period,  offset                    ]
 *      [VARIABLE_SAMPLE_TIME  ,  0.0                       ]
 *
 *    Alternatively, you can specify that the sample time is inherited from the
 *    driving block in which case the S-function can have only one sample time
 *    pair:
 *
 *      [INHERITED_SAMPLE_TIME,  0.0                       ]
 *    or
 *      [INHERITED_SAMPLE_TIME,  FIXED_IN_MINOR_STEP_OFFSET]
 *
 *    The following guidelines may help aid in specifying sample times:
 *
 *      o A continuous function that changes during minor integration steps
 *        should register the [CONTINUOUS_SAMPLE_TIME, 0.0] sample time.
 *      o A continuous function that does not change during minor integration
 *        steps should register the
 *              [CONTINUOUS_SAMPLE_TIME, FIXED_IN_MINOR_STEP_OFFSET]
 *        sample time.
 *      o A discrete function that changes at a specified rate should register
 *        the discrete sample time pair
 *              [discrete_sample_period, offset]
 *        where
 *              discrete_sample_period > 0.0 and
 *              0.0 <= offset < discrete_sample_period
 *      o A discrete function that changes at a variable rate should
 *        register the variable step discrete [VARIABLE_SAMPLE_TIME, 0.0]
 *        sample time. The mdlGetTimeOfNextVarHit function is called to get
 *        the time of the next sample hit for the variable step discrete task.
 *        Note, the VARIABLE_SAMPLE_TIME can be used with variable step
 *        solvers only.
 *      o Discrete blocks which can operate in triggered subsystems.  For your 
 *        block to operate correctly in a triggered subsystem or a periodic 
 *        system it must register [INHERITED_SAMPLE_TIME, 0.0]. In a triggered
 *        subsystem after sample times have been propagated throughout the
 *        block diagram, the assigned sample time to the block will be 
 *        [INHERITED_SAMPLE_TIME, INHERITED_SAMPLE_TIME]. Typically discrete
 *        blocks which can be periodic or reside within triggered subsystems
 *        need to register the inherited sample time and the option
 *        SS_DISALLOW_CONSTANT_SAMPLE_TIME. Then in mdlSetWorkWidths, they
 *        need to verify that they were assigned a discrete or triggered
 *        sample time. To do this:
 *          mdlSetWorkWidths:
 *            if (ssGetSampleTime(S, 0) == CONTINUOUS_SAMPLE_TIME) {
 *              ssSetErrorStatus(S, "This block cannot be assigned a "
 *                               "continuous sample time");
 *            }
 *
 *    If your function has no intrinsic sample time, then you should indicate
 *    that your sample time is inherited according to the following guidelines:
 *
 *      o A function that changes as its input changes, even during minor
 *        integration steps should register the [INHERITED_SAMPLE_TIME, 0.0]
 *        sample time.
 *      o A function that changes as its input changes, but doesn't change
 *        during minor integration steps (i.e., held during minor steps) should
 *        register the [INHERITED_SAMPLE_TIME, FIXED_IN_MINOR_STEP_OFFSET]
 *        sample time.
 *
 *    To check for a sample hit during execution (in mdlOutputs or mdlUpdate),
 *    you should use the ssIsSampleHit or ssIsContinuousTask macros.
 *    For example, if your first sample time is continuous, then you
 *    used the following code-fragment to check for a sample hit. Note,
 *    you would get incorrect results if you used ssIsSampleHit(S,0,tid).
 *        if (ssIsContinuousTask(S,tid)) {
 *        }
 *    If say, you wanted to determine if the third (discrete) task has a hit,
 *    then you would use the following code-fragment:
 *        if (ssIsSampleHit(S,2,tid) {
 *        }
 *
 */
static void mdlInitializeSampleTimes(SimStruct *S)
{
  /* Specify that we have a continuous sample time. */
  ssSetSampleTime(S,0,CONTINUOUS_SAMPLE_TIME);
  ssSetOffsetTime(S,0,0.0);
}


#define MDL_START  /* Change to #undef to remove function */
/* Function: mdlStart =======================================================
 * Abstract:
 *    This function is called once at start of model execution. If you
 *    have states that should be initialized once, this is the place
 *    to do it.
 */
static void mdlStart(SimStruct *S)
{
  int_T nx,nu,nz,nup,use_reset,u_port,reset_port,use_param,use_sd,sd_port;
  real_T *z_and_u,*temp,zero,*cont_states;  
  
  /* Assume that all parameters have been checked previously. */
  use_reset = (int_T) *mxGetPr(ssGetSFcnParam(S,PARAM_USE_RESET));
  use_param = (int_T) *mxGetPr(ssGetSFcnParam(S,PARAM_USE_PARAM));
  use_sd = (int_T) *mxGetPr(ssGetSFcnParam(S,PARAM_USE_SD)); 
  nx = (int_T) *mxGetPr(ssGetSFcnParam(S,PARAM_NX));
  if (use_sd) {
    nup = (int_T) *mxGetPr(ssGetSFcnParam(S,PARAM_NUP));
    nz = (int_T) *mxGetPr(ssGetSFcnParam(S,PARAM_NZ));
  }
  nu = (int_T) *mxGetPr(ssGetSFcnParam(S,PARAM_NU));
  
  
  /* Compute port index for the input u. Port index is -1 if there is
     no input signal u. */
  if ((nu > 0))
    u_port = 0;
  else
    u_port = -1;
  
  /* Compute port index for the SD clock input.*/  
  if (use_sd)
    sd_port = u_port + 1;
  else
    sd_port = u_port;  
    
  /* Compute port index for the reset signal. Port index is -1 if
     there is no reset signal.  Note that the sampled-data clock input is now the first
     input port after the discrete-location inputs. */
  if (use_reset)
    reset_port = sd_port + 1;
  else
    reset_port = -1;
  
  /* Store port indices in the integer work vector so that we don't
     have to compute them again. */
  ssSetIWorkValue(S,IWORK_U_PORT,u_port);
  ssSetIWorkValue(S,IWORK_RESET_PORT,reset_port);
  ssSetIWorkValue(S,IWORK_USE_RESET,use_reset);
  ssSetIWorkValue(S,IWORK_USE_PARAM,use_param);
  ssSetIWorkValue(S,IWORK_USE_SD,use_sd);
  ssSetIWorkValue(S,IWORK_SD_PORT,sd_port);
  
  
  /* Initialize pointer work vector and allocate some mxArrays to
     store arguments for the SCSB wrapper function. */
  ssSetPWorkValue(S,PWORK_X_DOT,calloc((nx+1),sizeof(real_T)));
  ssSetPWorkValue(S,PWORK_X_RESET,calloc(nx,sizeof(real_T)));
  if (use_sd){
    ssSetPWorkValue(S,PWORK_Z,calloc(nz,sizeof(real_T)));
    ssSetPWorkValue(S,PWORK_U_OUT,calloc(nup,sizeof(real_T)));
  }
    
  /* Initialize the continuous state vector to initial values
     specified in S-function parameter. */
  if (nx>0){
  nx = ssGetNumContStates(S);
  memcpy(ssGetContStates(S),mxGetPr(ssGetSFcnParam(S,PARAM_X0)),
         (nx-1)*sizeof(real_T));
  zero=0;
  cont_states = ssGetContStates(S);
  memcpy(&cont_states[nx-1],&zero,
         sizeof(real_T));
         }
 
  /* If sampled-data analysis is used, put the initial controller
     states in the first part of the discrete-state vector.  Then 
     compute the output of the controller and put those values in the
     second part of the discrete-state vector.*/
  if (use_sd) {
    temp = mxGetPr(ssGetSFcnParam(S,PARAM_X0));
    if (nx>0){
    memcpy(ssGetDiscStates(S),&temp[nx-1],
         (nz)*sizeof(real_T));
    } else {
    memcpy(ssGetDiscStates(S),temp,
         (nz)*sizeof(real_T));
    }
    computeDerivativeAndReset(S);
    z_and_u = ssGetDiscStates(S);

    if (nup>0){
    memcpy(&z_and_u[nz],ssGetPWorkValue(S,PWORK_U_OUT),nup*sizeof(real_T)); 
    } 
  }
  
  
}


/* Function: mdlOutputs =======================================================
 * Abstract:
 *    In this function, you compute the outputs of your S-function
 *    block. Generally outputs are placed in the output vector(s),
 *    ssGetOutputPortSignal.
 */
static void mdlOutputs(SimStruct *S,int_T tid)
{
  
  real_T *cont_out,*disc_out,use_sd;
  int_T nx,nz;  
  
  use_sd = (int_T) *mxGetPr(ssGetSFcnParam(S,PARAM_USE_SD)); 
  
  nx = ssGetNumContStates(S);
  if (use_sd){
      nz = (int_T) *mxGetPr(ssGetSFcnParam(S,PARAM_NZ));
  }
  
  /* y = x, copy state vector x to output vector y. */
  cont_out = ssGetOutputPortRealSignal(S,0);
  memcpy(cont_out,ssGetContStates(S),
         (ssGetNumContStates(S)-1)*sizeof(real_T));
  if (use_sd){
    disc_out = &cont_out[nx-1];
    memcpy(disc_out,ssGetDiscStates(S),
             nz*sizeof(real_T));
  }
}

#define MDL_UPDATE  /* Change to #undef to remove function */
#if defined(MDL_UPDATE)
/* Function: mdlUpdate ======================================================
 * Abstract:
 *    This function is called once for every major integration time step.
 *    Discrete states are typically updated here, but this function is useful
 *    for performing any tasks that should only take place once per
 *    integration step.
 */
static void mdlUpdate(SimStruct *S,int_T tid)
{
  int_T i,j,nx,nz,nup,use_reset,reset_value,use_sd,sd_port,reset_port,clock_value,nAR;
  real_T prod_i;
  real_T *x,*CI,*dI,*z_and_u;
  mxArray *mxCI;
  InputPtrsType      u;
  DTypeId test;



  nx = ssGetNumContStates(S);
  x = ssGetContStates(S);

  /* Check if state reset should be applied. */

  use_reset = ssGetIWorkValue(S,IWORK_USE_RESET);
  if (use_reset) {
    reset_port = ssGetIWorkValue(S,IWORK_RESET_PORT);
    
    /* This code was added by JPK 2/2004.  The purpose is to 
     * determine what the data type of the reset input is and 
     * to handle it accordingly.*/
    test= ssGetInputPortDataType(S,reset_port);
    if (test==8) {
        /* Boolean data type case */
        u     = ssGetInputPortSignalPtrs(S,reset_port);
        if((**(InputBooleanPtrsType) u)==1){        
            reset_value=1;
        }else{
            reset_value=0;
        }      
    } else {
       /* Double data type case */
        if(**ssGetInputPortRealSignalPtrs(S,reset_port)==1){        
            reset_value=1;
        }else{
            reset_value=0;
        } 
    }    
    
    if (ssGetIWorkValue(S,IWORK_LAST_RESET) != reset_value) {
      /* If the reset signal changes, record the new reset signal value. */
      ssSetIWorkValue(S,IWORK_LAST_RESET,reset_value);
      /* Apply state reset. */
      computeDerivativeAndReset(S);
      memcpy(x,ssGetPWorkValue(S,PWORK_X_RESET),(nx-1)*sizeof(real_T));
      /* Update block output since state has changed. */
      mdlOutputs(S,tid);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -