bslMS / BusinessSimulation

Dynamic modeling for business, economics, and ecology using the system dynamics approach
https://bsl-support.de/BusinessSimulation/BusinessSimulation
European Union Public License 1.2
20 stars 6 forks source link

Check of v1.0.1 reports 44 errors #2

Closed dietmarw closed 2 years ago

dietmarw commented 3 years ago

I ran a quick pedantic check with Dymola on the library and got 44 errors in the library. See attached: CheckOfBusinessSimulation.log

gwr69 commented 3 years ago

@dietmarw Again, thank you for reporting these errors. I have now taken a closer look and the 44 errors break down to only three issues:

For one, there is a repeatedly reported error with regard to the unit framework in Modelica. Using custom units like Amount (e.g., thousand, million, percent, pair, and each) is open to debate, but works very nicely for the purpose of simulation in Business and Economics in Wolfram System Modeler.

Consisdering that the Modelica specifications do seem not completely worked out with regard to units I have decided not to fix this issue for now, as it will not impede running models in most tools.

There was a copy & paste error so that a Diagram annotation was used for the paramater Boolean gaming. That is a really trivial error (e.g., the Diagram annotation just needs to be deleted) and what is even better: It currently does not affect anything.

Which leaves the only "real" need for fixing: I have used a Real variable in an equation that has Boolean on the left hand side. This is a violation of variability but fortunately is totally easy to fix:

UPDATE BusinessSimulation.Functions.ConstrainedRateBoolean.mo

within BusinessSimulation.Functions;

function constrainedRateBoolean "Return true, if the indicated rate meets restrictions"
  extends BusinessSimulation.Icons.Function;
  // neagtive rate is inflow to stock
  input Boolean indRateIsInflow "Proposed rate is inflow to a connected stock";
  input Boolean stopInflow "Signal from connected stock";
  input Boolean stopOutflow "Signal from connected stock";
  output Boolean useRate "= true, if the indicated rate does not violate restrictions";
algorithm
  // set rate to zero if stopSignal matches character of flow
  useRate := if stopInflow and indRateIsInflow then false elseif stopOutflow and not indRateIsInflow then false else true;
  annotation(Documentation(info = "<html>
<p class=\"aside\">This information is part of the Business Simulation&nbsp;Library (BSL).</p>
<p>The real output <strong><code>actualRate</code> </strong>is determined by checking whether the real input <strong><code>indicatedRate</code> </strong>is complying with the restrictions signaled by a connected stock in form of the boolean flags <strong><code>stopInflow</code> </strong>and <strong><code>stopOutflow</code></strong>. If the rate is found to violate either flag <code>false</code> is returned, in all other cases <code>true</code> is&nbsp;returned.</p>
<h4>Syntax</h4>
<p>
<code>Functions.<strong>constrainedRateBoolean</strong>( indicatedRateIsInflowToStock, stopInflow, stopOutflow)</code><br>
<code>Functions.<strong>constrainedRateBoolean</strong>(indicatedRate < 0, stopInflow, stopOutflow)</code>
</p>
<h4>Examples</h4>
<br>
<pre>
Functions.constrainedRateBoolean(-5.0 < 0, stopInflow = true, stopOutflow = false); //  false
Functions.constrainedRateBoolean( 5.0 < 0, stopInflow = true, stopOutflow = false); //  true
Functions.constrainedRateBoolean(-5.0 < 0, stopInflow = false, stopOutflow = true); //  true
Functions.constrainedRateBoolean( 5.0 < 0, stopInflow = false, stopOutflow = true); //  false</pre>
<br>
<h4>Notes</h4><p>Rates are usually set by flow components and have to observe the flow-restrictions with regard to a connected stock component. By Modelica conventions a negative rate for the flow indicates an inflow with regard to the connected stock, while a positive rate indicates an outflow for the stock.</p>
<p>Thus, in the first example above the indicated negative rate for a &rarr;<a href=\"modelica://BusinessSimulation.Interfaces.Connectors.FlowPort\">FlowPort </a>would mean an outflow from the flow component and an inflow with regard to the connected &rarr;<a href=\"modelica://BusinessSimulation.Interfaces.Connectors.StockPort\">StockPort</a>. Observing the flow restriction signaled by the stock <code>false</code> is returned.</p>
<h4>See also</h4><p><a href=\"modelica://BusinessSimulation.Functions.constrainedRate\">constrainedRate</a></p>
</html>"), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})));
end constrainedRateBoolean;

UPDATE BusinessSimulation.Interfaces.PartialFlows.BidirectionalFlow.mo

within BusinessSimulation.Interfaces.PartialFlows;

partial model BidirectionalFlow "Generic bi-directional flow between two stocks"
  import BusinessSimulation.Units.Rate;
  extends Basics.GenericFlow;
  extends Icons.BidirectionalFlow;
  extends Basics.ThreeSO_rate;
protected
  // indicated rates; positive rates will drain the conected stock
  Rate A_rate "Indicated rate for portA";
  Rate B_rate "Indicated rate for portB";
  Boolean useA_rate "= true, if indicated rate for portA meets restrictions";
  Boolean useB_rate "= true, if indicated rate for portB meets restrictions";
initial equation
  // make sure that discrete vars are properly initialized
  pre(useA_rate) = Functions.constrainedRateBoolean(A_rate < 0, portA.stopInflow, portA.stopOutflow);
  pre(useB_rate) = Functions.constrainedRateBoolean(B_rate < 0, portB.stopInflow, portB.stopOutflow);
equation
  // set indicated rates according to flow rules
  A_rate = -B_rate;
  // make sure that stock constraints are met
  useA_rate = Functions.constrainedRateBoolean(A_rate < 0, portA.stopInflow, portA.stopOutflow);
  useB_rate = Functions.constrainedRateBoolean(B_rate < 0, portB.stopInflow, portB.stopOutflow);
  // set flow to zero if constraints are not met
  portA.rate = if useA_rate and useB_rate then A_rate else 0;
  portB.rate = -portA.rate;
  // report the actual rate of flow at Port A
  y = portA.rate;
  y1 = portA.rate;
  y2 = portA.rate;
  ...
end BidirectionalFlow;

UPDATE BusinessSimulation.Interfaces.PartialFlows.UnidirectionalFlow.mo

within BusinessSimulation.Interfaces.PartialFlows;

partial model UnidirectionalFlow "Flow from Stock A to Stock B"
  import BusinessSimulation.Units.Rate;
  extends Basics.GenericFlow;
  extends Icons.UnidirectionalFlow;
  extends Basics.ThreeSO_rate;
protected
  // positive rates will drain the conected stock (e.g. flow from A to B)
  Rate A_rate(min = 0) "Indicted rate for portA";
  Rate B_rate(max = 0) "Indicted rate for portB";
  Boolean useA_rate "= true, if indicated rate for portA meets constraints";
  Boolean useB_rate "= true, if indicated rate for portB meets constraints";
initial equation
  // make sure that discrete vars are properly initialized
  pre(useA_rate) = Functions.constrainedRateBoolean(A_rate < 0, portA.stopInflow, portA.stopOutflow) and A_rate > 0;
  pre(useB_rate) = Functions.constrainedRateBoolean(B_rate < 0, portB.stopInflow, portB.stopOutflow);
equation
  // set indicated rates according to flow rules
  A_rate = -B_rate;
  // make sure that stock constraints are met
  useA_rate = Functions.constrainedRateBoolean(A_rate < 0, portA.stopInflow, portA.stopOutflow) and A_rate > 0;
  useB_rate = Functions.constrainedRateBoolean(B_rate < 0, portB.stopInflow, portB.stopOutflow);
  portA.rate = if useA_rate and useB_rate then A_rate else 0;
  portB.rate = -portA.rate;
  // report the actual rate of flow at Port A
  y = portA.rate;
  y1 = portA.rate;
  y2 = portA.rate;
  ...
end UnidirectionalFlow;

This issue will be fixed in the upcoming release v1.1.0—but given the easy way to fix this as posted above, everybody should be able to fully enjoy Business Simulation on a Modelica platform neer you.

Cheers, Guido

gwr69 commented 2 years ago

The main issue (see above) is resolved in v2.0.0 which has just been released. Errors dues to custom units can be avoided by simply not making use of them outside of SystemModeler which nicely supports this feature.