Я использую OpenModelica для моделирования сложной системы и сталкиваюсь с неудобной ошибкой ошибка находится в инструкции when
, как вы можете видеть на изображении я использую инструкцию when
для определения массового расхода в расширительном клапане, чтобы подтвердить, что ошибка находится в заявлении when
. Я удалил его и поставил массовый расход равным формуле, которая вычисляет массовый расход и это сработало, это означает, что проблема в when
заявлении, если кто-нибудь может мне помочь, пожалуйста
НЕ линейная ошибка из-за оператора WHEN в OPEN MODELICA
Ответы (3)
Обычное решение циклов с when
- ввести pre
для переменной с дискретным значением. К сожалению, его нет, поэтому мы должны его представить.
Так что вместо
when level<min_level then
port.e_dbM=0.12;
end when;
это было бы:
Boolean belowMin=level<min_level;
equation
when pre(belowMin) then
port.e_dbM=0.12;
end when;
(И то же самое для elsewhen.)
Это дубликат ответа на вопрос, и сообщение об ошибке в: Проблемы с пониманием сообщения об ошибке dymola - для этого нам может потребоваться более общий вопрос и ответ, как канонический.
Из вашего описания я вижу, что переменная dbM - это непрерывная переменная. Я считаю, что использовать when
-оператор неправильно. Давайте сначала исправим это.
Обоснование: условие в when
-выражении запускает событие только один раз в момент времени, когда индикатор условия начинает менять свой знак, то есть величина liquid_level_valve - min_value
становится отрицательной после положительного значения. Числовому решателю обычно удается определить момент времени, когда происходит такое изменение знака. В этот момент времени, скажем, t_e, запускается событие.
Как только событие инициировано, уравнение внутри when
-оператора вычисляется в момент времени t_e. Для следующих временных шагов моделирования, т. Е. T ›t_e, это уравнение больше не вычисляется. Вместо этого уравнение, полученное из оператора connect
, имеет место как уравнение по умолчанию, а не уравнение внутри оператора when
.
Поэтому попробуйте выразить граничные условия с помощью оператора if
вместо оператора when
. Выражение if
похоже на то, что мы называем функциями ветвления в исчислении, и здесь такая ситуация.
Я думаю, что та же ситуация, о которой говорилось в другом ответе, также может произойти с if
. Возможно, вам придется применить аналогичный подход, описанный здесь.
Если ошибки все еще присутствуют с оператором if
, можно попробовать оператор noEvent
, см. описание. Это не совсем правильные цифры, но все же способ сузить возможные причины таких ошибок.
update: как использовать if
вместо when
: чтобы проиллюстрировать идею простым вариантом использования, предположим, что основное уравнение выглядит так:
myMassFlowRate = port_e.dbM;
Чтобы выразить граничные условия, можно ввести вспомогательную переменную:
if liquid_level_value < min_value then
tmp = 0.012;
elseif liquid_level_value > max_value then
tmp = 0;
else
tmp = port_e.dbM;
end if;
myMassFlowRate = tmp;
Это работает с таким плоским кодом без connect
-оператора. Этот способ требует небольшой модификации для работы с портами, передающими информацию между компонентами, но идея та же, например. при необходимости вы можете передавать дискретные логические значения через порты. Например,
type LiquidLevel = enumeration(above,normal,below);
discrete LiqidLevel level(start = normal); // assumption
...
// using when is now correct
when(liquid_level_value < min_value) then
level = below;
elsewhen (liquid_level > max_value) then
level = above;
elsewhen (....)
level = normal;
end when;
переменный уровень может передаваться через порт ввода / вывода для установки скорости потока:
if level == normal then
myMassFlowRate = port_e.dbM;
elseif level == below then
myMassFlowRate = 0;
else
myMassFlowRate = 0.012;
end if;
Это то, что соответствует вашему описанию. Использование when
напрямую для установки реальной переменной - это просто повторная инициализация.
when
неправильно. Ясно, что нельзя установить dbM
непосредственно в if
-выражении, иначе система уравнений не будет согласованной, т.е. больше уравнений, чем неизвестных. Требуется дополнительная вспомогательная переменная, см. Обновление ответа на идею.
- person Atiyah Elsheikh; 05.12.2020
потратив много дней на решение опубликованной проблемы, я нашел решение, чтобы предотвратить ошибку нелинейности, я использовал логическое значение внутри состояния WHEN, и это логическое значение будет управлять массовым расходом с помощью состояния IF следующим образом:
when liquid_level_valve < min_valve then
open_valve = true;
elsewhen liquid_level_valve > max_valve then
open_valve = false;
end when;
port_e.dbM = if open_tev then dbM_valve else 1 / 100000;
где dbM рассчитывается с использованием уравнения, соответствующего клапану. и теперь моя система работает без проблем
спасибо всем, как пытался мне помочь