Функция для интерполяции с использованием openmodelica - PullRequest
2 голосов
/ 18 октября 2019

У меня есть некоторые данные, извлеченные из matlab, и я хочу, чтобы они были доступны в openmodelica. Данные представлены в виде таблицы x, y и значения z. Я хочу создать функцию, которая воспроизводит точку z из x и y, в которой функция также может красиво интерполироваться между x и y. Таким образом, в основном, интерполяция Modelica должна загружать таблицу результатов и выполнять интерполяцию. Это возможно ? Кто-нибудь может привести меня на путь? заранее спасибо за помощь.

Я приложил свои данные к этому сообщению, первая строка и первый столбец соответствуют значениям x и y соответственно.

https://www.dropbox.com/s/75z2ejcjru8hiu8/data.zip?dl=0

Ответы [ 4 ]

2 голосов
/ 21 октября 2019

Вам необходимо адаптировать файл данных в соответствии с https://doc.modelica.org/Modelica%203.2.3/Resources/helpOM/Modelica.Blocks.Tables.CombiTable2D.html,, т. Е. Не оставлять элемент в позиции (0,0) пустым. См. https://gist.github.com/tbeu/2004db0f7753e69f42da39aec3a00b3d для исправления.

Затем вы можете загрузить и интерполировать данные, используя MSL v3.2.3, например

model Model
  Modelica.Blocks.Tables.CombiTable2D combiTable2D(
    tableOnFile=true,
    tableName="A'_Coefficient",
    fileName="c:\\temp\\data.txt") annotation(Placement(transformation(extent={{-95,60},{-75,80}})));
  Modelica.Blocks.Sources.RealExpression realExpression1(y=time*10) annotation(Placement(transformation(extent={{-140,65},{-120,85}})));
  Modelica.Blocks.Sources.RealExpression realExpression2(y=time*100) annotation(Placement(transformation(extent={{-140,40},{-120,60}})));
  equation
    connect(realExpression1.y,combiTable2D.u1) annotation(Line(points={{-119,75},{-114,75},{-102,75},{-102,76},{-97,76}}, color={0,0,127}));
    connect(realExpression2.y,combiTable2D.u2) annotation(Line(points={{-119,50},{-114,50},{-102,50},{-102,64},{-97,64}}, color={0,0,127}));
  annotation(uses(Modelica(version="3.2.3")));
end Model;
1 голос
/ 18 октября 2019

Вот трехмерная диаграмма рассеяния ваших данных и трехмерная полиномиальная поверхность, прикрепленная к ней. Поскольку данные имеют значительную кривизну поверхности, я не мог найти простое приближающее уравнение для интерполяции. Здесь я использовал поверхностный полином с членами 3-го порядка, и это должно плохо экстраполировать вне границ данных. По этой причине я рекомендую использовать его только для интерполяции.

scatter

surface

# taken from source code output of fitting software
a = -4.8044356996540731E+00
b = -1.7238982381056298E+00
c = 9.7121730188860766E+00
d = 2.0725836239688458E-02
f = -2.3810662793461059E+00
g = -6.8495593999129412E-05
h = 1.7294254445305737E-01
i = 2.6034147965619335E-02
j = -8.6126736653591163E-04
k = 5.8779369562417683E-05

z = a
z += b * x
z += c * y
z += d * pow(x, 2.0)
z += f * pow(y, 2.0)
z += g * pow(x, 3.0)
z += h* pow(y, 3.0)
z += i * x * y
z += j * pow(x, 2.0) * y
z += k * x * pow(y, 2.0)
return z
0 голосов
/ 22 октября 2019

function TestBend

input Real angle;
input Real radius;
output Real coefficient_a;
output Real  coefficient_b;

 Modelica.Blocks.Tables.CombiTable2D A_Coefficient(fileName = "C:\Users\AWH7RNG\Desktop\a_data.txt", smoothness = Modelica.Blocks.Types.Smoothness.ContinuousDerivative, tableName = "A'_Coefficient", tableOnFile = true)  annotation(
Placement(visible = true, transformation(origin = {-10, 54}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));


  Modelica.Blocks.Sources.RealExpression Radius_A(y = radius)  annotation(
Placement(visible = true, transformation(origin = {-62, 64}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
Modelica.Blocks.Sources.RealExpression Angle_A(y = angle)  annotation(
Placement(visible = true, transformation(origin = {-62, 32}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
 Modelica.Blocks.Tables.CombiTable2D B_Coefficient(fileName = "C:\Users\AWH7RNG\Desktop\b_data.txt", tableName = "B_Coefficient")  annotation(
Placement(visible = true, transformation(origin = {4, -20}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
 Modelica.Blocks.Sources.RealExpression Radius_B(y = radius)  annotation(
Placement(visible = true, transformation(origin = {-56, -8}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
 Modelica.Blocks.Sources.RealExpression Angle_B(y = angle)  annotation(
Placement(visible = true, transformation(origin = {-56, -32}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
algorithm
radius := Radius_B.y;
angle :=  Angle_A.y ;
angle := Angle_B.y;
radius := Radius_A.y;
coefficient_a := A_Coefficient.y;
coefficient_b := B_Coefficient.y;
equation
connect(Angle_B.y, B_Coefficient.u2) annotation(
Line(points = {{-44, -32}, {-24, -32}, {-24, -26}, {-8, -26}, {-8, -26}}, color = {0, 0, 127}));
connect(Radius_B.y, B_Coefficient.u1) annotation(
Line(points = {{-44, -8}, {-22, -8}, {-22, -14}, {-8, -14}, {-8, -14}}, color = {0, 0, 127}));
 connect(Angle_A.y, A_Coefficient.u2) annotation(
Line(points = {{-51, 32}, {-37, 32}, {-37, 48}, {-21, 48}, {-21, 48}, {-23, 48}, {-23, 48}}, color = {0, 0, 127}));
 connect(Radius_A.y, A_Coefficient.u1) annotation(
Line(points = {{-51, 64}, {-35, 64}, {-35, 60}, {-21, 60}, {-21, 60}, {-23, 60}, {-23, 60}}, color = {0, 0, 127}));
annotation(
uses(Modelica(version = "3.2.3")));


end TestBend;
0 голосов
/ 21 октября 2019

Вы можете использовать обычный объект внешней таблицы , если вы предпочитаете прямой интерфейс через функцию getTable2DValue . Например,

model Model2
  parameter Modelica.Blocks.Types.ExternalCombiTable2D tableID=Modelica.Blocks.Types.ExternalCombiTable2D(
    "A'_Coefficient",
    "c:\\temp\\data.txt",
    fill(0.0, 0, 2),
    Modelica.Blocks.Types.Smoothness.LinearSegments) "External table object";
  parameter Real x=3 "First coordinate";
  parameter Real y=12 "Second coordinate";
  Real z "Interpolated value at (x,y)";
  equation
    z = Modelica.Blocks.Tables.Internal.getTable2DValue(tableID, x, y);
  annotation(uses(Modelica(version="3.2.3")));
end Model2;
...