如何通过同步模型(modelica)中的函数初始化记录类型
How to initialize a record type by a function in synchronous models (modelica)
我写了一个函数,具有 return 记录类型的值。
通常我会使用这个函数通过初始方程来初始化记录类型的实例。
但是因为我想在时钟模型中使用这个函数,初始方程式是不可能的。
对我来说,这似乎是使用属性 start 初始化变量的唯一方法。不幸的是,记录没有这个属性,只有它的组成部分。
这是一个简单的例子,展示了我想做的事情:
model RecordInitializeTest
record simpleRecord
Integer arg1;
Integer arg2;
end simpleRecord;
function initFunc
output simpleRecord sR;
algorithm
sR.arg1 := 1;
sR.arg2 := 2;
end initFunc;
model InitializeTest
input Boolean u(start=false);
output simpleRecord sR1;
equation
if u and not previous(u) then
sR1 =initFunc();
else
sR1 = previous(sR1);
end if;
end InitializeTest;
InitializeTest iT;
equation
iT.u = sample(time > 0.5,Clock(0.1));
end RecordInitializeTest;
这个模型在 dymola 中工作,但当然有警告,因为 iT.sR1.agr1 和 iT.sR1.arg2 没有起始值,而是 previous() 的参数。
从理论上讲,我想使用
output simpleRecord sR1(start=initFunc());
有没有人知道如何以方便的方式初始化 sR1 而无需像
这样的赋值
output simpleRecord sR1(arg1(start=1),arg2(start=2));
因为这对于大型结构化记录来说不方便。
实际上,我只想在某些时间和初始情况下执行一个复杂的外部不纯函数(而不是 initFunc),并将结果保留在两者之间。而且我明确不想使用连续时间模型。而且我不想在翻译过程中收到警告。
如果我完全理解你的问题,只需要做一些小的修改就可以让你的例子运行符合预期:
model RecordInitializeTest
record simpleRecord
Integer arg1(start=0);
Integer arg2(start=0);
end simpleRecord;
function impureFunc
output simpleRecord sR;
algorithm
(sR.arg1, sR.arg2) :=Modelica.Utilities.System.getTime();
end impureFunc;
model ImpureTest
input Boolean u(start=false);
output simpleRecord sR1;
equation
if firstTick() or u and not previous(u) then
sR1 = impureFunc();
else
sR1 = previous(sR1);
end if;
end ImpureTest;
ImpureTest iT(u=sample(time > 0.5, Clock(0.1)));
end RecordInitializeTest;
在模拟结果中,我们看到新记录值恰好计算了 2 次:在时间 0 和时间 0.5:
变化是:
initFunc()
换成impureFunc()
,在结果中看到函数在时间0和时间0.5被调用
执行初始化firstTick()
添加在时间0调用不纯函数
不再有 start-value 警告,因为记录中的每个变量都有一个 dummy-start 值。实际的起始值并不重要,因为它们是用 firstTick()
设置的
注意:我以前从未创建过时钟模型,所以我可能犯了一些愚蠢的初学者错误。
我写了一个函数,具有 return 记录类型的值。 通常我会使用这个函数通过初始方程来初始化记录类型的实例。 但是因为我想在时钟模型中使用这个函数,初始方程式是不可能的。
对我来说,这似乎是使用属性 start 初始化变量的唯一方法。不幸的是,记录没有这个属性,只有它的组成部分。
这是一个简单的例子,展示了我想做的事情:
model RecordInitializeTest
record simpleRecord
Integer arg1;
Integer arg2;
end simpleRecord;
function initFunc
output simpleRecord sR;
algorithm
sR.arg1 := 1;
sR.arg2 := 2;
end initFunc;
model InitializeTest
input Boolean u(start=false);
output simpleRecord sR1;
equation
if u and not previous(u) then
sR1 =initFunc();
else
sR1 = previous(sR1);
end if;
end InitializeTest;
InitializeTest iT;
equation
iT.u = sample(time > 0.5,Clock(0.1));
end RecordInitializeTest;
这个模型在 dymola 中工作,但当然有警告,因为 iT.sR1.agr1 和 iT.sR1.arg2 没有起始值,而是 previous() 的参数。 从理论上讲,我想使用
output simpleRecord sR1(start=initFunc());
有没有人知道如何以方便的方式初始化 sR1 而无需像
这样的赋值output simpleRecord sR1(arg1(start=1),arg2(start=2));
因为这对于大型结构化记录来说不方便。
实际上,我只想在某些时间和初始情况下执行一个复杂的外部不纯函数(而不是 initFunc),并将结果保留在两者之间。而且我明确不想使用连续时间模型。而且我不想在翻译过程中收到警告。
如果我完全理解你的问题,只需要做一些小的修改就可以让你的例子运行符合预期:
model RecordInitializeTest
record simpleRecord
Integer arg1(start=0);
Integer arg2(start=0);
end simpleRecord;
function impureFunc
output simpleRecord sR;
algorithm
(sR.arg1, sR.arg2) :=Modelica.Utilities.System.getTime();
end impureFunc;
model ImpureTest
input Boolean u(start=false);
output simpleRecord sR1;
equation
if firstTick() or u and not previous(u) then
sR1 = impureFunc();
else
sR1 = previous(sR1);
end if;
end ImpureTest;
ImpureTest iT(u=sample(time > 0.5, Clock(0.1)));
end RecordInitializeTest;
在模拟结果中,我们看到新记录值恰好计算了 2 次:在时间 0 和时间 0.5:
变化是:
initFunc()
换成impureFunc()
,在结果中看到函数在时间0和时间0.5被调用执行初始化
firstTick()
添加在时间0调用不纯函数不再有 start-value 警告,因为记录中的每个变量都有一个 dummy-start 值。实际的起始值并不重要,因为它们是用
设置的firstTick()
注意:我以前从未创建过时钟模型,所以我可能犯了一些愚蠢的初学者错误。