объявление условного компонента и следующее уравнение if

Я пытаюсь построить модель, которая будет иметь немного разные уравнения в зависимости от того, существуют ли определенные компоненты (в моем случае, жидкостные порты).

Такой код не будет работать:

parameter Boolean use_component=false;
Component component if use_component;
equation
if use_component then
  component.x = 0;
end if;

Как я могу обойти это?


person Yigal    schedule 03.02.2013    source источник


Ответы (3)


Если вы хотите использовать компоненты условий, вам нужно знать о некоторых ограничениях. Раздел 4.4.5 спецификации Modelica 3.3 прекрасно подводит итог. В нем говорится: «Если условие ложно, компонент, его модификаторы и любые уравнения связи, включающие компонент, удаляются». Я покажу вам, как использовать это, чтобы решить вашу проблему всего за секунду, но сначала я хочу объяснить, почему ваше решение не работает.

Проблема связана с проверкой модели. В вашем случае очевидно, что уравнение component.x и компонент component либо существуют, либо не существуют. Это потому, что вы привязали их к одной и той же логической переменной. Но что, если бы у вас не было этого:

parameter Real some_number;
Component component if some_number*some_number>4.0;
equation
if some_number>=-2 and some_number<=2 then
  component.x = 0;
end if;

Мы видим, что это логически идентично вашему случаю. У component.x нет шансов существовать, когда component отсутствует. Но можем ли мы доказать такие вещи вообще? Нет.

Итак, когда были введены условные компоненты, была реализована консервативная семантика, которая всегда может тривиально гарантировать, что задействованные наборы переменных и уравнений никогда не будут «рассинхронизированы».

Вернемся к тому, что говорится в спецификации: «Если условие ложно, компонент, его модификаторы и любые уравнения связи, включающие компонент, удаляются».

В вашем случае решение может быть довольно простым. В зависимости от того, как вы объявляете «x», вы можете просто добавить модификацию к component, т.е.

parameter Boolean use_component=false;
Component component(x=0) if use_component;

Элегантность этого заключается в том, что модификация применяется только к component, а если component отсутствует, то и модификация (уравнение) не применяется. Таким образом, переменная x и связанное с ней уравнение «синхронизированы». Но это работает не во всех случаях (IIRC, x должен иметь квалификатор input, чтобы это работало... может быть, это возможно в вашем случае?).

Остаются две альтернативы. Сначала поместите уравнение component.x внутрь component. Во-вторых, ввести соединитель на component, который, если он подключен, будет генерировать нужное вам уравнение. Как и в случае с модификацией (это не совпадение), вы можете связать x с каким-либо входным соединителем, а затем сделать это:

parameter Boolean use_component;
Component component if use_component;
Constant zero(k=0);
equation
connect(k.y, component.x);

Теперь я могу представить, что после рассмотрения всех трех случаев (модификация, интернализация уравнения и использование connect) вы придете к выводу, что ни один из них не сработает. Если это так, то я бы скромно предположил, что у вас есть проблема с тем, как вы разработали компонент. Причина возникновения этих ограничений связана с необходимостью проверки компонентов сами на корректность. Это требует, чтобы компонент был полным («сбалансированным» в терминологии спецификации).

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

person Michael Tiller    schedule 04.02.2013

Я думаю, что причина, по которой это не сработает, заключается в том, что синтаксический анализатор будет искать объявление переменной "component.x", которая, если компонент не активен, не существует. Это не работает, даже если вы вставите «Evaluate = true» в аннотацию. На мой взгляд, самое чистое решение — работать на уровне уравнений и включать разные наборы уравнений в одном блоке. Вы можете создать модель-оболочку с правильными соединителями и параметрами, а затем, если это каузальная модель, например, вы можете использовать заменяемые классы, чтобы параметризовать модели как функции, или же, в случае акаузальных моделей, поместить уравнения внутри если заявления. Другой возможный обходной путь — поместить две разные модели в один блок, чтобы вы могли использовать их переменные в разделе уравнений, а затем создавать условные соединения, которые позволят использовать блок с выбранным поведением. Другими словами, вы можете создать «модель переноса» с двумя блоками внутри, а затем поместить уравнения соединения с соединителями модели переноса внутри операторов if. Не забудьте построить модель так, чтобы была непротиворечивая система уравнений даже для неиспользуемых блоков. Но это не лучшее решение, потому что если блоки большие, то придется ждать компиляции дольше, так как все будет скомпилировано.

Я надеюсь, это поможет,

Марко

person Marco Romanoni    schedule 04.02.2013

Вы также можете сделать фиктивный компонент, который не виден в графическом слое:

connector DummyHeatPort 
  "Dummy heatport to facilitate optional heatport.  Use this with a conditional heatport by connecting it to the heatport.  Then use the -DummyHeatPort.Q_flow in the thermal energy balance."
  Modelica.SIunits.Temperature T "Port temperature";
  flow Modelica.SIunits.HeatFlowRate Q_flow 
    "Heat flow rate (positive if flowing from outside into the component)";
end DummyHeatPort;

Затем, когда это используется в двухпортовой модели

 Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a heatport if use_heat_port;
 DummyHeatPort dummy_heatport;

...

 equation
 flowport_a.H_flow + flowport_b.H_flow - dummy_heatport.Q_flow = storage 
    "thermal energy balance";
  connect(dummy_heatport, heatport);  

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

person Chad    schedule 12.02.2014