# 状态机基本语法


在状态机中的语句编写需使用的 Modelica 语法。

# 常用运算符

# 比较运算符

状态机在数值比较操作时需使用的比较运算符,返回结果为布尔值,常用的比较运算符如下:

运算符 说明 示例
> 大于 7 > 3 // 返回 true,因为 7 大于 3;
3 > 7 // 返回 false,因为 3 不大于 7
>= 大于等于 5 >= 5 // 返回 true,因为 5 大于或等于 5;
2 >= 5 // 返回 false,因为 2 不大于也不等于 5
< 小于 2 < 10 // 返回 true,因为 2 小于 10;
10 < 2 // 返回 false,因为 10 不小于 2
<= 小于等于 8 <= 8 // 返回 true,因为 8 小于或等于 8;
11 <= 5 // 返回 false。因为 11 不小于也不等于 5
== 等于 4 == 4 // 返回 true,因为 4 等于 4;
8 == 2 // 返回 false,因为 8 不等于 2
<> 不等 9 <> 3 // 返回 true,因为 9 不等于 3;
6 <> 6 // 返回 false,因为 6 等于 6

# 逻辑运算符

状态机在进行逻辑运算时需使用的运算符,逻辑运算符仅支持以全小写的形式输入,返回结果为布尔值,常用的逻辑运算符如下:

运算符 说明 示例
and 比较两个或多个条件,只有当所有条件都为 true 时,结果才为 true。 7 > 3 and 5 < 10 // 返回 true,因为 7 大于 3 且 5 小于 1;
7 > 3 and 5 > 10 // 返回 false,因为 7 大于 3 但 5 不小于 10
or 用于比较两个或多个条件,只要至少有一个条件为 true,结果就为 true。 7 > 3 or 5 > 10 // 返回 true,因为 7 大于 3 或 5 大于 10;
5 < 3 or 2 < 1 // 返回 false,因为 5 不小于 3 且 2 不小于 1
not 用于反转条件的布尔值,如果条件为 true,则返回 false;如果条件为 false,则返回 true。 not 7 > 3 // 返回 false,因为 7 大于 3,反转后为假;
not 5 < 3 // 返回 true,因为 5 不小于 3,反转后为真

# 算术运算符

状态机在进行数值运算时需使用的运算符,返回结果参考参与运算的数值类型,常用的算符运算符如下:

运算符 说明 示例
+ 加法,用于两个数相加。 result := 5 + 3; // 返回 8,因为 5 加 3 等于 8;
result := 7 + 2; // 返回 9,因为 7 加 2 等于 9
- 减法,用于一个数减去另一个数。 result := 10 - 4; // 返回 6,因为 10 减 4 等于 6;
result := 2 - 5; // 返回 -3,因为 2 减 5 等于 -3
* 乘法,用于两个数相乘。 result := 4 * 6; // 返回 24,因为 4 乘 6 等于 24;
result := 7 * 3; // 返回 21,因为 7 乘 3 等于 21
/ 除法,用于一个数除以另一个数。 result := 20 / 4; // 返回 5,因为 20 除以 4 等于 5;
result := 9 / 3; // 返回 3,因为 9 除以 3 等于 3
^ 幂运算,用于计算一个数的另一个数次幂。 result := 2 ^ 3; // 返回 8,因为 2 的 3 次幂等于 8;
result := 5 ^ 2; // 返回 25,因为 5 的 2 次幂等于 25

# 内置函数

状态机支持的内置函数主要包括:

函数 说明 示例
abs(x) 绝对值,用于计算 x 的绝对值。 result := abs(-5); // 返回 5,因为 -5 的绝对值是 5
sign(x) 符号函数,若 x > 0 结果为 1,x < 0 结果为 -1。 result := sign(-3); // 返回 -1,因为 -3 小于 0;
result := sign(0); // 返回 0,因为 0 不大于也不小于 0;
result := sign(4); // 返回 1,因为 4 大于 0
sqrt(x) 平方根,若 x ≥ 0 时结果为 x 的平方根,否则出错。 result := sqrt(16); // 返回 4,因为 4 的平方是 16;
result := sqrt(9); // 返回 3,因为 3 的平方是 9
div(x,y) 整数除法,结果是 x/y 的商且丢弃小数部分。 result := div(10, 3); // 返回 3,因为 10 除以 3 的商是 3(丢弃小数部分)
mod(x,y) 取模运算,结果是 x/y 整除的模。 result := mod(10, 3); // 返回 1,因为 10 除以 3 的余数是 1
rem(x,y) 余数运算,结果是 x/y 整除的余数。 result := rem(10, 3); // 返回 1,因为 10 除以 3 的余数是 1
ceil(x) 上限函数,结果是不小于 x 的最小整数。 result := ceil(4.7); // 返回 5,因为不小于 4.7 的最小整数是 5
floor(x) 下限函数,结果是不大于 x 的最大整数。 result := floor(-4.7); // 返回 -5,因为不大于 -4.7 的最大整数是 -5
integer(x) 取整函数,结果是不大于 x 的最大整数。 result := integer(3.9); // 返回 3,因为不大于 3.9 的最大整数是 3
sin(x) 正弦函数,计算 x 的正弦值(x 通常以弧度表示)。 result := sin(0); // 返回 0,因为 π/2 弧度的正弦值是 0
cos(x) 余弦函数,计算 x 的余弦值(x 通常以弧度表示)。 result := cos(0); // 返回 1,因为 0 弧度的余弦值是 1
tan(x) 正切函数,计算 x 的正切值(x 通常以弧度表示)。 result := tan(1); // 返回 1.5574077246549,因为 π/4 弧度的正切值是 1.5574077246549
asin(x) 反正弦函数,计算 x 的反正弦值,结果以弧度表示。 result := asin(0); // 返回 0,因为 1 的反正弦值是 0 弧度
acos(x) 反余弦函数,计算 x 的反余弦值,结果以弧度表示。 result := acos(1); // 返回 0,因为 1 的反余弦值是 0 弧度
atan(x) 反正切函数,计算 x 的反正切值,结果以弧度表示。 result := atan(0.01745); // 返回 math.pi / 4,因为 1 的反正切值是 π/4 弧度
exp(x) 指数函数,计算 e 的 x 次幂。 result := exp(1); // 返回 math.e,因为 e 的 1 次幂是自然对数的底数
log(x) 自然对数,计算 x 的自然对数(e 为底)。 result := log(math.e); // 返回 1,因为 e 的自然对数是 1
log10(x) 以 10 为底的对数,计算 x 的以 10 为底的对数。 result := log10(100); // 返回 2,因为 100 的以 10 为底的对数是 2
nthRoo(a,n) 幂次根,用于计算一个数的任意次幂次根。 result := nthRoot(8, 3); // 返回 2,因为 8 的立方根是 2
cat(dim,A,B,...) 数组串联,用于将多个数组沿指定的维度 dim 进行拼接。 result := cat(1, {1, 2}, {3, 4}); // 返回 [1, 2, 3, 4],因为沿着维度 1 将两个数组串联
sum(x) 求和函数,用于计算数组或矩阵中所有元素的总和。 result := sum({1, 2, 3}); // 返回 6,因为 1 加 2 加 3 的总和是 6

# 算法语句

# 赋值语句

状态机通常采用非阻塞赋值,可以避免在代数方程系统中引入不必要的循环依赖,从而提高求解的稳定性和效率。它表示在模拟的当前时间步结束时,将右侧的表达式计算结果赋值给左侧的变量。

使用赋值语句的示例如下:

a := b + 1; // 表示 a 等于 b 加 1

# 数组操作

数组可以执行的常用操作,主要包括:

操作类型 说明 示例
整体赋值 数组以 {第一个元素, 第二个元素, ...} 的形式编写。 a := {1.0, 2.0, 3.0}; //将 {1,2,3} 赋值给数组 ;
b := {-1, 0, 1, 0}; //将 {-1, 0, 1, 0} 赋值给数组 b
数组元素索引 使用索引读取数组元素数组中的元素,支持使用 a[m:n] 的形式读取 a 的第 m 到 n 个元素(索引从1开始)。 b := a[2]; //读取数组 a 中的第二个元素;
c := a[2:3]; //将数组 a 的第二个元素和第三个元素赋值给 c
索引修改元素 使用索引修改数组元素数组中的元素(索引从 1 开始)。 a[2] := b; //将 b 赋值给数组 a 中的第二个元素;
a[2:3] := b; //错误,暂不支持通过数组给另一数组的部分元素进行赋值
拼接数组 使用 cat 函数拼接数组。 c := cat(1, a, b); //将 a 和 b 拼接成新数组 c
数组元素求和 使用 sum 函数求所有元素的和。 b := sum(a); // b 等于 a 中所有元素的和
数组算术运算 使用算术运算符进行计算。 c := a + b; //计算数组 a 和数组 b 的和,要求 a 和 b 的元素个数相同

# 条件语句

条件语句是编写动作时常用的语句,状态机现支持 if 语句、if-else 语句和 if-elseif-else 语句,暂不支持 when 语句。

语句类型 基本语法 示例
if
if condition then  
// 当条件为 true 时执行的代码
end if;
if indata > 0.5 then //如果 indata > 0.5,则 outdata 加 1 
  outdata := outdata + 1;
end if;
if-else
if condition then  
// 当条件为 true 时执行的代码
else
// 当条件为 false 时执行的代码
end if;
if indata > 0.5 then //如果 indata > 0.5,则 outdata 加 1,否则 outdata-1 
outdata := outdata + 1;
else
outdata := outdata - 1;
end if;
if-elseif-else
if condition then
// 当条件为 true 时执行的代码;
elseif anotherCondition then
// 当另一个条件为 true 时执行的代码
else
// 当所有条件都为 false 时执行的代码
end if;
if indata > 0.5 then //如果 indata > 0.5,则 outdata 加 2;如果 indata > 0 且 indata <= 0.5 时,则 outdata 加 1;如果 indata < 0,则 outdata 减 1 
outdata := outdata + 2;
elseif indata > 0 then
outdata := outdata + 1;
else
outdata := outdata - 1;
end if;

# 循环语句

循环语句用于重复执行一段代码,直到满足特定条件,当前支持两种类型的循环语句:for 循环和 while 循环。

循环类型 基本语法 示例
for 循环
for variable in sequence loop //variable 是在每次迭代中变化的变量,sequence 是一个范围或数组,定义了循环的迭代序列  
// 循环体内的代码
end for;
for i in 1:10 loop //从 1 到 10 进行循环,每次循环中将 outdata 的值增加 1
outdata := outdata + 1;
end for;
while 循环
while condition loop //condition 是一个返回布尔值的表达式,只要它为 true,循环就继续执行
// 循环体内的代码
end while;
while indata > 0 loop //当 indata > 0 时,执行 outdata+1
outdata := outdata+1;
end while;