OpenModelica жалуется на отрицательное значение, которое не может быть отрицательным

После этого вопроса я модифицировали контроллер на основе энергии, который я описал здесь, чтобы избежать отрицательные значения внутри sqrt:

model Model
  //constants
  parameter Real m = 1;
  parameter Real k = 2;
  parameter Real Fmax = 3;
  parameter Real x0 = 1;
  parameter Real x1 = 2;
  parameter Real t1 = 5;
  parameter Real v0 = -2;

  //variables
  Real x, v, a, xy, F, vm, K;

initial equation
  x = x0;
  v = v0;

equation
  v = der(x);
  a = der(v);
  m * a + k * x = F;

algorithm
  if time < t1 then
    xy := x0;
  else
    xy := x1;
  end if;
  
  K := Fmax * abs(xy - x) + k * (xy^2 - x^2) / 2;
  
  if abs(xy - x) < 1e-6 then
    F := k * x;
  else
    if K > 0 then
      vm := sign(xy - x) * sqrt(2 * K / m);
      F := Fmax * sign(vm - v);
    else
      F := Fmax * sign(x - xy);
    end if;
  end if;
  
  annotation(
    experiment(StartTime = 0, StopTime = 20, Tolerance = 1e-06, Interval = 0.001),
    __OpenModelica_simulationFlags(lv = "LOG_STATS", outputFormat = "mat", s = "euler"));
end Model;

Однако он продолжает выдавать мне ошибку:

Следующее утверждение было нарушено в момент времени 7.170000

Ошибка модели: аргумент sqrt(K/m) был -1.77973e-005, должен быть ›= 0

Интегратор пытается решить проблему с помощью вызываемого утверждения.

Следующее утверждение было нарушено в момент времени 7.169500.

Ошибка модели: аргумент sqrt(K/m) был -6.5459e-006, должен быть ›= 0

завершение модели | Симуляция прекращена подтверждением в момент времени: 7.1695.

СТАТИСТИКА

Ошибка процесса моделирования. Выход с кодом -1.

Я был бы признателен, если бы вы могли помочь мне узнать, в чем проблема и как я могу ее решить.


person Foad    schedule 21.02.2019    source источник


Ответы (1)


Созданный вами код выполняет локализацию событий, чтобы узнать, когда условие в операторах if становится истинным и/или ложным. Во время этого поиска возможно, что выражение в квадратном корне станет отрицательным, хотя вы «избежали» его с помощью оператора if.

Попробуйте прочитать это и применить представленное там решение. Спойлер: в основном это сводится к добавлению оператора noEvent() для вашего логического условия...

person Markus A.    schedule 21.02.2019
comment
большое спасибо. замена K > 0 на noEvent(K > 0) решила проблему. Также доказывает, что с моим контроллером что-то в корне не так. :) - person Foad; 21.02.2019