c-script

Start Function

这个函数只在仿真开始的时候调用。在这里对离散和连续状态变量进行初始化(使用宏ContState(i) and DiscState(i))。

Output Function

在主要和次要步长都会调用这个函数,用于更新模块的输出信号。

宏InputSignal(i, j)对应模块的输入,宏OutputSignal(i, j)对应模块的输出,宏CurrentTime对应当前的仿真时间。

输出函数可以在同一个主要时间步长内多次调用,并且在次要时间步长中,时间可能会在函数调用之间来回跳转。每个主要时间步长应恰好执行一次的代码应放在 update 函数中。

Update Function

如果模块具有离散状态变量,则在处理完所有模块的输出函数后,在主要时间步长内调用一次更新函数。应使用 宏 DiscState更新离散状态变量。

Derivative Function

如果模块具有连续状态变量,则在求解器的积分循环期间调用导数函数。在此调用期间,应使用 宏ContDeriv 更新连续状态导数。

Terminate Function

终止函数在仿真结束时调用 - 无论是否已达到仿真停止时间、仿真是否已以交互方式停止或是否发生错误。

使用此函数可以释放在启动功能期间可能分配的任何资源(例如文件句柄、内存等)。

Code Declarations

此代码部分用于全局声明和定义(即 C-Script 块范围内的全局声明和定义)。这里可以包含标准库头文件(例如 math.h 或 stdio.h),并定义要在 C-Script 函数中使用的宏、静态变量和辅助函数。

还可以包括外部源文件。包含模型文件的目录会自动添加到包含的搜索路径中,因此您可以指定相对于模型文件的源文件路径。

对不连续性进行建模

1 如果不连续性或事件发生的时间不是先验已知的,而是取决于模块输入和/或状态,则必须定义一个或多个过零信号,以帮助求解器定位事件。否则可能会导致活动时间抖动。

2 在次要时间步长中,连续状态导数和输出信号必须是连续且平滑的函数。如果不遵守这一点,可能会导致严重的数值积分误差。

Defining Zero-crossing Functions

1 要定义过零信号,请在“C-Script”对话框的“设置”窗格中注册所需数量的信号。

2 在输出函数中,使用宏 ZCSignal(i) 为各个过零信号分配值,例如,根据模块输入或状态或当前仿真时间。

3 求解器持续监控所有模块的所有过零信号。如果任何一个信号在当前积分步骤中改变其符号,则步长会减小,以便下一个主要时间步长发生在第一个过零之后。

例如,要对一个比较器进行建模,该比较器在输入超过阈值 1 时必须改变其输出,您应该定义以下过零信号:

ZCSignal(0) = InputSignal(0, 0) - 1.;
如果没有过零信号的帮助,求解器可能会在输入信号为 0.9 时一步一步地进行,而在输入信号已经增加到 1.23 时进行下一步,这样 C-Script 模块就会为时已晚地更改其输出。使用过零信号,并且输入信号是连续的,求解器将能够调整步长,以便 C-Script 输出在正确的时间发生变化。

如果过零信号仅取决于仿真时间,即如果事件时间是先验已知的,则建议改用离散变量采样时间和 宏NextSampleHit 。

Keeping Functions Continuous During Minor Time Steps

C-Script 模块的输出信号可以用作积分器的输入信号,因此可能成为连续状态变量的导数。因此,输出信号也应描述为分段平滑函数。

回到上面的比较器示例,完整的输出函数代码应如下所示:

if (IsMajorStep)  
{  
  if (InputSignal(0, 0) >= 1.)  
    OutputSignal(0, 0) = 1.;  
  else  
    OutputSignal(0, 0) = 0.;  
}  
 
ZCSignal(0) = InputSignal(0, 0) - 1.;

if (IsMajorStep) 使得输出信号只在MajorStep中改变。在积分循环期间,无论输入信号在这些次要时间步长中假设的值如何,它都保持不变。但是,在求解器的事件检测循环期间,过零信号也会以较小的时间步长更新。

Sample Time

C-Script 模块可以对连续系统、离散系统甚至同时具有连续和离散属性的混合系统进行建模。根据要建模的系统类型,您需要在“C-Script”对话框的“设置”窗格中指定适当的采样时间。采样时间决定了求解器在哪些时间步(以及在哪些阶段)调用不同的 C-Script 函数。

Continuous Sample Time(连续采样)

具有连续采样时间(设置 0 或 [0, 0])的模块在每个主要和次要时间步长执行。如果出现以下情况,则必须选择连续采样时间

C-Script 对连续(或分段连续)函数进行建模,
C-Script 具有连续状态,或者,C-Script 注册一个或多个过零信号以进行事件检测。

Semi-Continuous Sample Time(半连续采样)

具有半连续采样时间(设置 [0, -1])的模块在每个主要时间步长执行,但不在次要时间步长执行。如果 C-Script 仅生成离散输出值并且不需要过零信号,则可以选择半连续采样时间而不是连续采样时间。

Discrete-Periodic Sample Time(离散周期采样)

具有离散周期采样时间(设置 Tp 或 [Tp , To ])的模块以规则间隔的主要时间步长执行。采样周期 Tp 必须为正实数。样本偏移量 To 必须是区间 0 ≤ To < Tp 中的正实数;如果它为零,则可以省略它。

执行输出和更新函数的时间步长计算为 n⋅Tp +To 

Discrete-Variable Sample Time(可变的离散周期采样)

具有离散可变采样时间(设置 -2 或 [-2, 0])的模块以模块本身指定的主要时间步长执行。

在 C 脚本中,将接下来执行块的时间分配给宏 NextSampleHit。这可以在输出或更新函数中完成。最迟在更新函数调用后,NextSampleHit 必须大于当前模拟时间。

如果 C 脚本只有离散变量采样时间,则必须在启动函数中分配第一个采样命中的时间。否则,C-Script 将永远不会被执行。在启动函数中,可通过宏 CurrentTime 获得仿真开始时间。

Multiple Sample Times

如果要对混合系统进行建模,可以在 n ×2 矩阵的不同行中指定多个采样时间。例如,如果您的 C 脚本具有连续状态,但您还必须确保它每 0.5 秒执行一次,偏移量为 0.1 秒,则应输入 [0, 0; 0.5, 0.1]。

您可以在输出和更新函数中使用宏 IsSampleHit(i) 来查询哪个已注册的采样时间在当前时间步长中命中。索引 i 是采样时间矩阵中从零开始的行号。

如果你的 C 脚本应该只在定期采样间隔内执行某些操作,你会写

if (IsSampleHit(1))  
{  
  // this code is only executed at t == n*0.5 + 0.1  
}
要访问 C 脚本执行期间的采样时间,请使用宏 SampleTimePeriod(i) 和 SampleTimeOffset(i)。对于继承的采样时间,将返回实际解析的值,而不是 [-1, 0](请参阅采样时间)。

User Parameters

如果要实现可在不同上下文中使用的通用 C 脚本,则可以将外部参数传递到 C 函数中。

外部参数以逗号分隔的列表形式输入在“C-Script”对话框的“设置”窗格的“参数”字段中。各个参数可以指定为 MATLAB 表达式,并且可以引用工作区变量。它们必须计算为实标量、向量、矩阵、3d 数组或字符串。

在 C 函数中,您可以使用宏 NumParameters 查询外部参数的数量。宏 ParamNumDims(i) 和 ParamDim(i, j) 返回各个参数的维数及其大小。对于字符串,将分别返回 1 和以 C 字符 (char) 为单位的字符串长度。请注意,由于字符串是 UTF-8 编码的,因此 ParamDim(i, j) 返回的长度可能大于字符串中的 unicode 字符数。

若要访问实际参数值,请使用宏 ParamRealData(i, j),其中 j 是数据数组的线性索引。例如,要访问 3D 数组的特定行、列和页中的值,请编写:

int rowIdx = 2;  //行索引为2
int colIdx = 0;  //列索引为0
int pageIdx = 1;  //页索引为1
int numRows = ParamDim(0, 0); //得到第0个元素的行数 
int numCols = ParamDim(0, 1);  //得到第0个元素的列数
int elIdx = rowIdx + numRows*(colIdx + numCols*pageIdx); 
 //行索引+行数*(列索引+列数*页索引)
double value = ParamRealData(0, elIdx);//得到第0个元素的(2,0,1)位置的元素
//宏ParamRealData里将多维数组拉直成为一个一维数组,
//所以有了这段将(2,0,1)转换成一维坐标的程序

若要访问字符串参数,请使用宏 ParamStringData(i)。例如,要使用第2个参数作为错误消息,您可以编写:

SetErrorMessage(ParamStringData(1));

Runtime Checks

如果选中了“C-Script”对话框的“设置”窗格上的“Enable runtime checks(启用运行时检查)”框,则访问块数据(例如信号值、状态、参数等)的 C-Script 宏将使用保护代码包装,以检查数组索引是否超出范围。此外,C-Script 函数调用还包含代码,以检查求解器策略是否违反,例如在次要时间步长期间修改状态或在未启用直接馈通的情况下访问输出函数中的输入信号。

这些运行时检查有一定的开销,因此一旦您确定您的 C-Script 没有错误,您就可以禁用它们以提高仿真速度。但是,不建议这样做,因为在这种情况下,C脚本中的访问冲突可能会导致PLECS崩溃。

运行时检查无法防止直接内存访问导致的访问冲突。

  • 27
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值