Modelica Expandable Connector Best Practices
Oto minimalny działający przykład użycia niektórych rozszerzalnych złączy występujących w moich modelach:
model TestExpandableConnector
expandable connector ControlBus
extends Modelica.Icons.SignalBus;
Real signal1;
Real signal2;
end ControlBus;
ControlBus controlBus;
// example models to connect signals to
Modelica.Blocks.Math.Gain gain1;
Modelica.Blocks.Math.Gain gain2;
// and so on
equation
connect(controlBus.signal1, gain1.u);
connect(controlBus.signal2, gain2.u);
// and so on
end TestExpandableConnector;
To działa dobrze i nie ma tu żadnych obaw.
Należy zauważyć, że normalnie model ten byłby tworzony w warstwie diagramu z obiektami graficznymi i połączeniami między magistralą a komponentami (w tym przypadku zyski).
Chociaż powyższy przykład jest trywialny, w wielu rzeczywistych przykładach mam wiele połączeń wyłaniających się z tego jednego rozszerzalnego złącza. To szybko może stać się bałaganiarskie w warstwie diagramu i próbuję nauczyć się / opracować tutaj najlepsze praktyki dotyczące czyszczenia diagramów.
Jedną z opcji wydaje się być użycie bloku RealExpression w sposób prawie równoważny elementom From / Goto Simulink. Na przykład:
model TestExpandableConnectorRevised
expandable connector ControlBus
extends Modelica.Icons.SignalBus;
Real signal1;
Real signal2;
end ControlBus;
ControlBus controlBus;
// example models to connect signals to
Modelica.Blocks.Math.Gain gain1;
Modelica.Blocks.Math.Gain gain2;
// and so on
// using RealEpressions like goto tags
Modelica.Blocks.Sources.RealExpression realExpression1(y=controlBus.signal1);
Modelica.Blocks.Sources.RealExpression realExpression2(y=controlBus.signal2);
// and so on
equation
connect(realExpression1.y, gain1.u);
connect(realExpression2.y, gain2.u);
// and so on
end TestExpandableConnectorRevised;
Teraz, po tej zmianie, Dymola narzeka, że jest to nielegalne, ponieważ nie można ustalić związku przyczynowego. Wydaje się, że jestem w stanie rozwiązać ten ostatni problem przez 1) dodanie przedrostka "input" do deklaracji signal1 i signal2 w magistrali lub 2) umieszczenie deklaracji dla realExpressions przed deklaracją contolBus (to drugie rozwiązanie jest trochę dziwne dla mnie).
Ogólnie rzecz biorąc, jestem dość zadowolony z tych rozwiązań z punktu widzenia uporządkowania mojego diagramu, ale wydaje mi się, że są one co najmniej trochę „zepsute”. Moim podstawowym celem w tym pytaniu jest zbadanie, czy to podejście jest w porządku, czy też jest to zły pomysł? Dodatkowo, jeśli są jakieś inne sugestie dotyczące organizacji wszystkich połączeń w dużym modelu (szczególnie przy złączach rozszerzalnych), to jestem uszy. Jako dodatkowa myśl, wydaje mi się, że bardziej dedykowana funkcja "From / Goto" dla języka Modelica może być naprawdę fajna w Modelica, wyłącznie w celu uporządkowania diagramów, ale jest dokładnie równoważna z instrukcją connect pod maską.
Odpowiedzi
Dymola narzeka
Zmienna controlBus.signal1 jest częścią rozszerzalnego złącza i była używana tylko poza connect. Nie jest to zgodne z prawem, ponieważ nie możemy określić jego związku przyczynowego.
Twoje poprawione rozwiązanie działa, gdy tylko napiszesz gdzieś sygnał za pomocą instrukcji connect. Poniżej dodatkowo zredukowałem twój przykład, aby zawierał tylko signal1. Do ustawienia jej wartości używane jest dodatkowe wyrażenie rzeczywiste.
model TestExpandableConnectorRevised
expandable connector ControlBus
Real signal1;
end ControlBus;
ControlBus controlBus;
Modelica.Blocks.Math.Gain gain1;
Modelica.Blocks.Sources.RealExpression realExpression1(y=controlBus.signal1);
// Added to write the bus signal
Modelica.Blocks.Sources.RealExpression realExpression3(y=1);
equation
connect(realExpression1.y, gain1.u);
// Added to write the bus signal
connect(realExpression3.y, controlBus.signal1);
end TestExpandableConnectorRevised;
Ten przykład kompiluje się w trybie Dymola pedantic i OpenModelica, więc powinno być idealnie.
Alternatywne podejście z użyciem adapterów magistrali
Jak widać, złącza rozszerzalne są pełne pułapek. Problem powyżej może również zdarzyć się łatwo, jeśli zdecydujesz się zmienić nazwę signal1na mysignalna rozszerzalnej złącza, ale zapomnij zaktualizować connect oświadczenie connect(realExpression3.y, controlBus.mysignal).
Dlatego niektóre biblioteki Modelica zdecydowały się na odczyt i zapis sygnałów magistrali tylko za pośrednictwem adapterów magistrali. Musisz utworzyć 2 dodatkowe bloki dla każdej zmiennej: jeden do odczytu i jeden do zapisania jej wartości. To dużo nudnej pracy, ale pozwala uniknąć powyższego problemu.
Oto minimalny przykład do czytania i pisania signal1.
package BusAdapters
partial block BusWriter
// Dialog allows to set the value of y in the parameter window, like for the real expression
Modelica.Blocks.Interfaces.RealInput u annotation (Dialog);
ControlBus controlBus;
end BusWriter;
block Write_signal1
extends BusWriter;
equation
connect(u, controlBus.signal1);
end Write_signal1;
partial block BusReader
Modelica.Blocks.Interfaces.RealOutput y;
ControlBus controlBus;
end BusReader;
block Read_signal1
extends BusReader;
equation
connect(y, controlBus.signal1);
end Read_signal1;
expandable connector ControlBus
extends Modelica.Icons.SignalBus;
Real signal1;
end ControlBus;
model TestBusConnectors
ControlBus controlBus;
Modelica.Blocks.Math.Gain gain1;
// setting bus variables: using modifiers in write blocks
Write_signal1 write1(u=sin(time));
// accessing bus variables part 1: creating instance of reader
Read_signal1 read1;
equation
// connect all read and write blocks to the same bus instance
connect(write1.controlBus, controlBus);
connect(read1.controlBus, controlBus);
// accessing bus variables part 2: connecting reader with component of interest
connect(read1.y, gain1.u);
end TestBusConnectors;
end BusAdapters;
Graficznie będzie to wyglądać jak poniżej. xjest napisany bezpośrednio za pomocą adapterów magistrali. W przypadku yrzeczywistych wyrażeń stosuje się, aby zmniejszyć liczbę linii w większych modelach.