Моделирование OpenModelica Кулоновское трение: Ошибка трансляции, модуль постоптимизации findZeroCrossings (моделирование) не выполнен
Я пытаюсь смоделировать кулоновское трение в Modelica. основная концепция состоит в том, чтобы проверить, меньше ли относительная скорость между поверхностями, чем постоянная, а внешняя сила, которая пыталась скользить поверхности друг против друга, меньше максимальной статической силы трения (normalForce * staticFrictionCoefficient), то сила трения равна отрицательной внешней силы сдвига. в противном случае сила трения равна кинетической силе трения (normalForce * kineticFrictionCoefficient) в направлении, противоположном направлению скольжения. Я реализовал эту концепцию в Modelica, как показано ниже:
function coulombFriction
input Real relVel;
input Real shearForce;
input Real normalForce;
input Real statfricco;
input Real kinfricco;
output Real fricForce;
algorithm
if relVel==0 and abs(shearForce)<statfricco*normalForce then
fricForce:=shearForce;
else
fricForce:=kinfricco*normalForce*sign(relVel);
end if;
end coulombFriction;
но когда я вызываю эту функцию из модели, как показано ниже:
model fricexample_1
extends coulombFriction;
//parameters
parameter Real kco=0.3;
parameter Real sco=0.4;
parameter Real nfo=1.0;
Real sfo;
Real ffo;
Real x;
Real v;
initial equation
x=0;
v=0;
equation
v=der(x);
der(v)=sfo-ffo;
sfo=time;
ffo=coulombFriction(relVel=v, shearForce=sfo, normalForce=nfo, statfricco=sco, kinfricco=kco);
end fricexample_1;
Я вижу ошибку:
Ошибка перевода
модуль постоптимизации findZeroCrossings (симуляция) не выполнен.
Если я удаляю функцию abs из определенной функции, это решает проблему компиляции, но модель неверна! Буду признателен, если вы поможете мне узнать:
- Как я могу решить эту проблему?
- как иначе моделировать трение?
3 ответа
Ваша модель работает с версией 1.11. Проблема заключается в extends coulombFriction;
заявление. После того, как вы удалили его, он должен работать нормально даже без noEvent
звонки:
package Friction
function coulombFriction
input Real relVel;
input Real shearForce;
input Real normalForce;
input Real statfricco;
input Real kinfricco;
output Real fricForce;
algorithm
if relVel==0 and abs(shearForce)<statfricco*normalForce then
fricForce:=shearForce;
else
fricForce:=kinfricco*normalForce*sign(relVel);
end if;
end coulombFriction;
model fricexample_1
parameter Real kco=0.3;
parameter Real sco=0.4;
parameter Real nfo=1.0;
Real sfo;
Real ffo;
Real x;
Real v;
initial equation
x = 0;
v = 0;
equation
v = der(x);
der(v) = sfo-ffo;
sfo = time;
ffo = coulombFriction(relVel=v, shearForce=sfo, normalForce=nfo, statfricco=sco, kinfricco=kco);
end fricexample_1;
end Friction;
Вы можете использовать noEvent для условий, которые могут генерировать события в функции. Обратите внимание, что вам не нужно расширять модель с помощью функции. На самом деле он не должен работать (расширять модель из функции), но, похоже, мы не проверяем это.
Модель, которая компилируется для меня ниже:
package Friction
function coulombFriction
input Real relVel;
input Real shearForce;
input Real normalForce;
input Real statfricco;
input Real kinfricco;
output Real fricForce;
algorithm
if noEvent(relVel==0) and noEvent(abs(shearForce)<statfricco*normalForce) then
fricForce:=shearForce;
else
fricForce:=kinfricco*normalForce*sign(relVel);
end if;
end coulombFriction;
model fricexample_1
//parameters
parameter Real kco=0.3;
parameter Real sco=0.4;
parameter Real nfo=1.0;
Real sfo;
Real ffo;
Real x;
Real v;
initial equation
x = 0;
v = 0;
equation
v = der(x);
der(v) = sfo-ffo;
sfo = time;
ffo = coulombFriction(relVel=v, shearForce=sfo, normalForce=nfo, statfricco=sco, kinfricco=kco);
end fricexample_1;
end Friction;
Я бы рекомендовал повторно использовать конечный автомат трения, доступный в стандартной библиотеке Modelica. Пример, который работает в OpenModelica и других инструментах, приведен в https://github.com/dzimmer/ZimmersModelicaTutorial/blob/master/Tutorial2015/BaseComponents/Friction/IdealDryFriction.mo.
На самом деле, модель трения Колумба, которую я разработал выше, неверна. Благодаря этому посту я смог найти правильную версию:
package friction1D
final constant Real eps=1.e-15 "Biggest number such that 1.0 + eps = 1.0";
function sgn
input Real inputVar;
output Real outputVar;
algorithm
if noEvent(inputVar < 0) then
outputVar := -1;
else
outputVar := 1;
end if;
end sgn;
function coulombFriction
input Real relVel;
input Real shearForce;
input Real normalForce;
input Real statfricco;
input Real kinfricco;
output Real fricForce;
algorithm
if noEvent(abs(relVel) < eps) and noEvent(abs(shearForce) < statfricco * normalForce) then
fricForce := shearForce;
else
fricForce := kinfricco * normalForce * sgn(relVel);
end if;
end coulombFriction;
model fricexample_1
//parameters
parameter Real kco = 0.3;
parameter Real sco = 0.4;
parameter Real nfo = 1.0;
parameter Real mass = 1.0;
Real sfo;
Real ffo;
Real x;
Real v;
initial equation
x = 0;
v = 0;
algorithm
sfo := 0.7 * sin(time);
ffo := coulombFriction(relVel = v, shearForce = sfo, normalForce = nfo, statfricco = sco, kinfricco = kco);
equation
v = der(x);
mass * der(v) = sfo - ffo;
annotation(
experiment(StartTime = 0, StopTime = 10, Tolerance = 1e-8, Interval = 0.02),
__OpenModelica_simulationFlags(lv = "LOG_STATS", outputFormat = "mat", s = "dassl"));
end fricexample_1;
end friction1D;