Как построить сбалансированный соединитель для жидкостей в Modelica? - PullRequest
5 голосов
/ 22 февраля 2020

Статус поста:

200313 Получил ответ с кодом DEMO_v42, который я принимаю за вознаграждение!

200310 Я комментирую два ключевых документа, предложенных вчера. До сих пор не понимаю, как обновить DEMO_v41.

200309 Я хочу подчеркнуть, что ключевая проблема заключается в том, как ввести понятие потока в код DEMO_v41 (если это возможно) и таким образом сделать балансный разъем. Переменная c, то есть концентрация, должна быть объявлена ​​stream, но как следует обновлять уравнения с помощью inStream или actualStream - что я был бы рад видеть!

200226 Был добавлен пост-пример DEMO_v41, который является упрощенным и я надеюсь, что более читаемый код, чем первый DEMO_v40.

200225 Я дал некоторые комментарии к ответам и попытался сосредоточить внимание читателей на реальных проблемах, но мало что произошло.

200224 I получил некоторый вклад в пост как общий, так и подробный. Подробные комментарии имеют меньшую ценность и частично являются результатом неправильного понимания проблемы. Более общий ответ от Рене хороший, но слишком общий. Мне очень нравится понимать, как использовать концепцию потока с небольшими примерами, прежде чем думать об использовании Modelica.Media et c. Это учебный процесс.


Я хочу знать, как правильно определить соединитель для жидкости, которая содержит ряд компонентов с различными концентрациями в растворе, а затем этот раствор имеет скорость потока. Давление в жидкости ничтожно мало. Стандартный соединитель, который я использовал в течение длительного времени:

connector LiquidCon
   nc=5;
   Real c[nc]        “Component concentrations”;
   flow Real F       “Flow rate”;
end LiquidCon;

Соединитель хорошо работает в JModelica и OpenModelica, но в OpenModelica я получаю предупреждения о том, что соединитель не сбалансирован. В спецификации языка Modelica, раздел 9.3.1, я вижу, что моя конструкция на самом деле недопустима, см. https://www.modelica.org/documents/ModelicaSpec34.pdf. Как я могу сделать соединитель, который удовлетворяет требованиям?

Я потратил некоторое время, читая главу 5.10 о понятии «поток» в издании Fritzons, книга 2n, но мне нужно изучить его более подробно.

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

Во вводном разделе главы 5.10 объем понятия «поток» выглядит так: «.. .применение двунаправленных потоков материи со связанными свойствами… ». В моей области применения я сомневаюсь, что мне нужно учитывать двунаправленные потоки. Это означает, что использование потока является« избыточным ». Но это также подразумевает, что я не должен используйте также понятие «поток», что немного жаль. Должны ли мы действительно прекратить использовать понятие «поток» здесь?

В любом случае, я попытался собрать более базовый пример c чем можно найти в книге Фрицсона на эту тему, чтобы увидеть, как будет выглядеть использование понятия «поток», а также какие издержки вы получите во время вычислений и т. д. c. В приведенном ниже примере я моделирую поток жидкости из Подающий бак в сборный бак. Поток теперь регулируется перепадом давления. de DEMO_v41 работает и выдает предупреждение, что разъем не сбалансирован. Если я теперь объявлю концентрацию субстрата c как «потоковую», как мне теперь обновить код с использованием inStream и actualStream, чтобы он работал так же, но теперь с этим сбалансированным соединителем?

package DEMO_v41

//  ---------------------------------------------------------------------------------------------
//     Interfaces  
//  ---------------------------------------------------------------------------------------------

    import Modelica.Blocks.Interfaces.RealInput;
    import Modelica.Blocks.Interfaces.RealOutput;

//  ---------------------------------------------------------------------------------------------
//     Equipment
//  ---------------------------------------------------------------------------------------------

    package EquipmentLib

        connector LiquidCon
            Real P                                             "Pressure"; 
            flow Real F                                        "Flow rate";
            Real c                                             "Substance conc";
        end LiquidCon;

        model PipeType
            LiquidCon inlet, outlet;
            parameter Real area = 1;
        equation
            inlet.F = -outlet.F;
            outlet.F = -area^2*(inlet.P - outlet.P);           // Linearized Bernoulli equation
            outlet.c = inlet.c;
        end PipeType;

        model FeedtankType
            LiquidCon outlet;                                  
            parameter Real P = 0.1                             "Pressure"; 
            parameter Real V_0 = 100                           "Initial feed volume";         
            parameter Real c_in = 1.0                          "Feedtank conc"; 
            Real V(start=V_0, fixed=true)                      "Feed volume";
        equation    
            outlet.c = c_in;
            outlet.P = P;
            der(V) = outlet.F;               
        end FeedtankType;

        model HarvesttankType
            LiquidCon inlet;
            parameter Real P = 0.0                             "Pressure";                      
            parameter Real V_0 = 1.0                           "Initial harvest liquid volume";
            parameter Real m_0 = 0.0                           "Initial substance mass";
            Real V(start=V_0, fixed=true)                      "Harvest liquid volume";
            Real m(start=m_0, fixed=true)                      "Substance mass";
            Real c                                             "Substance conc"; 
        equation
            inlet.P = P;
            der(V) = inlet.F;
            der(m) = inlet.c*inlet.F;
            c = m/V;            
        end HarvesttankType;
    end EquipmentLib;

//  ---------------------------------------------------------------------------------------------
//     Example of system 
//  ---------------------------------------------------------------------------------------------

    model Test
        EquipmentLib.FeedtankType feedtank;
        EquipmentLib.HarvesttankType harvesttank;
        EquipmentLib.PipeType pipe;
    equation
        connect(feedtank.outlet, pipe.inlet);
        connect(pipe.outlet, harvesttank.inlet);
    end Test;

end DEMO_v41;

Более старый пример DEMO_v40 ниже является более общим и сложным для чтения, но хранится для справки, так как один ранний ответ об этом примере.

Я получаю сообщение об ошибке компиляции (JModelica 2.14) это: «Ошибка в плоской модели: система структурно сингулярна. Следующие переменные не могут быть сопоставлены с уравнением: croptank.inlet.c [1], pipe.outlet.c [1]. OpenModelica (1. 16) дает примерно такое же сообщение. Что здесь не так?

package DEMO_v40

//  ---------------------------------------------------------------------------------------------
//     Interfaces  
//  ---------------------------------------------------------------------------------------------

    import Modelica.Blocks.Interfaces.RealInput;
    import Modelica.Blocks.Interfaces.RealOutput;

    partial package MediumBase
        constant String name                                   "Medium name";
        constant Integer nc                                    "Number of substances";
        replaceable type Concentration = Real[nc]              "Substance conc";        
    end MediumBase;

    package Medium1 
        extends MediumBase
            (name="One component medium",
             nc=1);
        constant Real[nc] mw = {10}                            "Substance weight";  
        constant Integer A = 1                                 "Substance index";
    end Medium1;

    record Medium_data
        constant String name = Medium1.name;
        constant Integer nc = Medium1.nc;
        constant Real[nc] mw = Medium1.mw;
        constant Integer A = Medium1.A;
    end Medium_data;

//  ---------------------------------------------------------------------------------------------
//     Equipment dependent on the medium  
//  ---------------------------------------------------------------------------------------------

    package EquipmentLib
        replaceable package Medium = MediumBase                // formal parameter - EquipmentLib
            constrainedby MediumBase;

        connector LiquidCon
            Real P                                             "Pressure"; 
            flow Real F (unit="m3/s")                          "Flow rate";
            stream Medium.Concentration c                      "Substance conc";
        end LiquidCon;

        model PipeType
            LiquidCon inlet, outlet;
            parameter Real area = 1;
        equation
            inlet.F = -outlet.F;
            outlet.F = area^2*(inlet.P - outlet.P);            // Linearized Bernoulli equation
            for i in 1:Medium.nc loop
                outlet.c[i] = inlet.c[i];
            end for;
        end PipeType;

        model FeedtankType
            LiquidCon outlet;                                  
            parameter Real P = 0.1                             "Pressure"; 
            parameter Real V_0 (unit="m3") = 100               "Initial feed volume";         
            parameter Real[Medium.nc] c_in (each unit="kg/m3") 
                            = {1.0*k for k in 1:Medium.nc}     "Feed inlet conc";                        
            Real V(start=V_0, fixed=true, unit="m3")           "Feed volume";
        equation    
            for i in 1:Medium.nc loop
                outlet.c[i] = c_in[i];
            end for;
            outlet.P = P;
            der(V) = outlet.F;               
        end FeedtankType;

        model HarvesttankType
            LiquidCon inlet;
            parameter Real P = 0.0                             "Pressure";                      
            parameter Real V_0 (unit="m3") = 1.0               "Initial harvest liquid volume";
            parameter Real[Medium.nc] m_0 
                  (each unit="kg/m3") = zeros(Medium.nc)       "Initial substance mass";
            Real[Medium.nc] m 
                  (start=m_0, each fixed=true)                 "Substance mass";
            Real[Medium.nc] c                                  "Substance conc"; 
            Real V(start=V_0, fixed=true, unit="m3")           "Harvest liquid volume";
        equation
            inlet.P = P;
            der(V) = inlet.F;
            for i in 1:Medium.nc loop
                der(m[i]) = inStream(inlet.c[i])*inlet.F;
                c[i] = m[i]/V;
            end for;               
        end HarvesttankType;
    end EquipmentLib;

//  ---------------------------------------------------------------------------------------------
//     Adaptation of package Equipment to Medium1 
//  ---------------------------------------------------------------------------------------------

    package Equipment
        import DEMO_v40.EquipmentLib;
        extends EquipmentLib(redeclare package Medium=Medium1);
    end Equipment;

//  ---------------------------------------------------------------------------------------------
//     Examples of systems 
//  ---------------------------------------------------------------------------------------------

    model Test
        Medium_data medium;
        Equipment.FeedtankType feedtank;
        Equipment.HarvesttankType harvesttank;
        Equipment.PipeType pipe;
    equation
        connect(feedtank.outlet, pipe.inlet);
        connect(pipe.outlet, harvesttank.inlet);
    end Test;

end DEMO_v40;

Ответы [ 3 ]

4 голосов
/ 24 февраля 2020

Лично я бы "go полностью" и использовал бы потоковые соединители по следующим причинам:

  1. В течение последних 15–20 лет было предпринято много попыток создать хороший термо -гидравлические c разъемы в Modelica Результатом этой работы стало создание в 2008 году разъемов stream, которые в настоящее время являются современными в Modelica. Он позволяет переносить заданную c энтальпию и фракции вещества (или концентрацию видов) с одной переменной flow и обеспечивает реверсирование потока. Использование stream разъемов не излишне.
  2. Придерживаясь, например, Modelica.Fluid.Interfaces.FluidPort, ваша работа будет совместима со многими существующими библиотеками и моделями, и вам не нужно создавать насосы, трубы, клапаны, модели резервуаров и т. Д. c. Вы сами.

Однако вы столкнетесь с парой трудностей:

  1. Вам нужно будет изучить синтаксис и работу соединителей stream. Вы можете найти вдохновение в https://github.com/justnielsen/ModelicaTutorials
  2. Вы должны реализовать модель среды на основе Modelica.Media для жидкости, которую вы будете транспортировать в соединителях потока. Модели среднего размера не должны быть очень сложными, если вы можете принять, например, постоянную плотность и / или заданную c теплоемкость. Если модель среды проста, в вычислительном отношении легко переключаться между объемным / массовым расходом при указании граничных условий (источник / приемники).

С наилучшими пожеланиями,

Rene Просто Нильсен

2 голосов
/ 24 февраля 2020

Правильный путь будет либо

connector LiquidCon
   nc=5;
   Real c[nc]        “Component concentrations”;
   flow Real F[nc]       “Flow rate”;
end LiquidCon;

, либо

connector LiquidCon
   Real c        “Component concentrations”;
   flow Real F       “Flow rate”;
end LiquidCon;

В зависимости от того, что вы хотите моделировать. Правило большого пальца: number of potentials = number of flows. Поскольку вы используете только один поток и несколько концентраций, это означает, что у вас есть несколько резервуарных компонентов, каждый с определенной концентрацией, соединенных трубчатыми компонентами, которые обеспечивают скорость потока.

Для них я бы порекомендовал вторую опубликованную мной версию!

Некоторая справочная информация: соединитель никогда не уравновешен, предполагается, что он обеспечивает половину числа уравнений по сравнению с его неизвестными. Всякий раз, когда вы добавляете соединитель к компоненту, этот компонент должен сбалансировать его. Причина довольно проста: например, разъем с одним потенциалом и одним потоком. Направление, в котором потоки информации неясны, но определенно то, что либо переменная flow считается известной, либо potential считается известной, другая будет вычисляться по уравнениям компонента. Для резервуара концентрация рассчитывается по его собственным уравнениям, а поток пропускается через соединитель (наоборот, для трубы).

При подключении двух или более соединителей все потенциалы устанавливаются равными, и все потоки суммируются. быть нулем ( Спецификация языка Modelica раздел 9.2).

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

package DEMO_v40

//  ---------------------------------------------------------------------------------------------

//     Interfaces
  //  ---------------------------------------------------------------------------------------------
    import Modelica.Blocks.Interfaces.RealInput;
    import Modelica.Blocks.Interfaces.RealOutput;

    partial package MediumBase
        constant String name                                   "Medium name";
        constant Integer nc = 1                           "Number of substances";
        replaceable type Concentration = Real[nc]              "Substance conc";        
    end MediumBase;

    package Medium1 
        extends MediumBase
            (name="One component medium",
             nc=1);
        constant Real[nc] mw = {10}                            "Substance weight";  
        constant Integer A = 1                                 "Substance index";
    end Medium1;

    record Medium_data
        constant String name = Medium1.name;
        constant Integer nc = Medium1.nc;
        constant Real[nc] mw = Medium1.mw;
        constant Integer A = Medium1.A;
    end Medium_data;

  //  ---------------------------------------------------------------------------------------------
  //     Equipment dependent on the medium
  //  ---------------------------------------------------------------------------------------------

    package EquipmentLib

        replaceable package Medium = MediumBase                "formal parameter EquipmentLib";


        connector LiquidCon
            Real P                                             "Pressure"; 
            flow Real F (unit="m3/s")                          "Flow rate";
            stream Medium.Concentration c                      "Substance conc";
        end LiquidCon;

        model PipeType
            LiquidCon inlet, outlet;
            parameter Real area = 1;
        equation
            inlet.F = -outlet.F;
            outlet.F = area^2*(inlet.P - outlet.P);            // Linearized Bernoulli equation
            for i in 1:Medium.nc loop
                outlet.c[i] = inlet.c[i];
            end for;
        end PipeType;

        model FeedtankType
            LiquidCon outlet;                                  
            parameter Real P = 0.1                             "Pressure"; 
            parameter Real V_0 (unit="m3") = 100               "Initial feed volume";         
            parameter Real[Medium.nc] c_in (each unit="kg/m3") 
                            = {1.0*k for k in 1:Medium.nc}     "Feed inlet conc";                        
            Real V(start=V_0, fixed=true, unit="m3")           "Feed volume";
        equation    
            for i in 1:Medium.nc loop
                outlet.c[i] = c_in[i];
            end for;
            outlet.P = P;
            der(V) = outlet.F;               
        end FeedtankType;

        model HarvesttankType
            LiquidCon inlet;
            parameter Real P = 0.0                             "Pressure";                      
            parameter Real V_0 (unit="m3") = 1.0               "Initial harvest liquid volume";
            parameter Real[Medium.nc] m_0 
                  (each unit="kg/m3") = zeros(Medium.nc)       "Initial substance mass";
            Real[Medium.nc] m 
                  (start=m_0, each fixed=true)                 "Substance mass";
            Real[Medium.nc] c                                  "Substance conc"; 
            Real V(start=V_0, fixed=true, unit="m3")           "Harvest liquid volume";
        equation
            inlet.P = P;
            der(V) = inlet.F;
            for i in 1:Medium.nc loop
                der(m[i]) = inStream(inlet.c[i])*inlet.F;
                c[i] = m[i]/V;
            end for;               
        end HarvesttankType;

    end EquipmentLib;

  //  ---------------------------------------------------------------------------------------------
  //     Adaptation of package Equipment to Medium1
  //  ---------------------------------------------------------------------------------------------

    package Equipment
        import DEMO_v40.EquipmentLib;
        extends EquipmentLib(redeclare package Medium=Medium1);
    end Equipment;

  //  ---------------------------------------------------------------------------------------------
  //     Examples of systems
  //  ---------------------------------------------------------------------------------------------

    model Test
        Medium_data medium;
        Equipment.FeedtankType feedtank;
        Equipment.HarvesttankType harvesttank;
        Equipment.PipeType pipe;
    equation
        connect(feedtank.outlet, pipe.inlet);
        connect(pipe.outlet, harvesttank.inlet);
    end Test;

end DEMO_v40;

С этим я перешел к OMEdit и проверил каждый компонент отдельно с помощью кнопки CheckModel (Single галочка на зеленом кружке в верхней середине OMEdit). Я понял, что у вашего соединителя есть 3 неизвестных и 1 уравнение, которое является недопустимым (как я уже сказал, это должно быть соотношение 2: 1) Это также приводит к тому, что все остальные ваши компоненты являются незаконными.

Так как отладить все ваши вещи было бы вполне достаточно, я могу предоставить только то, что я когда-то сделал go для студенческого проекта, но это должно показать, что нужно сделать. Вам не нужно пропускать оба pressure и concentration, так как они должны быть алгебраически связаны в любом случае. Я использовал height вместо этого.

См. Следующий ответ для модели, он не подходит к этому (и я не могу добавить файлы здесь).

РЕДАКТИРОВАТЬ: Я только что сделал git хранилище. Гораздо проще на самом деле:

HTTPS: https://github.com/kabdelhak/TankSystem

S SH: git@github.com: kabdelhak / TankSystem. git

1 голос
/ 13 марта 2020

После некоторых размышлений я полагаю, что следующий пример преобразован для непосредственного использования потоковых переменных (хотя я согласен с тем, что было бы неплохо сделать его совместимым с MSL, как предложил @ReneJustNielsen).

package DEMO_v42

//  ---------------------------------------------------------------------------------------------
//     Interfaces  
//  ---------------------------------------------------------------------------------------------

    import Modelica.Blocks.Interfaces.RealInput;
    import Modelica.Blocks.Interfaces.RealOutput;

//  ---------------------------------------------------------------------------------------------
//     Equipment
//  ---------------------------------------------------------------------------------------------

    package EquipmentLib

        connector LiquidCon
            Real P                                             "Pressure";
            flow Real F                                        "Flow rate";
      stream Real c_outflow "Substance conc";
        end LiquidCon;

        model PipeType
            LiquidCon inlet, outlet;
            parameter Real area = 1;
        equation 
            inlet.F = -outlet.F;
            outlet.F = -area^2*(inlet.P - outlet.P);           // Linearized Bernoulli equation
            outlet.c_outflow = inStream(inlet.c_outflow);
            inlet.c_outflow=inStream(outlet.c_outflow);
        end PipeType;

        model FeedtankType
            LiquidCon outlet;
            parameter Real P = 0.1                             "Pressure";
            parameter Real V_0 = 100                           "Initial feed volume";
            parameter Real c_in = 1.0                          "Feedtank conc";
            Real V(start=V_0, fixed=true)                      "Feed volume";
        equation 
            outlet.c_outflow = c_in;
            outlet.P = P;
            der(V) = outlet.F;
        end FeedtankType;

        model HarvesttankType
            LiquidCon inlet;
            parameter Real P = 0.0                             "Pressure";
            parameter Real V_0 = 1.0                           "Initial harvest liquid volume";
            parameter Real m_0 = 0.0                           "Initial substance mass";
            Real V(start=V_0, fixed=true)                      "Harvest liquid volume";
            Real m(start=m_0, fixed=true)                      "Substance mass";
            Real c                                             "Substance conc";
            Real inletC=actualStream(inlet.c_outflow);
        equation 
            inlet.P = P;
            inlet.c_outflow=c;
            der(V) = inlet.F;
            der(m) = actualStream(inlet.c_outflow)*inlet.F;
            c = m/V;
        end HarvesttankType;
    end EquipmentLib;

//  ---------------------------------------------------------------------------------------------
//     Example of system 
//  ---------------------------------------------------------------------------------------------

    model Test
        EquipmentLib.FeedtankType feedtank;
        EquipmentLib.HarvesttankType harvesttank;
        EquipmentLib.PipeType pipe;
    equation 
        connect(feedtank.outlet, pipe.inlet);
        connect(pipe.outlet, harvesttank.inlet);
    end Test;

end DEMO_v42;

Я добавил вход C для возможности сравнения концентраций с предыдущими моделями.

Основное изменение заключается в том, что для переменной потока c_outflow фактически используются две / три различные переменные:

  • Если вам нужна концентрация, если среда вытекала, используйте c_outflow
  • Если вы хотите концентрацию, если среда текла, используйте inStream(c_outflow)
  • Если вы просто для фактической концентрации в потоке используйте actualStream(c_outflow)

Итак, для трубы вы пишете, что концентрация, вытекающая из одного порта, равна концентрации, поступающей в другой порт, и наоборот. Для резервуара вы просто пишете уравнение для c_outflow, но используете actualStream, чтобы получить фактическую концентрацию в потоке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...