НЕ линейная ошибка из-за оператора WHEN в OPEN MODELICA

Я использую OpenModelica для моделирования сложной системы и сталкиваюсь с неудобной ошибкой  введите описание изображения здесь ошибка находится в инструкции when, как вы можете видеть на изображении  введите описание изображения здесь я использую инструкцию when для определения массового расхода в расширительном клапане, чтобы подтвердить, что ошибка находится в заявлении when. Я удалил его и поставил массовый расход равным формуле, которая вычисляет массовый расход и это сработало, это означает, что проблема в when заявлении, если кто-нибудь может мне помочь, пожалуйста


person Dahmani Merzaka    schedule 01.12.2020    source источник
comment
Как вы объявили port_e.dbM? Он объявлен как дискретная или непрерывная переменная? Он участвует в других уравнениях вне когда?   -  person Atiyah Elsheikh    schedule 03.12.2020
comment
Я использовал потоковый коннектор, я назвал его коннектором, так что он:. Коннектор port_e, port_s;   -  person Dahmani Merzaka    schedule 03.12.2020
comment
Как насчет переменной dbM. Мое впечатление, что это непрерывная переменная, а не дискретная переменная, т.е. она объявлена ​​как Real dbM, а не как дискретная Real dbM ?. В этом случае я подозреваю, что вам нужно использовать оператор if вместо оператора when.   -  person Atiyah Elsheikh    schedule 03.12.2020
comment
Так объявлен dbM сменный пакет connector_A коннектора Medium = Modelica.Media.Interfaces.PartialMedium; поток Medium.MassFlowRate dbM; Среднее абсолютное давление p; поток Сред. специфическая энтальпия h; концевой соединитель_A;   -  person Dahmani Merzaka    schedule 04.12.2020


Ответы (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 - для этого нам может потребоваться более общий вопрос и ответ, как канонический.

person Hans Olsson    schedule 03.12.2020
comment
спасибо, что нашли время ответить мне, я попробовал ваше предложение, но все равно получаю ту же ошибку, я не понимаю - person Dahmani Merzaka; 04.12.2020
comment
Вы добавили полностью следующее - если да, я не знаю: Boolean belowMin = level ‹min_level; Boolean aboveMax = level› max_level; уравнение, когда pre (нижеMin), то port.e_dbM = 0.12; иначе если pre (вышеMax), то port.e_dbM = 0.0; конец, когда; - person Hans Olsson; 07.12.2020

Из вашего описания я вижу, что переменная 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 напрямую для установки реальной переменной - это просто повторная инициализация.

person Atiyah Elsheikh    schedule 03.12.2020
comment
для более подробной информации я использую оператор when, чтобы контролировать скорость массового потока, поступающего в резервуар, скорость массового потока контролируется оператором when, когда уровень жидкости в резервуаре ниже определенного минимального значения, скорость массового потока будет рассчитывается с помощью определенного уравнения, и как только уровень в резервуаре достигает максимального уровня, массовый расход будет равен нулю, и я не могу использовать оператор IF, - person Dahmani Merzaka; 04.12.2020
comment
Это то, что я понял из описания, и вижу, что использовать 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 рассчитывается с использованием уравнения, соответствующего клапану. и теперь моя система работает без проблем

спасибо всем, как пытался мне помочь

person Dahmani Merzaka    schedule 30.12.2020