Engee 文档
Notebook

利萨如斯曲线的构造

建立基本数学对象的模型有助于更好地理解产生这些对象的过程的工作原理。在本例中,我们将学习两种建立利萨如斯曲线模型的方法,并使用文档页面"软件控制建模 "中描述的_软件控制_命令建立这些模型并比较它们的运行情况。

建模过程

Lissajous 图形是由一个点同时产生两次谐波振荡所绘制的轨迹。它们通常由两个三角函数系统产生。坐标$x$ 和$y$ 与时间$t$ 的关系如下:

$$\left\{\begin{align*} x(t) &= A \, sin(\alpha t + \beta) \\ y(t) &= B \, sin(\beta t) \end{align*}\right.$$

这里$A, B$ 是每个谐波过程的振幅(我们将使它们等于1)

$\alpha, \beta$ - 两个过程的频率、

$\delta$ - 谐波过程之间的位移。

由正弦波发生器创建的模型

我们的第一个模型将由两个模块组成Sine Wave

lissajous_curve_blocks_im.png

定义为代码的模型

第二个模型将由一个块Engee Function 和几个块Constant 组成,指定相关的系统参数。

lissajous_curve_function_im.png

在这两种情况下,输出参数都是信号xy ,并将其标记为_记录信号_。这样我们就可以在程序运行仿真时读取它们。

加载模型

首先要做的是控制这些模型。如果模型已经打开(例如在画布上),只需使用一条命令即可,如果需要加载模型,则需要使用另一条命令。让我们来获取已加载模型的列表:

In [ ]:
all_model_names = [m.name for m in engee.get_all_models()]
Out[0]:
1-element Vector{String}:
 "engee_function_moving_average"

如果模型已经打开,我们将使用函数open 来获取天数控制。如果没有,我们将使用函数load

In [ ]:
# Модель, состоящая из блоков
if "lissajous_curve_blocks" in all_model_names m1 = engee.open( "lissajous_curve_blocks" )
else m1 = engee.load( "/user/start/examples/edu/lissajous_curves/lissajous_curve_blocks.engee" )
end;

# Модель, состоящая из кода
if "lissajous_curve_function" in all_model_names m2 = engee.open( "lissajous_curve_function" )
else m2 = engee.load( "/user/start/examples/edu/lissajous_curves/lissajous_curve_function.engee" )
end;

现在我们有了两个对象m1m2 ,通过它们可以控制我们正在研究的两个模型的参数和运行。

同步模型参数

$\alpha$ 和$\beta$ 参数的比值决定了曲线的形状(裂片数)。现在我们将使用软件控制命令将两个模型设置为相同的参数。我们希望模型使用以下参数:

In [ ]:
alpha = 3;
beta = 4;

让我们研究一下Sine Wave 模块的参数结构lissajous_curve_blocks

In [ ]:
param = engee.get_param( "lissajous_curve_blocks/Sine Wave" )
Out[0]:
BlockParameters(
  SineType => Time based,
  Amplitude => 1,
  Bias => 0.0,
  TimeSource => Use simulation time,
  Frequency => 4,
  Phase => 0,
  SampleTime => 0.0,
)

这是一个Pair 类型的结构,它可以作为块lissajous_curve_blocks/Sine Wave 的新参数进行更改和整体传递:

In [ ]:
param.Frequency = alpha
engee.set_param!( "lissajous_curve_blocks/Sine Wave", param )

也可以使用更简短的语法。让我们对第二个程序块和第二个模型做同样的处理:

In [ ]:
engee.set_param!( "lissajous_curve_blocks/Sine Wave-1", "Frequency"=>beta )
engee.set_param!( "lissajous_curve_function/Constant", "Value"=>alpha )
engee.set_param!( "lissajous_curve_function/Constant-1", "Value"=>beta )

模拟参数的结构可以通过engee.get_param( "lissajous_curve_function" ) 命令获得。

将两个模型设置为相同的模拟步骤:

In [ ]:
param = engee.get_param( "lissajous_curve_blocks" )
Out[0]:
ModelParameters(
  :EnableMultiTasking => false
  :GenerateComments => true

  #Параметры интегратора:
  :StartTime => 0.0
  :StopTime => 10
  :SolverType => fixed-step
  :SolverName => Euler
  :FixedStep => 0.01
)
In [ ]:
# Установим обеим моделям временной шаг 0.001
engee.set_param!( "lissajous_curve_function", "FixedStep"=>0.001 )
engee.set_param!( "lissajous_curve_blocks", "FixedStep"=>0.001 )

现在我们可以使用run 命令来执行这些模型:

In [ ]:
r1 = engee.run( m1; verbose=false );

# Иногда нужно дождаться, пока модель закончит выполнение
# while( engee.get_status() != Engee.Types.READY ) end;
In [ ]:
r2 = engee.run( m2; verbose=false );

我们得到的输出是一个结构Dict (字典),其中包含一组表DataFrame 。每个表都有列向量timevalue ,对应于每个存储模型信号的时间和输出值。

建模结果

使用图表可以很容易地比较输出曲线:

In [ ]:
using Plots
plot( r1["x"].value, r1["y"].value, lc=:red, lw=10, label="Блоки Sine Wave" )
plot!( r2["x"].value, r2["y"].value, lc=:orange, lw=4, label="Блоки Engee Function" )
Out[0]:
No description has been provided for this image

结论

我们研究了一种基本数学对象的两个模型的运行,这种数学对象在从物理学到电路学等多种技术学科中都有应用。我们还应用了 "程序控制 "机制,将两个模型设置为相同的参数,并在图形上分析了模拟结果,而无需离开脚本。