diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4ef2717 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ + +*.log diff --git a/.project b/.project new file mode 100644 index 0000000..22029d3 --- /dev/null +++ b/.project @@ -0,0 +1,11 @@ + + + modelica-business-simulation + + + + + + + + diff --git a/BusinessSimulation/Constants/package.mo b/BusinessSimulation/Constants/package.mo new file mode 100644 index 0000000..ef356a4 --- /dev/null +++ b/BusinessSimulation/Constants/package.mo @@ -0,0 +1,32 @@ +within BusinessSimulation; + +package Constants "Mathematical and other constants" + import BusinessSimulation.Types.TimeBases; + import BusinessSimulation.Units.Amount; + extends Icons.Package; + final constant Real e = Modelica.Constants.e "Euler's number also known as Napier's constant"; + final constant Real eps = ModelicaServices.Machine.eps "Biggest number such that 1.0 + eps = 1.0"; + final constant Real inf = Modelica.Constants.inf "Infinity"; + final constant Real INF = inf "Infinity"; + final constant Real pi = Modelica.Constants.pi "Ratio of a circle's circumference to its diameter (π)"; + final constant Real small = ModelicaServices.Machine.small "Smallest number such that small and -small are representable on the machine"; + final constant String timeBaseUnits[TimeBases] = {"s", "min", "h", "d", "wk", "mo", "qtr", "yr"} "Unit strings for model time bases"; + final constant String rateStrings[TimeBases] = {"per second", "per minute", "per hour", "per day", "per week", "per month", "per quarter", "per year"} "Rate strings for different time bases"; + final constant Real timeBaseConversionFactors[TimeBases, TimeBases] = [1, 1 / 60, 1 / 3600, 1 / 86400, 1 / 604800, 1 / 2628000, 1 / 7884000, 1 / 31536000; 60, 1, 1 / 60, 1 / 1440, 1 / 10080, 1 / 43800, 1 / 131400, 1 / 525600; 3600, 60, 1, 1 / 24, 1 / 168, 1 / 730, 1 / 2190, 1 / 8760; 86400, 1440, 24, 1, 1 / 7, 12 / 365, 4 / 365, 1 / 365; 604800, 10080, 168, 7, 1, 84 / 365, 28 / 365, 7 / 365; 2628000, 43800, 730, 365 / 12, 365 / 84, 1, 1 / 3, 1 / 12; 7884000, 131400, 2190, 365 / 4, 365 / 28, 3, 1, 1 / 4; 31536000, 525600, 8760, 365, 365 / 7, 12, 4, 1] "Conversion factors for time base conversions"; + final constant Real zero = -1e-10 "Constant that is negative but close enough to zero to be considered effectively zero"; + final constant Amount '1each' = 1 "Define the amount of one `each` for counting"; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This package contains some common constants that are considered useful for System Dynamics modeling and simulation.

+

Notes

+

It is generally advisable to set up models in SIunits of time so that they will be compatibale with models from other domains. To enter and display times and rates in a convenient fashion the displayUnit attribute should be used. This should be conveniently handled by Modelica tools which most often will allow to make such a choice by drop-down menu.

+

In that sense, the constants timeBaseUnits and timeBaseConversionFactors are usually not needed.

+

See also

+

+Tutorial.UnitsInBusinessSimulations, +TimeConversion

+
+
+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, origin = {14.3, 18.868}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, points = {{-80, -6.372}, {-80, -6.372}, {-76.12, -6.372}, {-76.12, -6.372}, {-60.75, 16.378}, {-9.64, 16.378}, {43.88, 16.378}, {43.88, 16.378}, {43.88, 32.798}, {43.88, 32.798}, {-11.12, 32.798}, {-66.12, 32.798}}, smooth = Smooth.Bezier), Polygon(visible = true, origin = {14.3, 18.868}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, points = {{16.84, 26.921}, {16.84, -51.493}, {33.13, -53.079}, {41.24, -38.779}, {41.24, -38.779}, {45.7, -38.779}, {45.7, -38.779}, {33.13, -75.549}, {6.87, -75.549}, {0, -43.079}, {5.157, 26.921}, {5.157, 26.921}, {16.84, 26.921}}, smooth = Smooth.Bezier), Polygon(visible = true, origin = {14.3, 18.868}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, points = {{-38.493, 26.921}, {-44.229, -29.502}, {-70, -66.269}, {-52.476, -76.921}, {-33.577, -66.269}, {-28.493, 26.921}, {-28.493, 26.921}, {-38.493, 26.921}}, smooth = Smooth.Bezier)})); +end Constants; diff --git a/BusinessSimulation/Constants/package.order b/BusinessSimulation/Constants/package.order new file mode 100644 index 0000000..a93c467 --- /dev/null +++ b/BusinessSimulation/Constants/package.order @@ -0,0 +1,11 @@ +e +eps +inf +INF +pi +small +timeBaseUnits +rateStrings +timeBaseConversionFactors +zero +'1each' diff --git a/BusinessSimulation/Converters/Abs.mo b/BusinessSimulation/Converters/Abs.mo new file mode 100644 index 0000000..344e2c8 --- /dev/null +++ b/BusinessSimulation/Converters/Abs.mo @@ -0,0 +1,12 @@ +within BusinessSimulation.Converters; + +model Abs "Return the absolute value of input" + extends Interfaces.PartialConverters.SISO; +equation + y = abs(u); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output y is given as the absolute value of the input u.

+

Implementation

+

The function abs() is used to compute the absolute value so no event will be generated.

", revisions = ""), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {0, 0, 128}, extent = {{-40.484, -12}, {40.484, 12}}, textString = "ABS", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Abs; diff --git a/BusinessSimulation/Converters/AccumulationFunction.mo b/BusinessSimulation/Converters/AccumulationFunction.mo new file mode 100644 index 0000000..9275e57 --- /dev/null +++ b/BusinessSimulation/Converters/AccumulationFunction.mo @@ -0,0 +1,18 @@ +within BusinessSimulation.Converters; + +block AccumulationFunction "Determing the time value of money for an investment of 1" + extends Interfaces.PartialConverters.SISO(redeclare replaceable type OutputType = Units.Dimensionless); + parameter Boolean isCCR = true "= true, if the factional rate given is assumed to be a continuously compounding rate else the rate will be converted (growing.isCCR)" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); +protected + SourcesOrSinks.ExponentialGrowth growing(hasConstantRate = false, isCCR = isCCR) annotation(Placement(visible = true, transformation(origin = {-30, -30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Stocks.InformationLevel accumulationFunction(initialValue = 1, redeclare replaceable type OutputType = Units.Dimensionless, init = BusinessSimulation.Types.InitializationOptions.FixedValue) "Growth factor according to the accumulation function" annotation(Placement(visible = true, transformation(origin = {10, -30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(growing.massPort, accumulationFunction.inflow) annotation(Line(visible = true, origin = {-10, -30}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(accumulationFunction.y, y) annotation(Line(visible = true, origin = {63.423, -6.533}, points = {{-48.423, -13.067}, {-48.423, 6.533}, {96.845, 6.533}}, color = {1, 37, 163})); + connect(u, growing.u) annotation(Line(visible = true, origin = {-71.667, -6.667}, points = {{-73.333, 6.667}, {36.667, 6.667}, {36.667, -13.333}}, color = {0, 0, 128})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The Real output y is the value of the accumulation function at any time t in the simulation given the variable rate of interest according to input u. By definition the accumulation function will give the factor to determing the future value A(t) for an investment with a present value A(0) of 1 monetary units:

+

A(t) = A(0) · a(t) = 1 · a(t)

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {0, 0, 128}, extent = {{-40.484, -12}, {40.484, 12}}, textString = "a(t)", fontName = "Lato Black", textStyle = {TextStyle.Bold, TextStyle.Italic})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end AccumulationFunction; diff --git a/BusinessSimulation/Converters/Add_2.mo b/BusinessSimulation/Converters/Add_2.mo new file mode 100644 index 0000000..3b06409 --- /dev/null +++ b/BusinessSimulation/Converters/Add_2.mo @@ -0,0 +1,12 @@ +within BusinessSimulation.Converters; + +block Add_2 "Sum of two inputs" + extends Interfaces.PartialConverters.SI2SO; +equation + y = u1 + u2; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output y is obtained as the sum of the inputs u1 and u2.

+

See also

+

Add_3Total

", revisions = ""), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, rotation = -225, points = {{15, 15}, {-15, -15}}, color = {0, 0, 128}, thickness = 4, arrowSize = 0), Line(visible = true, rotation = -315, points = {{15, 15}, {-15, -15}}, color = {0, 0, 128}, thickness = 4, arrowSize = 0)}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Add_2; diff --git a/BusinessSimulation/Converters/Add_3.mo b/BusinessSimulation/Converters/Add_3.mo new file mode 100644 index 0000000..7ff39ff --- /dev/null +++ b/BusinessSimulation/Converters/Add_3.mo @@ -0,0 +1,12 @@ +within BusinessSimulation.Converters; + +block Add_3 "Total of three inputs" + extends Interfaces.PartialConverters.SI3SO; +equation + y = u1 + u2 + u3; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output y is calculated as the sum of the inputs u1, u2, and u3.

+

See also

+

Add_2Total

", revisions = ""), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, rotation = -225, points = {{15, 15}, {-15, -15}}, color = {0, 0, 128}, thickness = 4, arrowSize = 0), Line(visible = true, rotation = -315, points = {{15, 15}, {-15, -15}}, color = {0, 0, 128}, thickness = 4, arrowSize = 0)}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Add_3; diff --git a/BusinessSimulation/Converters/Clip.mo b/BusinessSimulation/Converters/Clip.mo new file mode 100644 index 0000000..e8ac465 --- /dev/null +++ b/BusinessSimulation/Converters/Clip.mo @@ -0,0 +1,33 @@ +within BusinessSimulation.Converters; + +block Clip "Clips input signal so that it remains within a given interval" + import Modelica.Blocks.Types.{LimiterHomotopy,VariableLimiterHomotopy}; + import BusinessSimulation.Constants.inf; + extends Interfaces.PartialConverters.SISO; + Interfaces.Connectors.RealInput u_max if not hasConstantLimits "Upper limit input" annotation(Placement(visible = true, transformation(origin = {-145, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, 50}, extent = {{-10, 10}, {10, -10}}, rotation = 0))); + Interfaces.Connectors.RealInput u_min if not hasConstantLimits "Lower limit input" annotation(Placement(visible = true, transformation(origin = {-145, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, -50}, extent = {{-10, 10}, {10, -10}}, rotation = 0))); + parameter Real maxValue = inf "Maximum value (default = infinity)" annotation(Dialog(enable = hasConstantLimits)); + parameter Real minValue = -maxValue "Minimum value (default = - infinity)" annotation(Dialog(enable = hasConstantLimits)); + parameter Boolean hasConstantLimits = true "= true, if the limits are constant" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean strict = true "= true, if strict limits with noEvent(..) (constantLimiter.strict)" annotation(Evaluate = true, Dialog(tab = "Advanced")); + parameter LimiterHomotopy homotopyType = LimiterHomotopy.Linear "Simplified model for homotopy-based initialization (constantLimiter.homotopyType)" annotation(Evaluate = true, Dialog(tab = "Advanced")); + parameter VariableLimiterHomotopy variableHomotopyType = VariableLimiterHomotopy.Linear "Simplified model for homotopy-based initialization (variableLimiter.homotopyType)" annotation(Evaluate = true, Dialog(tab = "Advanced")); +protected + Modelica.Blocks.Nonlinear.VariableLimiter variableLimiter(strict = strict, homotopyType = variableHomotopyType) if not hasConstantLimits "Clip input to variable limits" annotation(Placement(visible = true, transformation(origin = {0, -20}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Modelica.Blocks.Nonlinear.Limiter constantLimiter(uMax = maxValue, uMin = minValue, strict = strict, homotopyType = homotopyType) if hasConstantLimits "Clip input to constant limits" annotation(Placement(visible = true, transformation(origin = {0, 30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(u, constantLimiter.u) annotation(Line(visible = true, origin = {-76.75, 15}, points = {{-68.25, -15}, {16.75, -15}, {16.75, 15}, {64.75, 15}}, color = {0, 0, 128})); + connect(constantLimiter.y, y) annotation(Line(visible = true, origin = {75.317, 15}, points = {{-64.317, 15}, {4.683, 15}, {4.683, -15}, {84.951, -15}}, color = {1, 37, 163})); + connect(u, variableLimiter.u) annotation(Line(visible = true, origin = {-69.25, -10}, points = {{-75.75, 10}, {9.25, 10}, {9.25, -10}, {57.25, -10}}, color = {0, 0, 128})); + connect(u_max, variableLimiter.limit1) annotation(Line(visible = true, origin = {-78.845, 14}, points = {{-66.155, 26}, {-1.155, 26}, {-1.155, -26}, {66.845, -26}}, color = {0, 0, 128})); + connect(u_min, variableLimiter.limit2) annotation(Line(visible = true, origin = {-79.25, -34}, points = {{-65.75, -6}, {-0.75, -6}, {-0.75, 6}, {67.25, 6}}, color = {0, 0, 128})); + connect(variableLimiter.y, y) annotation(Line(visible = true, origin = {82.817, -10}, points = {{-71.817, -10}, {-2.817, -10}, {-2.817, 10}, {77.451, 10}}, color = {1, 37, 163})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The input u will be clipped to make sure that it is within the interval [minValue, maxValue] before it is given as output y. Alternatively, variable inputs can be used to set the limits (hasConstantLimits = false).

+

Implementation

+

The component internally uses the →Limiter and the →VariableLimiter from the Modelica Standard Library.

+

See also

+

Functions.clip, Vector.ClipClipProcessTimeZeroIfNegative 

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {0, 0, 128}, extent = {{-36.812, -12}, {36.812, 12}}, textString = "CLIP", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Clip; diff --git a/BusinessSimulation/Converters/ClipProcessTime.mo b/BusinessSimulation/Converters/ClipProcessTime.mo new file mode 100644 index 0000000..a30bceb --- /dev/null +++ b/BusinessSimulation/Converters/ClipProcessTime.mo @@ -0,0 +1,26 @@ +within BusinessSimulation.Converters; + +block ClipProcessTime "Limit any time input to be no smaller than dt" + extends Interfaces.PartialConverters.SISO(redeclare replaceable type OutputType = Units.Time); + parameter Boolean strict = true "= true, if strict limits with noEvent(..)" annotation(Evaluate = true, Dialog(tab = "Advanced")); +protected + outer ModelSettings modelSettings; +equation + if strict then + y = smooth(0, noEvent(if u < modelSettings.dt then modelSettings.dt else u)); + else + y = smooth(0, if u < modelSettings.dt then modelSettings.dt else u); + end if; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The global parameter modelSettings.dt gives the smallest possible average duration for any explicitly modeled process within a model (e.g. the shortest possible delay time). The time input u (usually a duration) will thus be clipped so that the output y will never be smaller than dt.

+

Implementation

+

In the default setting (strict = true) in the Advanced tab no events will be generated:

+
if strict then 
+    y = smooth(0, noEvent(if u < modelSettings.dt then modelSettings.dt else u));
+  else
+    y = smooth(0, if u < modelSettings.dt then modelSettings.dt else u);
+  end if;

+

See also

+

ClipZeroIfNegative

"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {0, 0, 128}, extent = {{-58.305, -12}, {58.305, 12}}, textString = "CLIP", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {0, -20}, textColor = {128, 128, 128}, extent = {{-58.305, -9}, {58.305, 9}}, textString = "Process Time", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end ClipProcessTime; diff --git a/BusinessSimulation/Converters/ConstantConverter.mo b/BusinessSimulation/Converters/ConstantConverter.mo new file mode 100644 index 0000000..aee6ffa --- /dev/null +++ b/BusinessSimulation/Converters/ConstantConverter.mo @@ -0,0 +1,15 @@ +within BusinessSimulation.Converters; + +block ConstantConverter "A constant value is turned into a constant signal" + extends Icons.ConstantConverter; + extends Interfaces.Basics.OutputTypeChoice; + RealOutput y "Constant output signal" annotation(Placement(visible = true, transformation(origin = {161.795, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {60, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + parameter OutputType value "Value of constant output"; +equation + y = value; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The parameter value is used to set the continous output y making it a constant-valued signal.

+

See also

+

ConstantConverterRateConstantConverterTimeConstantConverterBoolean

", revisions = ""), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Ellipse(visible = true, lineColor = {0, 0, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-28.253, -28.253}, {28.253, 28.253}}), Line(visible = true, rotation = -270, points = {{0, 40}, {0, -40}}, color = {0, 0, 128}, thickness = 3), Text(visible = true, origin = {0, 60}, textColor = {0, 0, 128}, extent = {{-100, -6}, {100, 6}}, textString = "%value", fontName = "Lato")}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Ellipse(visible = true, lineColor = {0, 0, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-20, -20}, {20, 20}}), Line(visible = true, origin = {0, -0.205}, rotation = -810, points = {{-30, 0}, {30, 0}}, color = {0, 0, 128}, thickness = 5), Text(visible = true, origin = {-50, 0}, textColor = {128, 0, 128}, extent = {{-44.917, -32.251}, {44.917, 32.251}}, textString = "%value", fontSize = 30, fontName = "Arial"), Text(visible = true, origin = {0, -56.852}, textColor = {128, 0, 128}, extent = {{-141.113, -29.508}, {141.113, 29.508}}, textString = "%name", fontName = "Arial")}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end ConstantConverter; diff --git a/BusinessSimulation/Converters/ConstantConverterRate.mo b/BusinessSimulation/Converters/ConstantConverterRate.mo new file mode 100644 index 0000000..32d63ee --- /dev/null +++ b/BusinessSimulation/Converters/ConstantConverterRate.mo @@ -0,0 +1,31 @@ +within BusinessSimulation.Converters; + +block ConstantConverterRate "A constant rate is turned into a constant-valued signal" + import BusinessSimulation.Units.{Rate,Dimensionless}; + import BusinessSimulation.Types.TimeBases; + extends Icons.ConstantConverter; + extends Interfaces.Basics.OutputTypeChoice_Rate; + replaceable type ValueType = Types.Reals "Basic type for the quantity that is transported per unit of time"; + RealOutput y "Constant output signal" annotation(Placement(visible = true, transformation(origin = {161.795, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {60, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + parameter ValueType value "Constant rate given in unit and displayUnit pertaining to ValueType per time base"; + parameter String timeBaseString = "second" "Time base of the rate entered (default = second)" annotation(choices(choice = "second", choice = "minute", choice = "hour", choice = "day", choice = "week", choice = "month", choice = "quarter", choice = "year")); +protected + parameter TimeBases timeBase = Functions.stringToTimeBase(timeBaseString) "Element of the enumeration TimeBases corresponding to the timeBase given as string" annotation(Dialog(tab = "Initialization", enable = false)); + ConstantConverter rateInTimeBase(value = value) annotation(Placement(visible = true, transformation(origin = {0, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + RateConversion convertRate(timeBaseA = timeBase, timeBaseB = TimeBases.seconds) "Convert the rate input to a rate per seconds" annotation(Placement(visible = true, transformation(origin = {70, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(convertRate.y, y) annotation(Line(visible = true, origin = {119.897, 0}, points = {{-41.897, 0}, {41.897, -0}}, color = {1, 37, 163})); + connect(rateInTimeBase.y, convertRate.u) annotation(Line(visible = true, origin = {34, 0}, points = {{-28, -0}, {28, 0}}, color = {1, 37, 163})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The parameter value is used to set the continous output y making it a constant-valued signal. The output will always give rates per second, but rates can be entered in non-SI-units of time using the parameter timeBaseString.

+

Notes

+ +

See also

+

ConstantConverterConstantConverterTime

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Ellipse(visible = true, lineColor = {0, 0, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-28.253, -28.253}, {28.253, 28.253}}), Line(visible = true, rotation = -270, points = {{0, 40}, {0, -40}}, color = {0, 0, 128}, thickness = 3), Text(visible = true, origin = {0, 60}, textColor = {0, 0, 128}, extent = {{-100, -6}, {100, 6}}, textString = "%value per %timeBaseString", fontName = "Lato")}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Ellipse(visible = true, lineColor = {0, 0, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-20, -20}, {20, 20}}), Line(visible = true, origin = {0, -0.205}, rotation = -810, points = {{-30, 0}, {30, 0}}, color = {0, 0, 128}, thickness = 5), Text(visible = true, origin = {-50, 0}, textColor = {128, 0, 128}, extent = {{-44.917, -32.251}, {44.917, 32.251}}, textString = "%value", fontSize = 30, fontName = "Arial"), Text(visible = true, origin = {0, -56.852}, textColor = {128, 0, 128}, extent = {{-141.113, -29.508}, {141.113, 29.508}}, textString = "%name", fontName = "Arial")}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end ConstantConverterRate; diff --git a/BusinessSimulation/Converters/ConstantConverterTime.mo b/BusinessSimulation/Converters/ConstantConverterTime.mo new file mode 100644 index 0000000..2c26f51 --- /dev/null +++ b/BusinessSimulation/Converters/ConstantConverterTime.mo @@ -0,0 +1,16 @@ +within BusinessSimulation.Converters; + +block ConstantConverterTime "A constant time value is turned into a constant signal" + import BusinessSimulation.Units.Time; + extends Icons.ConstantConverter; + extends Interfaces.Basics.OutputTypeChoice_Time; + RealOutput y "Constant value of time in the time base given" annotation(Placement(visible = true, transformation(origin = {161.795, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {60, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + parameter OutputType value "Constant value of time"; +equation + y = value; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The parameter value is used to set the continous output y making it a constant-valued signal. The output will always give times in seconds [s], but values can be entered in non-SI-units of time using displayUnit.

+

See also

+

ConstantConverterConstantConverterRate

"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Ellipse(visible = true, lineColor = {0, 0, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-28.253, -28.253}, {28.253, 28.253}}), Line(visible = true, rotation = -270, points = {{0, 40}, {0, -40}}, color = {0, 0, 128}, thickness = 3), Text(visible = true, origin = {0, 60}, textColor = {0, 0, 128}, extent = {{-100, -6}, {100, 6}}, textString = "%value", fontName = "Lato")}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Ellipse(visible = true, lineColor = {0, 0, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-20, -20}, {20, 20}}), Line(visible = true, origin = {0, -0.205}, rotation = -810, points = {{-30, 0}, {30, 0}}, color = {0, 0, 128}, thickness = 5), Text(visible = true, origin = {-50, 0}, textColor = {128, 0, 128}, extent = {{-44.917, -32.251}, {44.917, 32.251}}, textString = "%value", fontSize = 30, fontName = "Arial"), Text(visible = true, origin = {0, -56.852}, textColor = {128, 0, 128}, extent = {{-141.113, -29.508}, {141.113, 29.508}}, textString = "%name", fontName = "Arial")}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end ConstantConverterTime; diff --git a/BusinessSimulation/Converters/DiscreteDelay/DelayFixed.mo b/BusinessSimulation/Converters/DiscreteDelay/DelayFixed.mo new file mode 100644 index 0000000..d242adb --- /dev/null +++ b/BusinessSimulation/Converters/DiscreteDelay/DelayFixed.mo @@ -0,0 +1,83 @@ +within BusinessSimulation.Converters.DiscreteDelay; + +model DelayFixed "Pipeline information delay without awareness" + import BusinessSimulation.Types.InitializationOptions; + import BusinessSimulation.Units.Time; + import BusinessSimulation.Constants.inf; + extends Interfaces.PartialConverters.SmoothSISO; + Interfaces.Connectors.RealInput u_history if hasExogenousHistory "Historical input to be used in an initial period (up to maximumDelaytime)" annotation(Placement(visible = true, transformation(origin = {-145, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-50, 50}, extent = {{-10, 10}, {10, -10}}, rotation = -810))); + Interfaces.Connectors.RealOutput y_lookupTime if hasExogenousHistory "Time for looking up historical input" annotation(Placement(visible = true, transformation(origin = {160, 70}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, 30}, extent = {{10, -10}, {-10, 10}}, rotation = -360))); + Interfaces.Connectors.RealInput u_delayTime if not hasConstantDelayTime "Delay time input" annotation(Placement(visible = true, transformation(origin = {-145, 60}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {0, 50}, extent = {{-10, 10}, {10, -10}}, rotation = -810))); + parameter Time delayTime(min = modelSettings.dt) = 1 "Constant delay time (optional)" annotation(Dialog(enable = hasConstantDelayTime)); + parameter Time maximumDelayTime = 50 "Maximal value allowed for delay time (needed for variable delay time)" annotation(Evaluate = true, Dialog(enable = not hasConstantDelayTime)); + parameter Real initialValue = 0 "Initial constant output, if no exogenous history is given" annotation(Dialog(enable = not init == InitializationOptions.SteadyState and not hasExogenousHistory)); + parameter Boolean hasConstantDelayTime = true "= true, if the delay time is given by the parameter 'delayTime'" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean hasExogenousHistory = false "= true, if the input 'u_history' gives the output for an initial period, otherwise the initial output will remain constant until delayTime is reached" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter InitializationOptions init = modelSettings.init "Provide InitializationOptions (Free, FixedValue, SteadyState)" annotation(Evaluate = true, Dialog(tab = "Advanced")); + outer ModelSettings modelSettings; +protected + parameter Real initialOutput(start = initialValue, fixed = false) "Constant output if no exogenous history is provided; initialOutput.start = initialValue" annotation(Dialog(tab = "Initialization", enable = false)); + parameter Time initialDelayTime(fixed = false) "Delay time at initial time" annotation(Dialog(tab = "Initialization", enable = false)); + Add_2 historyHorizon "The modelStartTime plus the actual delayTime" annotation(Placement(visible = true, transformation(origin = {10, 55}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + ConstantConverterTime parStartTime(value = modelSettings.modelStartTime) "The model's start time" annotation(Placement(visible = true, transformation(origin = {-32.804, 50}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + ConstantConverterTime parDelayTime(value = delayTime) if hasConstantDelayTime "Constant delay time (optional)" annotation(Placement(visible = true, transformation(origin = {-130, 40}, extent = {{10, 10}, {-10, -10}}, rotation = 180))); + ConstantConverter parInitialOutput(value = initialOutput) if not hasExogenousHistory "Initial output if not history is given" annotation(Placement(visible = true, transformation(origin = {-120, -80}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Clip clippedDelayTime(minValue = modelSettings.dt, maxValue = if not hasConstantDelayTime then maximumDelayTime else inf) "DelayTime has to be in the interval (dt, maximumDelayTime)" annotation(Placement(visible = true, transformation(origin = {-85, 60}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Modelica.Blocks.Nonlinear.VariableDelay delayedInput(delayMax = maximumDelayTime) if not hasConstantDelayTime annotation(Placement(visible = true, transformation(origin = {-10, -30}, extent = {{-10, 10}, {10, -10}}, rotation = 0))); + PassThrough history annotation(Placement(visible = true, transformation(origin = {-50, -60}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + InformationSources.TimeInput clock "Provide time since start time (=0)" annotation(Placement(visible = true, transformation(origin = {65, 95}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Logical.Less historyNeededQ "Is historical trajectory needed for output?" annotation(Placement(visible = true, transformation(origin = {60, 30}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Logical.Switch switchedOutput "Either return historical value or delayed input" annotation(Placement(visible = true, transformation(origin = {60, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Modelica.Blocks.Nonlinear.FixedDelay delayedInputConstant(delayTime = delayTime) if hasConstantDelayTime "Delayed input with constant delay time" annotation(Placement(visible = true, transformation(origin = {-10, 10}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Gap lookupTime if hasExogenousHistory "Time that needs to be looked up in historical input data" annotation(Placement(visible = true, transformation(origin = {90, 70}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +initial equation + initialDelayTime = clippedDelayTime.y; + if init == InitializationOptions.FixedValue then + initialOutput = initialValue; + elseif init == InitializationOptions.SteadyState then + initialOutput = u; + end if; +equation + connect(u_delayTime, clippedDelayTime.u) annotation(Line(visible = true, origin = {-102, 50}, points = {{-43, 10}, {2, 10}, {2, 10}, {9, 10}}, color = {1, 37, 163})); + connect(u_history, history.u) annotation(Line(visible = true, origin = {-85.75, -50}, points = {{-59.25, 10}, {5.75, 10}, {5.75, -10}, {27.75, -10}}, color = {1, 37, 163})); + connect(parInitialOutput.y, history.u) annotation(Line(visible = true, origin = {-83.25, -70}, points = {{-31.75, -10}, {3.25, -10}, {3.25, 10}, {25.25, 10}}, color = {1, 37, 163})); + connect(clock.y, historyNeededQ.u1) annotation(Line(visible = true, origin = {65, 62.819}, points = {{0, 24.819}, {0, -24.819}}, color = {1, 37, 163})); + connect(historyNeededQ.y, switchedOutput.u_cond) annotation(Line(visible = true, origin = {60.006, 15.156}, points = {{-0.006, 7.481}, {-0.006, -0.156}, {0.006, -0.156}, {0.006, -7.168}}, color = {1, 37, 163})); + connect(delayedInput.y, switchedOutput.u2) annotation(Line(visible = true, origin = {16.25, -17.5}, points = {{-15.25, -12.5}, {-10.25, -12.5}, {-10.25, 12.5}, {35.75, 12.5}}, color = {1, 37, 163})); + connect(switchedOutput.y, y) annotation(Line(visible = true, origin = {113.681, 0}, points = {{-46.319, 0}, {46.319, 0}}, color = {1, 37, 163})); + connect(history.y, switchedOutput.u1) annotation(Line(visible = true, origin = {27.341, -27.5}, points = {{-69.979, -32.5}, {12.659, -32.5}, {12.659, 32.5}, {24.659, 32.5}}, color = {1, 37, 163})); + connect(u, delayedInput.u) annotation(Line(visible = true, origin = {-85.5, -2.5}, points = {{-84.5, 2.5}, {45.5, 2.5}, {45.5, -27.5}, {63.5, -27.5}}, color = {1, 37, 163})); + connect(u, delayedInputConstant.u) annotation(Line(visible = true, origin = {-78.423, 5}, points = {{-91.577, -5}, {38.423, -5}, {38.423, 5}, {56.423, 5}}, color = {1, 37, 163})); + connect(delayedInputConstant.y, switchedOutput.u2) annotation(Line(visible = true, origin = {28.25, 2.5}, points = {{-27.25, 7.5}, {-8.25, 7.5}, {-8.25, -7.5}, {23.75, -7.5}}, color = {1, 37, 163})); + connect(parDelayTime.y, clippedDelayTime.u) annotation(Line(visible = true, origin = {-98.25, 50}, points = {{-26.75, -10}, {-11.75, -10}, {-11.75, 10}, {5.25, 10}}, color = {1, 37, 163})); + connect(clippedDelayTime.y, delayedInput.delayTime) annotation(Line(visible = true, origin = {-74.106, 25.333}, points = {{-3.532, 34.667}, {14.106, 34.667}, {14.106, -49.333}, {52.106, -49.333}}, color = {1, 37, 163})); + connect(clippedDelayTime.y, lookupTime.u2) annotation(Line(visible = true, origin = {-31.409, 62.5}, points = {{-46.228, -2.5}, {-33.591, -2.5}, {-33.591, 2.5}, {113.409, 2.5}}, color = {1, 37, 163})); + connect(clock.y, lookupTime.u1) annotation(Line(visible = true, origin = {70.667, 79.213}, points = {{-5.667, 8.425}, {-5.667, -4.213}, {11.333, -4.213}}, color = {1, 37, 163})); + connect(lookupTime.y, y_lookupTime) annotation(Line(visible = true, origin = {129, 70}, points = {{-31, 0}, {31, 0}}, color = {1, 37, 163})); + connect(parStartTime.y, historyHorizon.u2) annotation(Line(visible = true, origin = {-12.402, 50}, points = {{-14.402, -0}, {14.402, 0}}, color = {1, 37, 163})); + connect(clippedDelayTime.y, historyHorizon.u1) annotation(Line(visible = true, origin = {-28.75, 57.5}, points = {{-48.25, 2.5}, {8.75, 2.5}, {8.75, 2.5}, {30.75, 2.5}}, color = {1, 37, 163})); + connect(historyHorizon.y, historyNeededQ.u2) annotation(Line(visible = true, origin = {42.667, 49.333}, points = {{-24.667, 5.667}, {12.333, 5.667}, {12.333, -11.333}}, color = {1, 37, 163})); + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {0, 0, 128}, extent = {{-99.005, -12}, {99.005, 12}}, textString = "DELAY FIXED", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The real output y is the real input delayed by a fixed delay time which can be constant (delayTime) or variable (u_delayTime) during the simulation.

+

y[t] = u[t - delayTime]

+

The input signal is thus effectively shifted forward in time.

+

During an initial period (at most as long as the initial delayTime or the maximumDelayTime when the delay time can vary over time), we need to provide information about the historical input u (e.g. the input before the start time of the simulation). The historical input can either be given by a constant value (either the initialValue or the initial input u) or by a function of time (usually a TableFunction), that will take the output connector y_timeHistory  as input and then provide the relevant historical input via the input connector u_history.

+

Notes

+ + +

See also

+

DelayInformationSmooth, SmoothNConveyor

+")); +end DelayFixed; diff --git a/BusinessSimulation/Converters/DiscreteDelay/DelayInformation.mo b/BusinessSimulation/Converters/DiscreteDelay/DelayInformation.mo new file mode 100644 index 0000000..2fdc0ad --- /dev/null +++ b/BusinessSimulation/Converters/DiscreteDelay/DelayInformation.mo @@ -0,0 +1,102 @@ +within BusinessSimulation.Converters.DiscreteDelay; + +model DelayInformation "Pipeline information delay with awareness" + import BusinessSimulation.Types.InitializationOptions; + import BusinessSimulation.Units.Time; + import BusinessSimulation.Constants.{inf,small}; + extends Interfaces.PartialConverters.SmoothSISO; + Interfaces.Connectors.RealInput u_history if hasExogenousHistory "Input of recent history (start time - initial delay time)" annotation(Placement(visible = true, transformation(origin = {-145, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-50, 50}, extent = {{-10, 10}, {10, -10}}, rotation = -810))); + Interfaces.Connectors.RealOutput y_lookupTime if hasExogenousHistory "Time for looking up historical input" annotation(Placement(visible = true, transformation(origin = {158.118, 65}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, 30}, extent = {{10, -10}, {-10, 10}}, rotation = -360))); + Interfaces.Connectors.RealInput u_delayTime if not hasConstantDelayTime "Delay time input" annotation(Placement(visible = true, transformation(origin = {-145, 60}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {0, 50}, extent = {{-10, 10}, {10, -10}}, rotation = -810))); + parameter Time delayTime(min = modelSettings.dt) = 1 "Constant delay time (optional)" annotation(Dialog(enable = hasConstantDelayTime)); + parameter Time maximumDelayTime = 50 "Maximal value allowed for delay time (needed for variable delay time)" annotation(Evaluate = true, Dialog(enable = not hasConstantDelayTime)); + parameter OutputType initialValue = 0 "Initial constant output, if no exogenous history is given" annotation(Dialog(enable = not init == InitializationOptions.SteadyState and not hasExogenousHistory)); + parameter Boolean hasConstantDelayTime = true "= true, if the delay time is given by the parameter 'delayTime'" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean hasExogenousHistory = false "= true, if the input 'u_history' gives the output for an initial period, otherwise the initial output will remain constant until delayTime is reached" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter InitializationOptions init = modelSettings.init "Provide InitializationOptions (Free, FixedValue, SteadyState)" annotation(Evaluate = true, Dialog(tab = "Advanced")); + parameter Time samplingPeriod(min = small, max = modelSettings.dt) = modelSettings.samplingPeriod "Interval at which to check for increases in delay time" annotation(Evaluate = true, Dialog(tab = "Advanced")); + outer ModelSettings modelSettings; +protected + // variables + parameter Real initialOutput(start = initialValue, fixed = false) "Constant output if no exogenous history is provided" annotation(Dialog(tab = "Initialization", enable = false)); + parameter Time initialDelayTime(fixed = false) "Delay time at initial time" annotation(Dialog(tab = "Initialization", enable = false)); + Time t_delayed "Time stamp for the delayed time (if less than zero => use historical input)"; + discrete Real sampledDelayedInformation "Delayed information sampled when the delay time increased"; + discrete Time t_sample "Time, when the delay time last increased"; + // components + ConstantConverterTime parDelayTime(value = delayTime) if hasConstantDelayTime "Constant delay time (optional)" annotation(Placement(visible = true, transformation(origin = {-87.5, 40}, extent = {{10, 10}, {-10, -10}}, rotation = 180))); + ConstantConverter parInitialOutput(value = initialOutput) if not hasExogenousHistory "Initial output if not history is given" annotation(Placement(visible = true, transformation(origin = {-77.5, -80}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Clip clippedDelayTime(minValue = modelSettings.dt, maxValue = if not hasConstantDelayTime then maximumDelayTime else inf) "DelayTime has to be in the interval (dt, maximumDelayTime)" annotation(Placement(visible = true, transformation(origin = {-42.5, 60}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Modelica.Blocks.Nonlinear.VariableDelay delayedInput(delayMax = maximumDelayTime) if not hasConstantDelayTime annotation(Placement(visible = true, transformation(origin = {27.5, -30}, extent = {{-10, 10}, {10, -10}}, rotation = 0))); + PassThrough history annotation(Placement(visible = true, transformation(origin = {-7.5, -60}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Modelica.Blocks.Nonlinear.FixedDelay delayedInputConstant(delayTime = delayTime) if hasConstantDelayTime "Delayed input with constant delay time" annotation(Placement(visible = true, transformation(origin = {27.5, 10}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + PassThrough delayedInformation "Delayed input to use for further processing" annotation(Placement(visible = true, transformation(origin = {70, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + InformationSources.TimeInput clock "Provide time starting with 0" annotation(Placement(visible = true, transformation(origin = {45, 85}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Gap lookupTime if hasExogenousHistory "Time that needs to be looked up in historical input data" annotation(Placement(visible = true, transformation(origin = {90, 65}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +initial equation + initialDelayTime = clippedDelayTime.y; + if init == InitializationOptions.FixedValue then + initialOutput = initialValue; + elseif init == InitializationOptions.SteadyState then + initialOutput = u; + end if; + pre(t_sample) = modelSettings.modelStartTime - initialDelayTime; + pre(sampledDelayedInformation) = delayedInformation.y; +algorithm + // check for increase in delay time at samplingPeriod-intervals + when sample(modelSettings.modelStartTime + samplingPeriod, samplingPeriod) then + if noEvent(pre(clippedDelayTime.y) < clippedDelayTime.y) then + // sample delayed information and store the time of sampling + t_sample := clock.y; + sampledDelayedInformation := pre(delayedInformation.y); + end if; + end when; + t_delayed := max(t_sample, clock.y - clippedDelayTime.y); + // while the historical information is more recent (e.g t_delayed < 0), use it + // otherwise decide if the last sample or the actual delayed information is more recent + y := if t_delayed < modelSettings.modelStartTime then history.y elseif t_sample > clock.y - clippedDelayTime.y then sampledDelayedInformation else delayedInformation.y; +equation + connect(u_delayTime, clippedDelayTime.u) annotation(Line(visible = true, origin = {-59.5, 50}, points = {{-85.5, 10}, {2, 10}, {2, 10}, {9, 10}}, color = {1, 37, 163})); + connect(u_history, history.u) annotation(Line(visible = true, origin = {-43.25, -50}, points = {{-101.75, 10}, {5.75, 10}, {5.75, -10}, {27.75, -10}}, color = {1, 37, 163})); + connect(parInitialOutput.y, history.u) annotation(Line(visible = true, origin = {-40.75, -70}, points = {{-31.75, -10}, {3.25, -10}, {3.25, 10}, {25.25, 10}}, color = {1, 37, 163})); + connect(u, delayedInput.u) annotation(Line(visible = true, origin = {-43, -2.5}, points = {{-127, 2.5}, {5.5, 2.5}, {5.5, -27.5}, {58.5, -27.5}}, color = {1, 37, 163})); + connect(u, delayedInputConstant.u) annotation(Line(visible = true, origin = {-35.923, 5}, points = {{-134.077, -5}, {-1.577, -5}, {-1.577, 5}, {51.423, 5}}, color = {1, 37, 163})); + connect(parDelayTime.y, clippedDelayTime.u) annotation(Line(visible = true, origin = {-55.75, 50}, points = {{-26.75, -10}, {-11.75, -10}, {-11.75, 10}, {5.25, 10}}, color = {1, 37, 163})); + connect(clippedDelayTime.y, delayedInput.delayTime) annotation(Line(visible = true, origin = {-31.606, 25.333}, points = {{-3.532, 34.667}, {31.606, 34.667}, {31.606, -49.333}, {47.106, -49.333}}, color = {1, 37, 163})); + connect(delayedInputConstant.y, delayedInformation.u) annotation(Line(visible = true, origin = {46.875, 5}, points = {{-8.375, 5}, {-3.375, 5}, {-3.375, -5}, {15.125, -5}}, color = {1, 37, 163})); + connect(delayedInput.y, delayedInformation.u) annotation(Line(visible = true, origin = {46.875, -15}, points = {{-8.375, -15}, {-3.375, -15}, {-3.375, 15}, {15.125, 15}}, color = {1, 37, 163})); + connect(clock.y, lookupTime.u1) annotation(Line(visible = true, origin = {63.591, 77.5}, points = {{-11.228, 7.5}, {-3.591, 7.5}, {-3.591, -7.5}, {18.409, -7.5}}, color = {1, 37, 163})); + connect(clippedDelayTime.y, lookupTime.u2) annotation(Line(visible = true, origin = {41.716, 62.5}, points = {{-76.853, -2.5}, {18.284, -2.5}, {18.284, -2.5}, {40.284, -2.5}}, color = {1, 37, 163})); + connect(lookupTime.y, y_lookupTime) annotation(Line(visible = true, origin = {128.059, 65}, points = {{-30.059, 0}, {30.059, 0}}, color = {1, 37, 163})); + annotation(Diagram(coordinateSystem(extent = {{-148.5, -100}, {146.892, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, 12.5}, textColor = {0, 0, 128}, extent = {{-99.005, -12}, {99.005, 12}}, textString = "DELAY", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {0, -12.5}, textColor = {0, 0, 128}, extent = {{-100, -12}, {100, 12}}, textString = "INFORMATION", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The real output y is the real input delayed by a fixed delay time which can be constant (delayTime) or variable (u_delayTime) during the simulation.

+

y[t] = u[t - delayTime]

+

The input signal is thus effectively shifted forward in time.

+

During an initial period (at most as long as the initial delayTime or the maximumDelayTime when the delay time can vary over time), we need to provide information about the historical input u (e.g. the input before the start time of the simulation). The historical input can either be given by a constant value (either the initialValue or the initial input u) or by a function of time (usually a TableFunction), that will take the output connector y_timeHistory  as input and then provide the relevant historical input via the input connector u_history.

+

Given, that the delay time may be variable, we must distinguish two kinds of changes:

+ +

Implementation

+

Internally a TimeInput component is used to provide a clock starting at modelSettings.modelStartTime. Whenever the clipped delay time increases, the delayed information and the time it was sampled (t_sampled) will be stored. As long as max(t_sampled, clock.y - clippedDelayTime.y) is less than modelSetting.modelStartTime, the historical information (either the constant initialValue or the input u_hist) is reported as output y.

+

Once the current delayed output becomes more recent (either because time has proceeded beyond the initial delay time or the current delay time has significantly decreased), it will be used. From then on, the last stored information (e.g. information that is on hold due to an increase in delay time) will be compared with the currently delayed information output and whatever is more recent will be returned.

+

As checking for increases in the delay time can introduce a lot of events, the checks will only be done a regular time events given by the parameter samplingPeriod in the Advanced tab. 

+

Notes

+ +

See also

+

DelayFixedSmooth, SmoothNConveyor

+")); +end DelayInformation; diff --git a/BusinessSimulation/Converters/DiscreteDelay/SampleIfTrue.mo b/BusinessSimulation/Converters/DiscreteDelay/SampleIfTrue.mo new file mode 100644 index 0000000..e9f2eb9 --- /dev/null +++ b/BusinessSimulation/Converters/DiscreteDelay/SampleIfTrue.mo @@ -0,0 +1,42 @@ +within BusinessSimulation.Converters.DiscreteDelay; + +block SampleIfTrue "Samples input, if Boolean trigger is true" + import BusinessSimulation.Types.InitializationOptions; + extends Interfaces.PartialConverters.SmoothSISO(redeclare discrete RealOutput y); + extends Icons.DiscreteSmoothLabel; + Interfaces.Connectors.BooleanInput trigger "Triggers sampling upon `true`" annotation(Placement(visible = true, transformation(origin = {-145, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {0.12, 49.88}, extent = {{-10.12, -10.12}, {10.12, 10.12}}, rotation = -450))); + parameter OutputType initialValue = 0 "Initial Value to be reported before sampling starts" annotation(Dialog(enable = not init == InitializationOptions.SteadyState)); + parameter InitializationOptions init = modelSettings.init "Provide InitializationOptions (Free, FixedValue, SteadyState)" annotation(Evaluate = true, Dialog(tab = "Advanced")); + outer ModelSettings modelSettings; +protected + parameter Real initialOutput(start = initialValue, fixed = false) "Initial output for the sampler" annotation(Dialog(tab = "Initialization", enable = false)); +initial equation + if init == InitializationOptions.FixedValue then + initialOutput = initialValue; + elseif init == InitializationOptions.SteadyState then + initialOutput = u; + end if; + pre(y) = initialOutput; +algorithm + when trigger then + y := u; + end when; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The (discrete) output y is sampled from the input u whenever the Boolean input trigger becomes true.

+

Notes

+ +

See also

+

+Sampler +

+"), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, 12.5}, textColor = {0, 0, 128}, extent = {{-51.371, -12}, {51.371, 12}}, textString = "SAMPLE", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Bitmap(visible = true, origin = {178.304, 50}, fileName = "", imageSource = "iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAACXBIWXMAAAsTAAALEwEAmpwYAAAABGdBTUEAALGeYUxB9wAAACBjSFJNAAB6JQAAgIMAAPn/AACA6AAAUggAARVYAAA6lwAAF2/XWh+QAAAB7klEQVR42mJsufTiPwMZACCAWP5//4Fd4tcnBsndRQzyn/aA+Q/5XBieu/Yx/GHjA/MBAojl3zfsGmWOlDHo/N7DoKEA4Qu83MPAfKCM4Z7NBDAfIIBY/uKwUebtDrAmDlYIX0OcgeHDgx0Mt6HqAQKI5Q8OjbgATD1AALH8xuHUJ8IeDDde7gDbBAI3XkLEYOoBAojlF5Dx69dvhrev34MFePm4GXh4uRkuCqcw/P39B+g8ROBcAYrBNAIEEMuXT18Y3rx6z2Ctp8hgoCbNMHfTcYY/QIM4uTgYTgjlgDEc/AIREI0AAcTy+uU7BjtDZYZkP0uGn7/+MOSFOzBMXHGA4dfP3wzs7KwM////Z/j06SvDnz9/wRp4eLjA4gABxGRvpMKQEWjN8PfvPzCWEOJjSAPyQbZ+/vyN4cOHLwwC3BwMsV5mDN7W2gw/f/wEiwMEEOOPn7///wDa9PP3bwYwDcQg+tGLdwwLt55kYGVlYQhxNADb9gNo2Kt3nxkOXbjLABBATH/+AW0C4j9QG2G0iAAPQ5iLETDg/jDce/oGIg5Ux83FzmCqJccAEEBMCMX/Ic5FMkiIj4vBz06X4fiVBwwPnr+Fe4eLnY0BIIBYYDaAFf/7B5f8CzVMgJeTwcdGG+yFPyDDoeoAAgwAAiQQgeLRB5kAAAAASUVORK5CYII=", extent = {{-1.696, -0}, {1.696, 0}}), Text(visible = true, origin = {0, -12.5}, textColor = {0, 0, 128}, extent = {{-51.371, -12}, {51.371, 12}}, textString = "IF TRUE", fontName = "Lato Black", textStyle = {TextStyle.Bold})})); +end SampleIfTrue; diff --git a/BusinessSimulation/Converters/DiscreteDelay/Sampler.mo b/BusinessSimulation/Converters/DiscreteDelay/Sampler.mo new file mode 100644 index 0000000..89afa57 --- /dev/null +++ b/BusinessSimulation/Converters/DiscreteDelay/Sampler.mo @@ -0,0 +1,45 @@ +within BusinessSimulation.Converters.DiscreteDelay; + +block Sampler "Ideal periodic sampler of input" + import BusinessSimulation.Units.Time; + import BusinessSimulation.Types.InitializationOptions; + import BusinessSimulation.Constants.small; + extends Interfaces.PartialConverters.SmoothSISO(redeclare discrete RealOutput y); + extends Icons.DiscreteSmoothLabel; + parameter Time samplingPeriod(min = small) "Interval at which to sample the input" annotation(Evaluate = true); + parameter Time offsetStartTime = samplingPeriod "Sampling will begin at startTime = modelStartTime + offsetStartTime"; + parameter OutputType initialValue = 0 "Initial Value to be reported before startTime" annotation(Dialog(enable = not init == InitializationOptions.SteadyState)); + parameter InitializationOptions init = modelSettings.init "Provide InitializationOptions (Free, FixedValue, SteadyState)" annotation(Evaluate = true, Dialog(tab = "Advanced")); + outer ModelSettings modelSettings; +protected + parameter Real initialOutput(start = initialValue, fixed = false) "Initial output for the sampler" annotation(Dialog(tab = "Initialization", enable = false)); +initial equation + if init == InitializationOptions.FixedValue then + initialOutput = initialValue; + elseif init == InitializationOptions.SteadyState then + initialOutput = u; + end if; + pre(y) = initialOutput; +algorithm + when sample(modelSettings.modelStartTime + offsetStartTime, samplingPeriod) then + y := u; + end when; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The (discrete) output y is obtained by sampling every samplingPeriod starting at modelSettings.modelStartTime + offsetStartTime from the input u.

+

Notes

+ +

See also

+

+SampleIfTrue +

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {0, 0, 128}, extent = {{-51.371, -12}, {51.371, 12}}, textString = "SAMPLER", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Sampler; diff --git a/BusinessSimulation/Converters/DiscreteDelay/Smooth.mo b/BusinessSimulation/Converters/DiscreteDelay/Smooth.mo new file mode 100644 index 0000000..09a39e5 --- /dev/null +++ b/BusinessSimulation/Converters/DiscreteDelay/Smooth.mo @@ -0,0 +1,59 @@ +within BusinessSimulation.Converters.DiscreteDelay; + +block Smooth "First-order exponential smooth" + import BusinessSimulation.Types.InitializationOptions; + import BusinessSimulation.Units.Time; + extends Interfaces.PartialConverters.SmoothSISO; + Interfaces.Connectors.RealInput u_delayTime if not hasConstantDelayTime "Delay time" annotation(Placement(visible = true, transformation(origin = {0, 100}, extent = {{-10, -10}, {10, 10}}, rotation = -90), iconTransformation(origin = {0, 50}, extent = {{-10, 10}, {10, -10}}, rotation = -810))); + parameter Time delayTime = 1 "Constant delay time (optional)" annotation(Dialog(enable = hasConstantDelayTime)); + parameter OutputType initialValue = 0 "Output at startTime" annotation(Dialog(enable = not init == InitializationOptions.SteadyState)); + parameter InitializationOptions init = modelSettings.init "Provide InitializationOptions (Free, FixedValue, SteadyState)" annotation(Evaluate = true, Dialog(tab = "Advanced")); + parameter Boolean hasConstantDelayTime = true "= true, if delayTime is given by the parameter instead of the input" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + outer ModelSettings modelSettings; +protected + parameter Real initialOutput(start = initialValue, fixed = false) "Value to be used for initialization of the implicit stock" annotation(Dialog(enable = false, tab = "Initialization")); + SourcesOrSinks.ExogenousChange changingPerception annotation(Placement(visible = true, transformation(origin = {-50, 5}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Gap gap "Difference between acutal information and perceived information" annotation(Placement(visible = true, transformation(origin = {-107.215, 50}, extent = {{-10, 10}, {10, -10}}, rotation = 0))); + Division_Guarded rateOfChange(outputIfZero = 0) "Rate of change in perceived information" annotation(Placement(visible = true, transformation(origin = {-68.12, 45}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Stocks.InformationLevel perceivedInformation(initialValue = initialOutput, init = BusinessSimulation.Types.InitializationOptions.FixedValue) "Smoothed information" annotation(Placement(visible = true, transformation(origin = {0, 5}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + ClipProcessTime positiveDelayTime "Delay time shall never be less than dt" annotation(Placement(visible = true, transformation(origin = {-70, 80}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + ConstantConverterTime parDelayTime(value = delayTime) if hasConstantDelayTime "Constant delay time (optional)" annotation(Placement(visible = true, transformation(origin = {-35, 95}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); +initial equation + if init == InitializationOptions.FixedValue then + initialOutput = initialValue; + elseif init == InitializationOptions.SteadyState then + initialOutput = u; + end if; +equation + connect(u, gap.u1) annotation(Line(visible = true, origin = {-130.661, 22.5}, points = {{-39.339, -22.5}, {10.446, -22.5}, {10.446, 22.5}, {15.446, 22.5}}, color = {0, 0, 127})); + connect(gap.y, rateOfChange.u1) annotation(Line(visible = true, origin = {-87.986, 50}, points = {{-11.866, 0}, {11.866, 0}}, color = {0, 0, 127})); + connect(rateOfChange.y, changingPerception.u) annotation(Line(visible = true, origin = {-56.919, 35}, points = {{-3.838, 10}, {1.919, 10}, {1.919, -20}}, color = {0, 0, 127})); + connect(changingPerception.massPort, perceivedInformation.inflow) annotation(Line(visible = true, origin = {-25, 5}, points = {{-15, 0}, {15, 0}}, color = {128, 0, 128})); + connect(perceivedInformation.y, gap.u2) annotation(Line(visible = true, origin = {-69.643, 53.124}, points = {{74.643, -37.724}, {74.643, 11.876}, {-50.357, 11.876}, {-50.357, 1.876}, {-45.572, 1.876}}, color = {0, 0, 127})); + connect(perceivedInformation.y1, y) annotation(Line(visible = true, origin = {62.625, -2.5}, points = {{-52.125, 2.5}, {-22.625, 2.5}, {-22.625, 2.5}, {97.375, 2.5}}, color = {1, 37, 163})); + connect(positiveDelayTime.y, rateOfChange.u2) annotation(Line(visible = true, origin = {-83.371, 62.5}, points = {{5.371, 17.5}, {-6.629, 17.5}, {-6.629, -22.5}, {7.251, -22.5}}, color = {1, 37, 163})); + connect(parDelayTime.y, positiveDelayTime.u) annotation(Line(visible = true, origin = {-44, 83}, points = {{9, 6}, {9, -3}, {-18, -3}}, color = {1, 37, 163})); + connect(u_delayTime, positiveDelayTime.u) annotation(Line(visible = true, origin = {-20.667, 86.667}, points = {{20.667, 13.333}, {20.667, -6.667}, {-41.333, -6.667}}, color = {1, 37, 163})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

A smooth is a first-order exponential information delay. It is typically used to model time lags in forming an expectation or in perceiving some information.

+

Inside the converter there actually is a stock x that stores the perceived or expected value of the information input u. The output y is derived immediately from x as can be seen from these equations where τ denotes the delayTime:

+

\"y=x\"

+

Notes

+ + +

See also

+

SmoothNDecay

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {0, 0, 128}, extent = {{-99.005, -12}, {99.005, 12}}, textString = "SMOOTH", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Smooth; diff --git a/BusinessSimulation/Converters/DiscreteDelay/SmoothN.mo b/BusinessSimulation/Converters/DiscreteDelay/SmoothN.mo new file mode 100644 index 0000000..002d1e8 --- /dev/null +++ b/BusinessSimulation/Converters/DiscreteDelay/SmoothN.mo @@ -0,0 +1,48 @@ +within BusinessSimulation.Converters.DiscreteDelay; + +block SmoothN "N-th order exponential smooth with constant averaging time" + import BusinessSimulation.Types.InitializationOptions; + import BusinessSimulation.Units.{Time,Rate}; + extends Interfaces.PartialConverters.SmoothSISO; + Interfaces.Connectors.RealInput u_delayTime if not hasConstantDelayTime "Delay time input" annotation(Placement(visible = true, transformation(origin = {-145, 45}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {0, 50}, extent = {{-10, 10}, {10, -10}}, rotation = -810))); + parameter Integer n(min = 1) = 3 "Order of the smooth" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Time delayTime(min = 0) = 1 "Constant delay time (optional)" annotation(Dialog(enable = hasConstantDelayTime)); + parameter OutputType initialValue = 0 "Initial Output" annotation(Dialog(enable = not init == InitializationOptions.SteadyState)); + parameter Boolean hasConstantDelayTime = true "if true, the constant parameter value is used" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter InitializationOptions init = modelSettings.init "Provide InitializationOptions (Free, FixedValue, SteadyState)" annotation(Evaluate = true, Dialog(tab = "Advanced")); + outer ModelSettings modelSettings; +protected + Division partialDelayTime if not hasConstantDelayTime "Delay time for each smooth in the chain of smooths" annotation(Placement(visible = true, transformation(origin = {-30, 40}, extent = {{-10, -10}, {10, 10}}, rotation = -360))); + Converters.DiscreteDelay.Smooth firstOrderSmooth[n](each hasConstantDelayTime = hasConstantDelayTime, each init = init, each initialValue = initialValue, each delayTime = delayTime / n) "Chain of n first-order exponential information delays" annotation(Placement(visible = true, transformation(origin = {0, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + ConstantConverter parN(value = n) if not hasConstantDelayTime "Order of the delay" annotation(Placement(visible = true, transformation(origin = {-70, 35}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(u_delayTime, partialDelayTime.u1) annotation(Line(visible = true, origin = {1.5, 95.188}, points = {{-146.5, -50.188}, {-39.5, -50.188}, {-39.5, -50.188}}, color = {1, 37, 163})); + connect(parN.y, partialDelayTime.u2) annotation(Line(visible = true, origin = {-51.5, 35}, points = {{-13.5, 0}, {13.5, 0}}, color = {1, 37, 163})); + connect(partialDelayTime.y, firstOrderSmooth[1].u_delayTime) annotation(Line(visible = true, origin = {-7.333, 28.333}, points = {{-14.667, 11.667}, {7.333, 11.667}, {7.333, -23.333}}, color = {1, 37, 163})); + for i in 2:n loop + connect(partialDelayTime.y, firstOrderSmooth[i].u_delayTime); + end for; + connect(u, firstOrderSmooth[1].u) "Input signal" annotation(Line(visible = true, origin = {-89.681, 0}, points = {{-80.319, 0}, {80.319, 0}}, color = {1, 37, 163})); + for i in 1:n - 1 loop + connect(firstOrderSmooth[i].y, firstOrderSmooth[i + 1].u); + end for; + connect(firstOrderSmooth[n].y, y) "Output signal" annotation(Line(visible = true, origin = {84.767, 0}, points = {{-75.233, 0}, {75.233, 0}}, color = {1, 37, 163})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

A smooth is an exponential information delay. It is typically used to model time lags in forming an expectation or in perceiving some information. A smooth of order n is modeled as a cascade of n first-order exponential smooth components, where the output of a preceding component is the input for its successor. The delay time for each smooth in the cascade will be delayTime/n.

+

Notes

+ +

See also

+

Smooth

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {0, 0, 128}, extent = {{-60.252, -12}, {60.252, 12}}, textString = "SMOOTH N", fontName = "Lato Black", textStyle = {TextStyle.Bold}, horizontalAlignment = TextAlignment.Left)}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end SmoothN; diff --git a/BusinessSimulation/Converters/DiscreteDelay/package.mo b/BusinessSimulation/Converters/DiscreteDelay/package.mo new file mode 100644 index 0000000..c0fd351 --- /dev/null +++ b/BusinessSimulation/Converters/DiscreteDelay/package.mo @@ -0,0 +1,12 @@ +within BusinessSimulation.Converters; + +package DiscreteDelay "Discrete or delay converters" + extends Icons.Package; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This package contains converters which have an internal stock or state—exemplified by rectangular icons. This can be discrete processes of information collection as in the Sampler or SampleIfTrue converters, or it can be information delays where the perceived or reported information will follow the actual information with some lag.

+
+
+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, lineThickness = 8, extent = {{-50, -30}, {50, 30}}), Polygon(visible = true, origin = {67.809, 0}, rotation = -1080, lineColor = {76, 112, 136}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-10, 10}, {10, 0}, {-10, -10}, {-10, 10}}), Polygon(visible = true, origin = {-64.857, 0}, rotation = -1440, lineColor = {76, 112, 136}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-10, 10}, {10, 0}, {-10, -10}, {-10, 10}})}), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end DiscreteDelay; diff --git a/BusinessSimulation/Converters/DiscreteDelay/package.order b/BusinessSimulation/Converters/DiscreteDelay/package.order new file mode 100644 index 0000000..92b2a6d --- /dev/null +++ b/BusinessSimulation/Converters/DiscreteDelay/package.order @@ -0,0 +1,6 @@ +DelayFixed +DelayInformation +Sampler +SampleIfTrue +Smooth +SmoothN diff --git a/BusinessSimulation/Converters/Division.mo b/BusinessSimulation/Converters/Division.mo new file mode 100644 index 0000000..8858350 --- /dev/null +++ b/BusinessSimulation/Converters/Division.mo @@ -0,0 +1,15 @@ +within BusinessSimulation.Converters; + +block Division "Division without protection against division by zero" + extends Interfaces.PartialConverters.SO; + Interfaces.Connectors.RealInput u1 "Nominator input" annotation(Placement(visible = true, transformation(origin = {-145, 20}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, 50}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealInput u2 "Denominator input" annotation(Placement(visible = true, transformation(origin = {-145, -20}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, -50}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + y = u1 / u2; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output y is obtained by unguarded division of the nominator input u1 and the denominator input u2:

+
y = u1/u2;

+

See also

+

Division_Guarded

", revisions = ""), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {-60.109, 49.884}, rotation = -990, points = {{0.116, -0.109}, {0.116, -47.528}, {-19.884, -47.528}}, color = {0, 0, 128}, thickness = 3, arrowSize = 0), Line(visible = true, origin = {-33.755, -50}, rotation = -270, points = {{0, 26.245}, {0, -43.755}, {15.751, -43.755}}, color = {0, 0, 128}, thickness = 3, arrowSize = 0), Line(visible = true, rotation = -45, points = {{20, 20}, {-20, -20}}, color = {0, 0, 128}, thickness = 4, arrowSize = 0), Text(visible = true, origin = {0, 15}, textColor = {0, 0, 128}, extent = {{-30, -12}, {30, 12}}, textString = "Nom", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {0.75, -15}, textColor = {0, 0, 128}, extent = {{-29.25, -12}, {29.25, 12}}, textString = "Den", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Division; diff --git a/BusinessSimulation/Converters/Division_Guarded.mo b/BusinessSimulation/Converters/Division_Guarded.mo new file mode 100644 index 0000000..84722c4 --- /dev/null +++ b/BusinessSimulation/Converters/Division_Guarded.mo @@ -0,0 +1,19 @@ +within BusinessSimulation.Converters; + +block Division_Guarded "Division guarded for division by zero" + extends Interfaces.PartialConverters.SO; + Interfaces.Connectors.RealInput u1 "Nominator input" annotation(Placement(visible = true, transformation(origin = {-145, 20}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, 50}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealInput u2 "Denominator input" annotation(Placement(visible = true, transformation(origin = {-145, -20}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, -50}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + parameter OutputType outputIfZero = 0 "Output, if denominator (u2) is zero (default = 0)"; +equation + // as division by zero is to be avoided at all cases event checking has to be turned off + y = if noEvent(u2 < 0 or u2 > 0) then u1 / u2 else outputIfZero; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output y is obtained by guarded division of the nominator input u1 and the denominator input u2:

+

y = u1/u2

If u2 is equal to zero, then outputIfZero is returned.

+

Implementation

+

y = if noEvent(u2 < 0 or u2 > 0) then u1 / u2 else outputIfZero;

+

See also

+

Division

", revisions = ""), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, rotation = -45, points = {{20, 20}, {-20, -20}}, color = {0, 0, 128}, thickness = 4), Line(visible = true, origin = {-60.109, 49.884}, rotation = -990, points = {{0.116, -0.109}, {0.116, -47.528}, {-19.884, -47.528}}, color = {0, 0, 128}, thickness = 3), Line(visible = true, origin = {-33.755, -50}, rotation = -270, points = {{0, 26.245}, {0, -43.755}, {15.751, -43.755}}, color = {255, 0, 0}, thickness = 3), Text(visible = true, origin = {0, 15}, textColor = {0, 0, 128}, extent = {{-30, -12}, {30, 12}}, textString = "Nom", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {0.75, -15}, textColor = {255, 0, 0}, extent = {{-29.25, -12}, {29.25, 12}}, textString = "Den", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Division_Guarded; diff --git a/BusinessSimulation/Converters/DmnlInput.mo b/BusinessSimulation/Converters/DmnlInput.mo new file mode 100644 index 0000000..13f444b --- /dev/null +++ b/BusinessSimulation/Converters/DmnlInput.mo @@ -0,0 +1,26 @@ +within BusinessSimulation.Converters; + +block DmnlInput "Input u will be stated as dimensionless fraction with regard to a reference value" + extends Interfaces.PartialConverters.SO(redeclare final type OutputType = Units.Dimensionless); + Interfaces.Connectors.RealInput u "Input to be normalized" annotation(Placement(visible = true, transformation(origin = {-145, 5}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, 0}, extent = {{-10, 10}, {10, -10}}, rotation = 0))); + Interfaces.Connectors.RealInput u_reference if not hasConstantReference "Input of reference value" annotation(Placement(visible = true, transformation(origin = {-145, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {0, 80}, extent = {{-10, 10}, {10, -10}}, rotation = -90))); + parameter Real referenceValue "Reference value, so that input is represented as a dimensionless fraction thereof" annotation(Dialog(enable = hasConstantReference)); + parameter Boolean hasConstantReference = false "If true, the constant reference value will be used" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); +protected + Division_Guarded division_yidz(outputIfZero = 0) annotation(Placement(visible = true, transformation(origin = {0, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + ConstantConverter parReference(value = referenceValue) if hasConstantReference "Constant reference value (optional)" annotation(Placement(visible = true, transformation(origin = {-120, -5}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(u, division_yidz.u1) annotation(Line(visible = true, origin = {-83.75, 22.5}, points = {{-61.25, -17.5}, {3.75, -17.5}, {3.75, -17.5}, {75.75, -17.5}}, color = {0, 0, 127})); + connect(u_reference, division_yidz.u2) annotation(Line(visible = true, origin = {-83.75, -22.5}, points = {{-61.25, -17.5}, {3.75, -17.5}, {3.75, 17.5}, {75.75, 17.5}}, color = {0, 0, 127})); + connect(division_yidz.y, y) annotation(Line(visible = true, origin = {83.681, 0}, points = {{-76.319, 0}, {76.319, 0}}, color = {0, 0, 127})); + connect(parReference.y, division_yidz.u2) annotation(Line(visible = true, origin = {-61, -5}, points = {{-53, 0}, {53, 0}}, color = {1, 37, 163})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output y is obtained by guarded division of the input u by some reference value. The reference value can either be a constant (referenceValue) or a variable input (u_reference). If the reference value is zero the output will be zero also.

+

Notes

+

Since there is just regular division, care has to be taken in case of negative values for either input or reference value.

+
Units
+

As the reference value should have the same dimension as the input, the output will effectively be dimensionless.

+

See also

+

Division_Guarded

", revisions = ""), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {0, 0, 128}, extent = {{-43.326, -12}, {43.326, 12}}, textString = "Dmnl [1]", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end DmnlInput; diff --git a/BusinessSimulation/Converters/Exp.mo b/BusinessSimulation/Converters/Exp.mo new file mode 100644 index 0000000..3b0f9bc --- /dev/null +++ b/BusinessSimulation/Converters/Exp.mo @@ -0,0 +1,11 @@ +within BusinessSimulation.Converters; + +block Exp "Natural exponential function" + extends Interfaces.PartialConverters.SISO; +equation + y = exp(u); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output y is the natural exponential function of the input u.

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {0, 0, 128}, extent = {{-40.484, -12}, {40.484, 12}}, textString = "EXP", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Exp; diff --git a/BusinessSimulation/Converters/ForceOfInterest.mo b/BusinessSimulation/Converters/ForceOfInterest.mo new file mode 100644 index 0000000..88ad617 --- /dev/null +++ b/BusinessSimulation/Converters/ForceOfInterest.mo @@ -0,0 +1,13 @@ +within BusinessSimulation.Converters; + +block ForceOfInterest "Calculates the force of interest (continuous compounding rate)" + extends Interfaces.PartialConverters.SISO; +equation + y = log(1 + u); + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {0, 0, 128}, extent = {{-54.133, -12}, {54.133, 12}}, textString = "Ln (1 + u)", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The Force of Interest y is calculated according to the formula:

+

y  = log( 1+ u)

+

It can be used to convert a periodically compounding rate to a continuously coumpounding rate.

+"), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end ForceOfInterest; diff --git a/BusinessSimulation/Converters/Gain.mo b/BusinessSimulation/Converters/Gain.mo new file mode 100644 index 0000000..4d2949c --- /dev/null +++ b/BusinessSimulation/Converters/Gain.mo @@ -0,0 +1,12 @@ +within BusinessSimulation.Converters; + +block Gain "Input is multiplied by constant parameter" + extends Interfaces.PartialConverters.SISO; + parameter Real c "Gain factor (constant multiplier)"; +equation + y = u * c; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output y is obtained by multiplying the input u with a constant gain factor c:

+
y = c * u;
", revisions = ""), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {5, -30}, textColor = {64, 64, 64}, extent = {{-55, -6}, {45, 6}}, textString = "%c", fontName = "Lato", textStyle = {TextStyle.Bold}), Text(visible = true, textColor = {0, 0, 128}, extent = {{-99.005, -12}, {99.005, 12}}, textString = "GAIN", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Gain; diff --git a/BusinessSimulation/Converters/Gap.mo b/BusinessSimulation/Converters/Gap.mo new file mode 100644 index 0000000..21eb52d --- /dev/null +++ b/BusinessSimulation/Converters/Gap.mo @@ -0,0 +1,11 @@ +within BusinessSimulation.Converters; + +block Gap "Compare goal (u1) and current value (u2) to determine gap" + extends Interfaces.PartialConverters.SI2SO; +equation + y = u1 - u2; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output y is obtained by subtracting input u2 from input u1:

+
 y = u1 - u2;
", revisions = ""), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {-32.809, -50}, rotation = -990, points = {{-0, 27.191}, {-0, 1.074}}, color = {255, 0, 0}, thickness = 3), Line(visible = true, origin = {-21.062, -30}, rotation = -270, points = {{-20, 14.231}, {20, -14.231}}, color = {255, 0, 0}, thickness = 3, arrowSize = 10), Ellipse(visible = true, lineColor = {0, 0, 128}, fillColor = {5, 5, 125}, fillPattern = FillPattern.Solid, extent = {{-11.872, -11.872}, {11.872, 11.872}}), Line(visible = true, origin = {-19.639, 27.324}, points = {{-14.516, 20.778}, {14.516, -20.778}}, color = {5, 5, 125}, thickness = 3, arrowSize = 10), Line(visible = true, origin = {33.017, 0}, rotation = -270, points = {{0, 25.332}, {0, -25.332}}, color = {5, 5, 125}, thickness = 3, arrowSize = 10), Line(visible = true, origin = {-29.824, 50}, rotation = -990, points = {{-0, 30.176}, {-0, 4.373}}, color = {0, 0, 128}, thickness = 3), Text(visible = true, origin = {1.181, 42.115}, textColor = {0, 0, 128}, extent = {{-21.181, -20}, {21.181, 20}}, textString = "+", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {1.402, -36}, textColor = {255, 0, 0}, extent = {{-15.402, -20}, {15.402, 20}}, textString = "‒", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Gap; diff --git a/BusinessSimulation/Converters/Log.mo b/BusinessSimulation/Converters/Log.mo new file mode 100644 index 0000000..5e3aaa6 --- /dev/null +++ b/BusinessSimulation/Converters/Log.mo @@ -0,0 +1,12 @@ +within BusinessSimulation.Converters; + +block Log "Logarithm of the input to a given base" + extends Interfaces.PartialConverters.SISO; + import BusinessSimulation.Constants.{e,small}; + parameter Real base(min = small) = e "Base of the logarithm (default = Euler's number)" annotation(Evaluate = true); +equation + y = log(u) / log(base); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output y is obtained as the logarithm of the input u to base base with the default base being Euler's number.

"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {0, 0, 128}, extent = {{-40.484, -12}, {40.484, 12}}, textString = "LOG", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Log; diff --git a/BusinessSimulation/Converters/Logical/AllTrue.mo b/BusinessSimulation/Converters/Logical/AllTrue.mo new file mode 100644 index 0000000..2b1ac70 --- /dev/null +++ b/BusinessSimulation/Converters/Logical/AllTrue.mo @@ -0,0 +1,11 @@ +within BusinessSimulation.Converters.Logical; + +block AllTrue "Logical 'all true'" + extends Interfaces.PartialConverters.BooleanMISO; +equation + y = Functions.allTrueQ(u); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The Boolean output y is true, if all Boolean elements of the input vector u are true, and false otherwise.

+"), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {190, 52, 178}, extent = {{-40.484, -12}, {40.484, 12}}, textString = "AllTrue", fontName = "Lato Black", textStyle = {TextStyle.Bold})})); +end AllTrue; diff --git a/BusinessSimulation/Converters/Logical/And.mo b/BusinessSimulation/Converters/Logical/And.mo new file mode 100644 index 0000000..c050de2 --- /dev/null +++ b/BusinessSimulation/Converters/Logical/And.mo @@ -0,0 +1,11 @@ +within BusinessSimulation.Converters.Logical; + +block And "Logical 'and'" + extends Interfaces.PartialConverters.BooleanSI2SO; +equation + y = u1 and u2; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The Boolean output y is true, if both Boolean inputs u1 and u2 are true, and false else. 

+"), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {190, 52, 178}, extent = {{-40.484, -12}, {40.484, 12}}, textString = "AND", fontName = "Lato Blak", textStyle = {TextStyle.Bold})})); +end And; diff --git a/BusinessSimulation/Converters/Logical/AnyTrue.mo b/BusinessSimulation/Converters/Logical/AnyTrue.mo new file mode 100644 index 0000000..613b48a --- /dev/null +++ b/BusinessSimulation/Converters/Logical/AnyTrue.mo @@ -0,0 +1,15 @@ +within BusinessSimulation.Converters.Logical; + +block AnyTrue "Logical 'any true'" + extends Interfaces.PartialConverters.BooleanMISO; + NoneTrue noneTrue(nin = nin) annotation(Placement(visible = true, transformation(origin = {-30, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Not negation annotation(Placement(visible = true, transformation(origin = {10, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(u, noneTrue.u) annotation(Line(visible = true, origin = {-104, 0}, points = {{-66, -0}, {66, 0}}, color = {255, 0, 255})); + connect(noneTrue.y, negation.u) annotation(Line(visible = true, origin = {-10, 0}, points = {{-12, 0}, {12, -0}}, color = {255, 0, 255})); + connect(negation.y, y) annotation(Line(visible = true, origin = {89, 0}, points = {{-71, 0}, {71, 0}}, color = {255, 0, 255})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The Boolean output y is true, if any of the Boolean elements of the input vector u are true, and false otherwise.

+"), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {190, 52, 178}, extent = {{-48.609, -12}, {48.609, 12}}, textString = "AnyTrue", fontName = "Lato Black", textStyle = {TextStyle.Bold})})); +end AnyTrue; diff --git a/BusinessSimulation/Converters/Logical/Boole.mo b/BusinessSimulation/Converters/Logical/Boole.mo new file mode 100644 index 0000000..7fee206 --- /dev/null +++ b/BusinessSimulation/Converters/Logical/Boole.mo @@ -0,0 +1,12 @@ +within BusinessSimulation.Converters.Logical; + +block Boole "Yields 1, if u is true and 0 if it is false" + extends Interfaces.PartialConverters.BooleanSIRealSO; +algorithm + y := Functions.boole(u); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The real output y will be 1 if the boolean input u is true and 0 if it is false.

+

See also

+

NotZero

", revisions = ""), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {0, 0, 128}, extent = {{-40.484, -12}, {40.484, 12}}, textString = "BOOLE", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Boole; diff --git a/BusinessSimulation/Converters/Logical/ConstantConverterBoolean.mo b/BusinessSimulation/Converters/Logical/ConstantConverterBoolean.mo new file mode 100644 index 0000000..8b4f2c8 --- /dev/null +++ b/BusinessSimulation/Converters/Logical/ConstantConverterBoolean.mo @@ -0,0 +1,14 @@ +within BusinessSimulation.Converters.Logical; + +block ConstantConverterBoolean "A constant boolean value is turned into a constant signal" + extends Icons.ConstantConverter; + Interfaces.Connectors.BooleanOutput y "Signal with constant boolean value" annotation(Placement(visible = true, transformation(origin = {160, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {60, 0}, extent = {{-10, -10}, {10, 10}}, rotation = -1440))); + parameter Boolean value "= true, if output should be consistently true"; +equation + y = value; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The boolean output y is equal to the boolean parameter value during a simulation.

+

See also

+

ConstantConverter

"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, 50}, textColor = {190, 52, 178}, extent = {{-100, -6}, {100, 6}}, textString = "%value", fontName = "Lato", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Ellipse(visible = true, lineColor = {0, 0, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-20, -20}, {20, 20}}), Line(visible = true, origin = {0, -0.205}, rotation = -810, points = {{-30, 0}, {30, 0}}, color = {0, 0, 128}, thickness = 5), Text(visible = true, origin = {-50, 0}, textColor = {128, 0, 128}, extent = {{-44.917, -32.251}, {44.917, 32.251}}, textString = "%value", fontSize = 30, fontName = "Arial"), Text(visible = true, origin = {0, -56.852}, textColor = {128, 0, 128}, extent = {{-141.113, -29.508}, {141.113, 29.508}}, textString = "%name", fontName = "Arial")}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end ConstantConverterBoolean; diff --git a/BusinessSimulation/Converters/Logical/Greater.mo b/BusinessSimulation/Converters/Logical/Greater.mo new file mode 100644 index 0000000..bb2519e --- /dev/null +++ b/BusinessSimulation/Converters/Logical/Greater.mo @@ -0,0 +1,10 @@ +within BusinessSimulation.Converters.Logical; + +block Greater "True, if u1 is greater than u2" + extends Interfaces.PartialConverters.SI2BooleanSO; +equation + y = u1 > u2; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The boolean output y will be true, if the real input u1 is greater than the real input u2 and otherwise be false.

", revisions = ""), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {190, 52, 178}, extent = {{-36.812, -20}, {36.812, 20}}, textString = ">", fontName = "Lato", textStyle = {TextStyle.Bold}), Line(visible = true, origin = {-33.755, -50}, rotation = -270, points = {{0, 53.755}, {0, -56.344}, {40, -56.344}}, color = {0, 0, 128}, thickness = 3), Line(visible = true, origin = {-59.824, 50}, rotation = -990, points = {{0, 27.51}, {0, -35.039}, {-40, -35.039}}, color = {0, 0, 128}, thickness = 3), Ellipse(visible = true, origin = {-66.537, 0}, lineColor = {0, 0, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 3, extent = {{32, -10}, {52, 10}}), Ellipse(visible = true, origin = {-19.543, 0}, lineColor = {0, 0, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 3, extent = {{32, -10}, {52, 10}})})); +end Greater; diff --git a/BusinessSimulation/Converters/Logical/GreaterEqual.mo b/BusinessSimulation/Converters/Logical/GreaterEqual.mo new file mode 100644 index 0000000..1e3ed14 --- /dev/null +++ b/BusinessSimulation/Converters/Logical/GreaterEqual.mo @@ -0,0 +1,10 @@ +within BusinessSimulation.Converters.Logical; + +block GreaterEqual "True, if u1 is greater than or equal to u2" + extends Interfaces.PartialConverters.SI2BooleanSO; +equation + y = u1 >= u2; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The boolean output y will be true, if the real input u1 is greater than or equal to the real input u2 and otherwise be false.

", revisions = ""), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {190, 52, 178}, extent = {{-36.812, -20}, {36.812, 20}}, textString = "≥", fontName = "Lato", textStyle = {TextStyle.Bold}), Line(visible = true, origin = {-33.755, -50}, rotation = -270, points = {{0, 53.755}, {0, -56.344}, {40, -56.344}}, color = {0, 0, 128}, thickness = 3), Line(visible = true, origin = {-59.824, 50}, rotation = -990, points = {{0, 27.51}, {0, -35.039}, {-40, -35.039}}, color = {0, 0, 128}, thickness = 3), Ellipse(visible = true, origin = {-66.537, 0}, lineColor = {0, 0, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 3, extent = {{32, -10}, {52, 10}}), Ellipse(visible = true, origin = {-19.543, 0}, lineColor = {0, 0, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 3, extent = {{32, -10}, {52, 10}})})); +end GreaterEqual; diff --git a/BusinessSimulation/Converters/Logical/Less.mo b/BusinessSimulation/Converters/Logical/Less.mo new file mode 100644 index 0000000..7439e11 --- /dev/null +++ b/BusinessSimulation/Converters/Logical/Less.mo @@ -0,0 +1,10 @@ +within BusinessSimulation.Converters.Logical; + +block Less "True, if u1 is less than u2" + extends Interfaces.PartialConverters.SI2BooleanSO; +equation + y = u1 < u2; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The boolean output y will be true, if the real input u1 is less than the real input u2 and otherwise be false.

", revisions = ""), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {190, 52, 178}, extent = {{-36.812, -20}, {36.812, 20}}, textString = "<", fontName = "Lato", textStyle = {TextStyle.Bold}), Line(visible = true, origin = {-33.755, -50}, rotation = -270, points = {{0, 53.755}, {0, -56.344}, {40, -56.344}}, color = {0, 0, 128}, thickness = 3), Line(visible = true, origin = {-59.824, 50}, rotation = -990, points = {{0, 27.51}, {0, -35.039}, {-40, -35.039}}, color = {0, 0, 128}, thickness = 3), Ellipse(visible = true, origin = {-66.537, 0}, lineColor = {0, 0, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 3, extent = {{32, -10}, {52, 10}}), Ellipse(visible = true, origin = {-19.543, 0}, lineColor = {0, 0, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 3, extent = {{32, -10}, {52, 10}})})); +end Less; diff --git a/BusinessSimulation/Converters/Logical/LessEqual.mo b/BusinessSimulation/Converters/Logical/LessEqual.mo new file mode 100644 index 0000000..7ae2928 --- /dev/null +++ b/BusinessSimulation/Converters/Logical/LessEqual.mo @@ -0,0 +1,10 @@ +within BusinessSimulation.Converters.Logical; + +block LessEqual "True, if u1 is less than or equal to u2" + extends Interfaces.PartialConverters.SI2BooleanSO; +equation + y = u1 <= u2; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The boolean output y will be true, if the real input u1 is less than or equal to the real input u2 and otherwise be false.

", revisions = ""), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {190, 52, 178}, extent = {{-36.812, -20}, {36.812, 20}}, textString = "≤", fontName = "Lato", textStyle = {TextStyle.Bold}), Line(visible = true, origin = {-33.755, -50}, rotation = -270, points = {{0, 53.755}, {0, -56.344}, {40, -56.344}}, color = {0, 0, 128}, thickness = 3), Line(visible = true, origin = {-59.824, 50}, rotation = -990, points = {{0, 27.51}, {0, -35.039}, {-40, -35.039}}, color = {0, 0, 128}, thickness = 3), Ellipse(visible = true, origin = {-66.537, 0}, lineColor = {0, 0, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 3, extent = {{32, -10}, {52, 10}}), Ellipse(visible = true, origin = {-19.543, 0}, lineColor = {0, 0, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 3, extent = {{32, -10}, {52, 10}})})); +end LessEqual; diff --git a/BusinessSimulation/Converters/Logical/NoneTrue.mo b/BusinessSimulation/Converters/Logical/NoneTrue.mo new file mode 100644 index 0000000..09393b4 --- /dev/null +++ b/BusinessSimulation/Converters/Logical/NoneTrue.mo @@ -0,0 +1,11 @@ +within BusinessSimulation.Converters.Logical; + +block NoneTrue "Logical 'none true'" + extends Interfaces.PartialConverters.BooleanMISO; +equation + y = Functions.noneTrueQ(u); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The Boolean output y is true, if none of the Boolean elements of the input vector u are true, and false otherwise.

+"), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {190, 52, 178}, extent = {{-57.18, -12}, {57.18, 12}}, textString = "NoneTrue", fontName = "Lato Black", textStyle = {TextStyle.Bold})})); +end NoneTrue; diff --git a/BusinessSimulation/Converters/Logical/Not.mo b/BusinessSimulation/Converters/Logical/Not.mo new file mode 100644 index 0000000..eade766 --- /dev/null +++ b/BusinessSimulation/Converters/Logical/Not.mo @@ -0,0 +1,11 @@ +within BusinessSimulation.Converters.Logical; + +block Not "Logical 'not'" + extends Interfaces.PartialConverters.BooleanSISO; +equation + y = not u; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The boolean output y is true, if the Boolean input u is false, and false otherwise. 

+"), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {190, 52, 178}, extent = {{-40.484, -12}, {40.484, 12}}, textString = "NOT", fontName = "Lato Black", textStyle = {TextStyle.Bold})})); +end Not; diff --git a/BusinessSimulation/Converters/Logical/NotZero.mo b/BusinessSimulation/Converters/Logical/NotZero.mo new file mode 100644 index 0000000..2c7b64f --- /dev/null +++ b/BusinessSimulation/Converters/Logical/NotZero.mo @@ -0,0 +1,15 @@ +within BusinessSimulation.Converters.Logical; + +block NotZero "True, if u is not zero" + extends Interfaces.PartialConverters.SIBooleanSO; +equation + y = Functions.notZeroQ(u); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The boolean output y is true, if the real input u is not equal to zero, and false else. 

+

Notes

+

If the inputs are restricted to either 0 or 1, then NotZero can be seen as an inverse Boole.

+

See also

+

BooleThreshold

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, 12.5}, textColor = {0, 0, 128}, extent = {{-59, -12}, {59, 12}}, textString = "NOT", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {0, -12.5}, textColor = {0, 0, 128}, extent = {{-59, -12}, {59, 12}}, textString = "ZERO", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end NotZero; diff --git a/BusinessSimulation/Converters/Logical/Or.mo b/BusinessSimulation/Converters/Logical/Or.mo new file mode 100644 index 0000000..69625fa --- /dev/null +++ b/BusinessSimulation/Converters/Logical/Or.mo @@ -0,0 +1,10 @@ +within BusinessSimulation.Converters.Logical; + +block Or "Logical 'or'" + extends Interfaces.PartialConverters.BooleanSI2SO; +equation + y = u1 or u2; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The boolean output y is true, if either or both boolean inputs u1 and u2 are true, and false else. 

", revisions = ""), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {190, 52, 178}, extent = {{-40.484, -12}, {40.484, 12}}, textString = "OR", fontName = "Lato Black", textStyle = {TextStyle.Bold})})); +end Or; diff --git a/BusinessSimulation/Converters/Logical/Switch.mo b/BusinessSimulation/Converters/Logical/Switch.mo new file mode 100644 index 0000000..1ac4c7b --- /dev/null +++ b/BusinessSimulation/Converters/Logical/Switch.mo @@ -0,0 +1,13 @@ +within BusinessSimulation.Converters.Logical; + +block Switch "Switching between inputs depending upon condition" + extends Interfaces.PartialConverters.SI2SO; + Interfaces.Connectors.BooleanInput u_cond "Condition" annotation(Placement(visible = true, transformation(origin = {-145, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {0.12, 79.88}, extent = {{-10.12, -10.12}, {10.12, 10.12}}, rotation = -450))); +equation + y = if u_cond then u1 else u2; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Depending upon the boolean input u_cond the output y will be equal to either the input u1 (u_cond = true) or the input u2 (u_cond = false).

+

See also

+

SwitchN

", revisions = ""), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {20, 35}, textColor = {190, 52, 178}, extent = {{-30.242, -12}, {30.242, 12}}, textString = "true", fontName = "Lato Black", textStyle = {TextStyle.Bold}, horizontalAlignment = TextAlignment.Left), Line(visible = true, origin = {-59.824, 50}, rotation = -990, points = {{-0, 0.176}, {0, -27.661}}, color = {0, 0, 128}, thickness = 3), Line(visible = true, origin = {-58.086, -50}, rotation = 990, points = {{-0, -1.914}, {0, 24.5}}, color = {0, 0, 128}, thickness = 3), Ellipse(visible = true, lineColor = {0, 0, 128}, fillColor = {5, 5, 125}, fillPattern = FillPattern.Solid, extent = {{-11.872, -11.872}, {11.872, 11.872}}), Line(visible = true, origin = {35, 0}, rotation = -270, points = {{0, 25}, {0, -25}}, color = {5, 5, 125}, thickness = 3, arrowSize = 10), Line(visible = true, origin = {-25.841, 0}, points = {{0, 30}, {-14.159, 0}, {0, -30}}, color = {190, 52, 178}, thickness = 3, arrow = {Arrow.Filled, Arrow.Filled}, arrowSize = 10, smooth = Smooth.Bezier), Line(visible = true, origin = {-30, -44.212}, rotation = -275.101, points = {{-6.228, 4.669}, {6.228, -4.669}}, color = {5, 5, 125}, thickness = 3, arrowSize = 10), Line(visible = true, origin = {-19.388, 28.7}, points = {{-14.549, 21.3}, {14.549, -21.3}}, color = {5, 5, 125}, thickness = 3, arrowSize = 10), Text(visible = true, origin = {20, -30}, textColor = {190, 52, 178}, extent = {{-30.242, -12}, {30.242, 12}}, textString = "false", fontName = "Lato Black", textStyle = {TextStyle.Bold}, horizontalAlignment = TextAlignment.Left)})); +end Switch; diff --git a/BusinessSimulation/Converters/Logical/SwitchN.mo b/BusinessSimulation/Converters/Logical/SwitchN.mo new file mode 100644 index 0000000..5db62b5 --- /dev/null +++ b/BusinessSimulation/Converters/Logical/SwitchN.mo @@ -0,0 +1,26 @@ +within BusinessSimulation.Converters.Logical; + +block SwitchN "Switching between inputs up to n times depending upon condition" + extends Interfaces.PartialConverters.SI2SO; + Interfaces.Connectors.BooleanInput u_cond "Condition" annotation(Placement(visible = true, transformation(origin = {-145, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {0.12, 79.88}, extent = {{-10.12, -10.12}, {10.12, 10.12}}, rotation = -450))); + parameter Integer n(min = 1) = 1 "Maximum number of switchings"; +protected + discrete Boolean previousCondition "Previous value for u_cond"; + discrete Integer counter "Counter for the switching operations"; +initial equation + pre(counter) = 0; + pre(previousCondition) = u_cond; +algorithm + when previousCondition <> u_cond then + counter := counter + 1; + // update previousCondition iff maximum switchings have not been reached yet + previousCondition := if counter <= n then u_cond else previousCondition; + end when; + // invariant: the previousCondition is always the relevant condition for switching + y := if previousCondition then u1 else u2; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The SwitchN switches up to n times between the inputs u1 (u_cond = true) and u2 (u_cond = false). After each switching an internal counter will be increased and checked so that there are at most n switches.

+

See also

+

Switch

", revisions = ""), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {-59.824, 50}, rotation = -990, points = {{-0, 0.176}, {0, -27.661}}, color = {0, 0, 128}, thickness = 3), Line(visible = true, origin = {-58.086, -50}, rotation = 990, points = {{-0, -1.914}, {0, 24.5}}, color = {0, 0, 128}, thickness = 3), Ellipse(visible = true, lineColor = {0, 0, 128}, fillColor = {5, 5, 125}, fillPattern = FillPattern.Solid, extent = {{-11.872, -11.872}, {11.872, 11.872}}), Line(visible = true, origin = {35, 0}, rotation = -270, points = {{0, 25}, {0, -25}}, color = {5, 5, 125}, thickness = 3, arrowSize = 10), Line(visible = true, origin = {-25.841, 0}, points = {{0, 30}, {-14.159, 0}, {0, -30}}, color = {190, 52, 178}, thickness = 3, arrow = {Arrow.Filled, Arrow.Filled}, arrowSize = 10, smooth = Smooth.Bezier), Line(visible = true, origin = {-31.39, -44.212}, rotation = -275.101, points = {{-6.228, 4.669}, {6.228, -4.669}}, color = {5, 5, 125}, thickness = 3, arrowSize = 10), Line(visible = true, origin = {-19.388, 28.7}, points = {{-14.549, 21.3}, {14.549, -21.3}}, color = {5, 5, 125}, thickness = 3, arrowSize = 10), Text(visible = true, origin = {-47.721, 0}, textColor = {190, 52, 178}, extent = {{-37.721, -6}, {37.721, 6}}, textString = "≤ n", fontName = "Lato", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {20, 35}, textColor = {190, 52, 178}, extent = {{-30.242, -12}, {30.242, 12}}, textString = "true", fontName = "Lato Black", textStyle = {TextStyle.Bold}, horizontalAlignment = TextAlignment.Left), Text(visible = true, origin = {20, -30}, textColor = {190, 52, 178}, extent = {{-30.242, -12}, {30.242, 12}}, textString = "false", fontName = "Lato Black", textStyle = {TextStyle.Bold}, horizontalAlignment = TextAlignment.Left)})); +end SwitchN; diff --git a/BusinessSimulation/Converters/Logical/Threshold.mo b/BusinessSimulation/Converters/Logical/Threshold.mo new file mode 100644 index 0000000..789f4fc --- /dev/null +++ b/BusinessSimulation/Converters/Logical/Threshold.mo @@ -0,0 +1,14 @@ +within BusinessSimulation.Converters.Logical; + +block Threshold "True, if u is greater than the given threshold" + extends Interfaces.PartialConverters.SIBooleanSO; + parameter Real threshold = 0.5 "Threshold to determine true or false"; +equation + y = u > threshold; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The boolean output y is true, if the real input u is greather than threshold, and false otherwise. 

+

See also

+

NotZeroBoole

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {9, 0}, textColor = {0, 0, 128}, extent = {{-40.484, -12}, {40.484, 12}}, textString = "THLD", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {-30, 0}, textColor = {190, 52, 178}, extent = {{-36.812, -20}, {36.812, 20}}, textString = ">", fontName = "Lato", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {0, -30}, textColor = {0, 0, 128}, extent = {{-31.111, -6}, {31.111, 6}}, textString = "%threshold", fontName = "Lato", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Threshold; diff --git a/BusinessSimulation/Converters/Logical/Xor.mo b/BusinessSimulation/Converters/Logical/Xor.mo new file mode 100644 index 0000000..a994c02 --- /dev/null +++ b/BusinessSimulation/Converters/Logical/Xor.mo @@ -0,0 +1,10 @@ +within BusinessSimulation.Converters.Logical; + +block Xor "Logical 'xor'" + extends Interfaces.PartialConverters.BooleanSI2SO; +equation + y = (u1 or u2) and not (u1 and u2); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The boolean output y is true, if either (but not both) boolean inputs u1 and u2 are true, and false else. 

", revisions = ""), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {190, 52, 178}, extent = {{-40.484, -12}, {40.484, 12}}, textString = "XOR", fontName = "Lato Black", textStyle = {TextStyle.Bold})})); +end Xor; diff --git a/BusinessSimulation/Converters/Logical/package.mo b/BusinessSimulation/Converters/Logical/package.mo new file mode 100644 index 0000000..fd8959d --- /dev/null +++ b/BusinessSimulation/Converters/Logical/package.mo @@ -0,0 +1,12 @@ +within BusinessSimulation.Converters; + +package Logical "Converters with boolean output and/or input" + extends Icons.Package; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This package contains converters where at least input or output signals are Boolean variables.

+
+
+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {255, 255, 255}, extent = {{-96.85, -20}, {96.85, 20}}, textString = "true | false", fontName = "Lato Black", textStyle = {TextStyle.Bold})})); +end Logical; diff --git a/BusinessSimulation/Converters/Logical/package.order b/BusinessSimulation/Converters/Logical/package.order new file mode 100644 index 0000000..b42a500 --- /dev/null +++ b/BusinessSimulation/Converters/Logical/package.order @@ -0,0 +1,17 @@ +AllTrue +And +AnyTrue +Boole +ConstantConverterBoolean +Greater +GreaterEqual +Less +LessEqual +NoneTrue +Not +NotZero +Or +Switch +SwitchN +Threshold +Xor diff --git a/BusinessSimulation/Converters/Lookup/ConcaveLookupNegative.mo b/BusinessSimulation/Converters/Lookup/ConcaveLookupNegative.mo new file mode 100644 index 0000000..32f489f --- /dev/null +++ b/BusinessSimulation/Converters/Lookup/ConcaveLookupNegative.mo @@ -0,0 +1,25 @@ +within BusinessSimulation.Converters.Lookup; + +block ConcaveLookupNegative "Concave Lookup with negative slope; fixpoints are (0,y0) and (1,0)" + extends Interfaces.PartialConverters.SISO; + parameter Real s(min = 1, max = 50) = 1 "Slope parameter (1 <= slope <= 50)"; + parameter Real y0(min = 0) = 1 "Value of y when input is zero or less (intercept)"; +equation + assert(s >= 1, "Slope parameter should not be less than 1", level = AssertionLevel.warning); + assert(y0 >= 0, "Intercept should not be negative", level = AssertionLevel.warning); + y = if noEvent(u <= 0) then y0 elseif noEvent(u < 1) then y0 * (1 - u ^ s) else 0; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output y is derived using the formula:

+

\"y

+

The function will go through the point (0,y0) and the output will be 0 for u ≥ 1 and y0 for u ≤ 0. The input u should thus be in the range [0,1]. The following graph shows plots for the function for different slopes:

+ + + + + + +
Graph of the Lookup-Function for Different Slopes (y0 = 1)
\"Graph.svg\"
+

See also

+

ConcaveLookupPositive, ConvexLookupNegativeConvexLookupPositive

"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {10.816, -30}, points = {{-46.394, 0}, {32.732, 0}, {13.662, 0}}, color = {128, 128, 128}, thickness = 1), Line(visible = true, origin = {-35.548, 9.209}, rotation = -270, points = {{-39.209, 0}, {18.362, 0}, {20.847, 0}}, color = {128, 128, 128}, thickness = 1), Text(visible = true, origin = {7.341, -37.537}, textColor = {128, 128, 128}, extent = {{-18.921, -12}, {18.921, 12}}, textString = "u", fontName = "Lato", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {-43.292, 4.265}, textColor = {128, 128, 128}, extent = {{-18.921, -12}, {18.921, 12}}, textString = "y", fontName = "Lato", textStyle = {TextStyle.Bold}), Line(visible = true, origin = {4, -6.714}, rotation = -180, points = {{-16, 23.286}, {6.446, -3.219}, {38.948, -6.714}}, color = {0, 0, 128}, thickness = 3, smooth = Smooth.Bezier), Ellipse(visible = true, origin = {19.097, -30}, lineColor = {255, 0, 0}, fillColor = {255, 0, 0}, fillPattern = FillPattern.Solid, extent = {{-2, -2}, {2, 2}}), Text(visible = true, origin = {30, 0}, textColor = {128, 128, 128}, extent = {{-18.921, -12}, {18.921, 12}}, textString = "(1,0)", fontName = "Lato")}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end ConcaveLookupNegative; diff --git a/BusinessSimulation/Converters/Lookup/ConcaveLookupPositive.mo b/BusinessSimulation/Converters/Lookup/ConcaveLookupPositive.mo new file mode 100644 index 0000000..7ec2f96 --- /dev/null +++ b/BusinessSimulation/Converters/Lookup/ConcaveLookupPositive.mo @@ -0,0 +1,30 @@ +within BusinessSimulation.Converters.Lookup; + +block ConcaveLookupPositive "Concave Lookup with positive slope; fixpoints are (0,y0) and (1,1)" + extends Interfaces.PartialConverters.SISO; + parameter Real s(min = 0, max = 1) = 0.5 "Slope parameter (0< slope <= 1)"; + parameter Real y0(min = 0, max = 1) = 0 "Value of y when input is zero or less (intercept)"; +equation + assert(y0 >= 0 and y0 <= 1, "Intercept should be within the closed unit interval [0,1]", level = AssertionLevel.warning); + assert(s > 0 and s <= 1, "Slope should be within the interval (0,1]", level = AssertionLevel.warning); + y = if noEvent(u <= 0) then y0 else y0 + (1 - y0) * u ^ s; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output y is derived using the formula:

+

\"y

+

The function will go through the points (1,1) and (0,y0). The output will be y0 for u ≤ 0.

+ + + + + + +
Graph of the Lookup-Function for Different Slopes (y0 = 0)
\"Graph.png\"
+

Notes

+ +

See also

+

ConcaveLookupNegative, ConvexLookupPositiveConvexLookupNegative

"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {10.816, -30}, points = {{-46.394, 0}, {32.732, 0}, {13.662, 0}}, color = {128, 128, 128}, thickness = 1), Line(visible = true, origin = {-35.548, 9.209}, rotation = -270, points = {{-39.209, 0}, {18.362, 0}, {20.847, 0}}, color = {128, 128, 128}, thickness = 1), Text(visible = true, origin = {7.341, -37.537}, textColor = {128, 128, 128}, extent = {{-18.921, -12}, {18.921, 12}}, textString = "u", fontName = "Lato", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {-43.292, 4.265}, textColor = {128, 128, 128}, extent = {{-18.921, -12}, {18.921, 12}}, textString = "y", fontName = "Lato", textStyle = {TextStyle.Bold}), Line(visible = true, origin = {4, -6.714}, rotation = -180, points = {{-35, -17.714}, {15, -2.472}, {37.931, 22.286}}, color = {0, 0, 128}, thickness = 3, smooth = Smooth.Bezier), Line(visible = true, origin = {-16.901, -11.709}, points = {{-18.396, 1.709}, {-2.099, 1.709}}, color = {128, 128, 128}, pattern = LinePattern.Dot, thickness = 1), Line(visible = true, origin = {-16.686, -42.099}, rotation = -90, points = {{-32.099, 1.709}, {-14.975, 1.709}}, color = {128, 128, 128}, pattern = LinePattern.Dot, thickness = 1), Ellipse(visible = true, origin = {-14.903, -10}, lineColor = {255, 0, 0}, fillColor = {255, 0, 0}, fillPattern = FillPattern.Solid, extent = {{-3, -3}, {3, 3}}), Ellipse(visible = true, origin = {-35, -10}, lineColor = {128, 128, 128}, fillColor = {128, 128, 128}, fillPattern = FillPattern.Solid, extent = {{-2, -2}, {2, 2}}), Ellipse(visible = true, origin = {-14.903, -30}, lineColor = {128, 128, 128}, fillColor = {128, 128, 128}, fillPattern = FillPattern.Solid, extent = {{-2, -2}, {2, 2}}), Text(visible = true, origin = {-8.921, 18}, textColor = {128, 128, 128}, extent = {{-18.921, -12}, {18.921, 12}}, textString = "(1,1)", fontName = "Lato")}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end ConcaveLookupPositive; diff --git a/BusinessSimulation/Converters/Lookup/ConvexLookupNegative.mo b/BusinessSimulation/Converters/Lookup/ConvexLookupNegative.mo new file mode 100644 index 0000000..958c2eb --- /dev/null +++ b/BusinessSimulation/Converters/Lookup/ConvexLookupNegative.mo @@ -0,0 +1,28 @@ +within BusinessSimulation.Converters.Lookup; + +block ConvexLookupNegative "Convex Lookup with negative slope usually defined for the range [0,∞) passing through the fixpoint (1,1)" + extends Interfaces.PartialConverters.SISO; + import BusinessSimulation.Constants.eps; + parameter Real y0(min = 1) = 2 "Value of y (intercept) when input is zero or less (y0>1)"; +equation + assert(y0 > 1, "Intercept should be greater than 1", level = AssertionLevel.warning); + y = smooth(3, if u <= 0 then y0 else y0 ^ (1 - u)); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output y is derived using the formula:

+

\"y=y0^(1-u)\"

+

The function will go through the point (1,1) and (0,y0). The output will be y0 for u ≤ 0. The following graph shows plots for the function for different values of y0:

+ + + + + + +
Graph of the Lookup-Function for Different Values of y0
\"Graph.svg\"
+

Notes

+ +

See also

+

ConvexLookupPositive, ConcaveLookupNegativeConcaveLookupPositive

"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {10.816, -30}, points = {{-46.394, 0}, {32.732, 0}, {13.662, 0}}, color = {128, 128, 128}, thickness = 1), Line(visible = true, origin = {-35.548, 9.209}, rotation = -270, points = {{-39.209, 0}, {18.362, 0}, {20.847, 0}}, color = {128, 128, 128}, thickness = 1), Line(visible = true, origin = {16, 10.357}, points = {{27.931, -35}, {-31.224, -28.273}, {-50.578, 13.643}}, color = {0, 0, 128}, thickness = 3, smooth = Smooth.Bezier), Text(visible = true, origin = {7.341, -37.537}, textColor = {128, 128, 128}, extent = {{-18.921, -12}, {18.921, 12}}, textString = "u", fontName = "Lato"), Text(visible = true, origin = {-43.292, 4.265}, textColor = {128, 128, 128}, extent = {{-18.921, -12}, {18.921, 12}}, textString = "y", fontName = "Lato", textStyle = {TextStyle.Bold}), Line(visible = true, origin = {-16.901, -11.709}, points = {{-18.396, 1.709}, {-2.099, 1.709}}, color = {128, 128, 128}, pattern = LinePattern.Dot, thickness = 1), Line(visible = true, origin = {-16.686, -42.099}, rotation = -90, points = {{-32.099, 1.709}, {-14.975, 1.709}}, color = {128, 128, 128}, pattern = LinePattern.Dot, thickness = 1), Ellipse(visible = true, origin = {-14.903, -10}, lineColor = {255, 0, 0}, fillColor = {255, 0, 0}, fillPattern = FillPattern.Solid, extent = {{-3, -3}, {3, 3}}), Ellipse(visible = true, origin = {-35, -10}, lineColor = {128, 128, 128}, fillColor = {128, 128, 128}, fillPattern = FillPattern.Solid, extent = {{-2, -2}, {2, 2}}), Ellipse(visible = true, origin = {-14.903, -30}, lineColor = {128, 128, 128}, fillColor = {128, 128, 128}, fillPattern = FillPattern.Solid, extent = {{-2, -2}, {2, 2}}), Text(visible = true, origin = {10, 8}, textColor = {128, 128, 128}, extent = {{-18.921, -12}, {18.921, 12}}, textString = "(1,1)", fontName = "Lato")}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end ConvexLookupNegative; diff --git a/BusinessSimulation/Converters/Lookup/ConvexLookupPositive.mo b/BusinessSimulation/Converters/Lookup/ConvexLookupPositive.mo new file mode 100644 index 0000000..4dc2236 --- /dev/null +++ b/BusinessSimulation/Converters/Lookup/ConvexLookupPositive.mo @@ -0,0 +1,30 @@ +within BusinessSimulation.Converters.Lookup; + +block ConvexLookupPositive "Convex Lookup with positive slope; usually with fixpoint (0,y0) and fixpoint (1,1)" + extends Interfaces.PartialConverters.SISO; + parameter Real s(min = 1) = 1 "Slope parameter (s>1)"; + parameter Real y0(min = 0, max = 1) = 0 "Value of y when input is zero or less"; +equation + assert(s > 1, "Slope should be greater than 1", level = AssertionLevel.warning); + assert(y0 >= 0 and y0 <= 1, "Intercept should be within the closed unit interval [0,1]", level = AssertionLevel.warning); + y = if noEvent(u <= 0) then y0 else y0 + (1 - y0) * u ^ s; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output y is derived using the formula:

+

\"y=y0

+

The function will go through the point (1,1) and the output will be y0 for u ≤ 0.

+ + + + + + +
Graph of the Lookup-Function for Different Slopes (y0 = 0)
\"Graph.svg\"
+

Notes

+ +

See also

+

ConvexLookupNegative, ConcaveLookupPositiveConcaveLookupNegative

"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {10.816, -30}, points = {{-46.394, 0}, {32.732, 0}, {13.662, 0}}, color = {128, 128, 128}, thickness = 1), Line(visible = true, origin = {-35.548, 9.209}, rotation = -270, points = {{-39.209, 0}, {18.362, 0}, {20.847, 0}}, color = {128, 128, 128}, thickness = 1), Line(visible = true, origin = {-6.931, 6}, points = {{-27.931, -35}, {15.901, -25}, {37.931, 22.286}}, color = {0, 0, 128}, thickness = 3, smooth = Smooth.Bezier), Text(visible = true, origin = {7.341, -37.537}, textColor = {128, 128, 128}, extent = {{-18.921, -12}, {18.921, 12}}, textString = "u", fontName = "Lato", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {-43.292, 4.265}, textColor = {128, 128, 128}, extent = {{-18.921, -12}, {18.921, 12}}, textString = "y", fontName = "Lato", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end ConvexLookupPositive; diff --git a/BusinessSimulation/Converters/Lookup/JanoschekNegative.mo b/BusinessSimulation/Converters/Lookup/JanoschekNegative.mo new file mode 100644 index 0000000..dd38422 --- /dev/null +++ b/BusinessSimulation/Converters/Lookup/JanoschekNegative.mo @@ -0,0 +1,64 @@ +within BusinessSimulation.Converters.Lookup; + +block JanoschekNegative "Janoschek's (S-shaped) growth curve with negative slope" + extends Interfaces.PartialConverters.SISO; + parameter Real upperBound = 2 "Upper asymptote for u <= 0 (upperBound > lowerBound)"; + parameter Real lowerBound = 0 "Lower asymptote for u -> infinity"; + parameter Real growthRate(min = 0) = 2 "Determines the gradient of the curve"; + parameter Real x_ref(min = 0) = 1 "x-value for point of inflection(>0)"; + parameter Real y_ref = 1 "y-value for point of inflection(lowerBound < y_ref < upperBound)"; +protected + Real k; +equation + assert(lowerBound < upperBound, "lowerBound must be smaller than upperBound"); + assert(y_ref > lowerBound and y_ref < upperBound, "y_ref needs to be between lowerBound and upperBound"); + assert(x_ref > 0, "x_ref needs to be greater than zero"); + // parameter k is determined by the constraint: f(x_ref) = y_ref + // for negative sloping curve upperBound and lowerBound simply need to be switched + k = x_ref ^ (-growthRate) * log(((-upperBound) + lowerBound) / (lowerBound - y_ref)); + y = smooth(5, if u <= 0 then upperBound else Functions.janoschek(x = u, l = lowerBound, b = upperBound, k = k, d = growthRate)); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This negative sloping Janoschek-Growth-Curve is simply a modification of the positive version. For more detail see JanoschekPositive.

+

The function is given by the following equation:

+

\"y

+

Where l is the lower boundβ is the upper bound, and δ is a parameter that determines the rate of growth (e.g. steepness of the curve). Given the point of inflection (x_ref,y_ref) the parameter k can be obtained in closed form, which is made use of in this implementation.

+

The following animation shows a growth curve with the following parameters:

+ + + + + + + + + + + + + + + + + + + + + + + +
ParameterValue
upperBound +

2

+
lowerBound +

0.1

+
(x_ref, y_ref) +

(1,1)

+
growthRate +

1, ... ,10

+
+


\"AnimatedGraph.gif\"

+

Notes

+

The lowerBound must be smaller than the upperBound. Also y_ref needs to be in the range [lowerBound, upperBound], while x_ref has to be a positive number larger than zero.

+

See also

+

JanoschekPositive

"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Ellipse(visible = true, lineColor = {0, 0, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-60, -60}, {60, 60}}), Line(visible = true, origin = {11.515, -18.173}, points = {{-46.394, 0}, {32.732, 0}, {13.662, 0}}, color = {128, 128, 128}, thickness = 1), Line(visible = true, origin = {-30, 12.704}, rotation = -270, points = {{-39.209, 0}, {18.362, 0}, {20.847, 0}}, color = {128, 128, 128}, thickness = 1), Line(visible = true, origin = {-16.063, -6.873}, points = {{-13.937, 32.823}, {9.408, 32.823}, {23.387, -7.757}, {51.346, -7.757}}, color = {0, 0, 128}, thickness = 3, smooth = Smooth.Bezier), Line(visible = true, origin = {2.099, -1.709}, points = {{-32.099, 1.709}, {-2.099, 1.709}}, color = {128, 128, 128}, pattern = LinePattern.Dot, thickness = 1), Line(visible = true, origin = {0.314, -32.099}, rotation = -90, points = {{-32.099, 1.709}, {-14.975, 1.709}}, color = {128, 128, 128}, pattern = LinePattern.Dot, thickness = 1), Ellipse(visible = true, origin = {2.097, 0}, lineColor = {255, 0, 0}, fillColor = {255, 0, 0}, fillPattern = FillPattern.Solid, extent = {{-3, -3}, {3, 3}}), Ellipse(visible = true, origin = {-29.903, 0}, lineColor = {128, 128, 128}, fillColor = {128, 128, 128}, fillPattern = FillPattern.Solid, extent = {{-2, -2}, {2, 2}}), Ellipse(visible = true, origin = {2.097, -18}, lineColor = {128, 128, 128}, fillColor = {128, 128, 128}, fillPattern = FillPattern.Solid, extent = {{-2, -2}, {2, 2}}), Text(visible = true, origin = {7.341, -37.537}, textColor = {128, 128, 128}, extent = {{-18.921, -12}, {18.921, 12}}, textString = "u", fontName = "Lato", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {-43.292, 4.265}, textColor = {128, 128, 128}, extent = {{-18.921, -12}, {18.921, 12}}, textString = "y", fontName = "Lato", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end JanoschekNegative; diff --git a/BusinessSimulation/Converters/Lookup/JanoschekPositive.mo b/BusinessSimulation/Converters/Lookup/JanoschekPositive.mo new file mode 100644 index 0000000..76668da --- /dev/null +++ b/BusinessSimulation/Converters/Lookup/JanoschekPositive.mo @@ -0,0 +1,63 @@ +within BusinessSimulation.Converters.Lookup; + +block JanoschekPositive "Janoschek's (S-shaped) growth curve with positive slope" + extends Interfaces.PartialConverters.SISO; + parameter Real lowerBound = 0 "Lower asymptote for u <= 0 (lowerBound < upperBound)"; + parameter Real upperBound = 2 "Upper asymptote for u -> infinity"; + parameter Real growthRate(min = 0) = 2 "Determines the gradient of the curve"; + parameter Real x_ref(min = 0) = 1 "x-value for point of inflection(x_ref > 0)"; + parameter Real y_ref = 1 "y-value for point of inflection(lowerBound < y_ref < upperBound)"; +protected + Real k; +equation + assert(lowerBound < upperBound, "lowerBound must be smaller than upperBound"); + assert(y_ref > lowerBound and y_ref < upperBound, "y_ref needs to be between lowerBound and upperBound"); + assert(x_ref > 0, "x_ref needs to be greater than zero"); + // parameter k is determined by the constraint: f(x_ref) = y_ref + k = x_ref ^ (-growthRate) * log((upperBound - lowerBound) / (upperBound - y_ref)); + y = smooth(5, if u <= 0 then lowerBound else Functions.janoschek(x = u, l = upperBound, b = lowerBound, k = k, d = growthRate)); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Many natural growth processes can be very closely described by s-shaped parametric functions (e.g. logistic curve). A. Janoschek [19] has proposed a growth curve that is determined by four parameters in 1957, which is very similar to the Weibull growth curve.

+

The function is given by the following equation:

+

\"y

+

Where l is the upper boundβ is the lower bound, and δ is a parameter that determines the rate of growth (e.g. steepness of the curve). Given the point of inflection (x_ref,y_ref) the parameter k can be obtained in closed form, which is made use of in this implementation.

+

The following animation shows a growth curve with the following parameters:

+ + + + + + + + + + + + + + + + + + + + + + + +
ParameterValue
upperBound +

2

+
lowerBound +

0.1

+
(x_ref, y_ref) +

(1,1)

+
growthRate +

1, ... ,10

+
+

\"\"

+

Notes

+

The lowerBound must be smaller than the upperBound. Also y_ref needs to be in the range [lowerBound, upperBound], while x_ref has to be a positive number larger than zero.

+

See also

+

JanoschekNegative

"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Ellipse(visible = true, lineColor = {0, 0, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-60, -60}, {60, 60}}), Line(visible = true, origin = {11.515, -18.173}, points = {{-46.394, 0}, {32.732, 0}, {13.662, 0}}, color = {128, 128, 128}, thickness = 1), Line(visible = true, origin = {-30, 12.704}, rotation = -270, points = {{-39.209, 0}, {18.362, 0}, {20.847, 0}}, color = {128, 128, 128}, thickness = 1), Line(visible = true, origin = {21.346, -5.174}, points = {{13.937, 32.823}, {-9.408, 32.823}, {-23.387, -7.757}, {-51.346, -7.757}}, color = {0, 0, 128}, thickness = 3, smooth = Smooth.Bezier), Line(visible = true, origin = {2.099, -1.709}, points = {{-32.099, 1.709}, {-2.099, 1.709}}, color = {128, 128, 128}, pattern = LinePattern.Dot, thickness = 1), Line(visible = true, origin = {0.314, -32.099}, rotation = -90, points = {{-32.099, 1.709}, {-14.975, 1.709}}, color = {128, 128, 128}, pattern = LinePattern.Dot, thickness = 1), Ellipse(visible = true, origin = {2.097, 0}, lineColor = {255, 0, 0}, fillColor = {255, 0, 0}, fillPattern = FillPattern.Solid, extent = {{-3, -3}, {3, 3}}), Ellipse(visible = true, origin = {-29.903, 0}, lineColor = {128, 128, 128}, fillColor = {128, 128, 128}, fillPattern = FillPattern.Solid, extent = {{-2, -2}, {2, 2}}), Ellipse(visible = true, origin = {2.097, -18}, lineColor = {128, 128, 128}, fillColor = {128, 128, 128}, fillPattern = FillPattern.Solid, extent = {{-2, -2}, {2, 2}}), Text(visible = true, origin = {7.341, -37.537}, textColor = {128, 128, 128}, extent = {{-18.921, -12}, {18.921, 12}}, textString = "u", fontName = "Lato", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {-43.292, 4.265}, textColor = {128, 128, 128}, extent = {{-18.921, -12}, {18.921, 12}}, textString = "y", fontName = "Lato", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end JanoschekPositive; diff --git a/BusinessSimulation/Converters/Lookup/PerformanceIndicator.mo b/BusinessSimulation/Converters/Lookup/PerformanceIndicator.mo new file mode 100644 index 0000000..0acfcae --- /dev/null +++ b/BusinessSimulation/Converters/Lookup/PerformanceIndicator.mo @@ -0,0 +1,108 @@ +within BusinessSimulation.Converters.Lookup; + +block PerformanceIndicator "Indicator function using fuzzy membership functions" + import BusinessSimulation.Types.MembershipFunctionTypes; + import BusinessSimulation.Units.Amount; + extends Interfaces.PartialConverters.SISO(redeclare final type OutputType = Units.Dimensionless); + parameter Amount a "Parameter to control shape of membership function" annotation(Dialog(enable = true)); + parameter Amount b "Parameter to control shape of membership function" annotation(Dialog(enable = not (mft == MembershipFunctionTypes.sigmoidal or mft == MembershipFunctionTypes.gaussian))); + parameter Amount c "Parameter to control shape of membership function" annotation(Dialog(enable = not (mft == MembershipFunctionTypes.ramp or mft == MembershipFunctionTypes.sshaped))); + parameter Amount d "Parameter to control shape of membership function" annotation(Dialog(enable = mft == MembershipFunctionTypes.trapezoidal or mft == MembershipFunctionTypes.pishaped or mft == MembershipFunctionTypes.psigmoidal)); + parameter MembershipFunctionTypes mft = MembershipFunctionTypes.ramp "Membership function type to use" annotation(Dialog(group = "Structural Parameters")); + parameter Boolean invertResult = false "= true, if the degree of membership is to be inverted (i.e. y = 1 - mf(u))" annotation(Dialog(group = "Structural Parameters")); +equation + y = if invertResult then 1 - Functions.evalmf(u, mft, a = a, b = b, c = c, d = d) else Functions.evalmf(u, mft, a = a, b = b, c = c, d = d); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output y is the dimensionless degree of membership to the set of \"good performances\" or \"good outcomes\" according to a chosen type of membership function. Using the PerformanceIndicator allows to quickly grasp how a system is currently performing with regard to some criteria: a value of 1 indicates best possible performance, while a value of 0 indicates unsustainable performance.

+

The following grid displays all available membership function types without inversion (invertResults = false):

+

+ + + + + + +
Membership Functions
\"Grid.svg\"
+

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Parameters
Membership Function Typeabcd
rampfootshoulder  
triangularleft footcenterright foot 
trapezoidalleft footleft shoulderright shoulderright foot
sshapedfootshoulder  
sigmoidalsteepness of transition area center of transition area 
pishapedleft footleft shoulderright shoulderright foot
psigmoidalsteepness of left transitioncenter of left transition areasteepness of right transitioncenter of right transition area
gaussianhalf width at half maximum center of curve (maximum) 
bellwidth of coresteepnesscenter of core 
+

+

When inversion is turned on (invertResult = true) the result obtained from the membership function as specified will be subtracted from 1. Thus the ramp shown above can be made to ramp down from left to right with a being the shoulder and b the foot by inverting the results.

+

See also

+

rampmf, trapmf, trimf, smf, sigmf, pimf, psigmf, gaussmf, gbellmf

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {-11.686, -22.099}, rotation = -90, points = {{-44.186, 1.686}, {-14.975, 1.709}}, color = {128, 128, 128}, pattern = LinePattern.Dot, thickness = 1), Line(visible = true, origin = {-8.485, -8.173}, points = {{-46.394, 0}, {32.732, 0}, {13.662, 0}}, color = {128, 128, 128}, thickness = 1), Text(visible = true, origin = {0, -30}, textColor = {0, 0, 128}, extent = {{-36.812, -12}, {36.812, 12}}, textString = "PI", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Line(visible = true, points = {{-7.669, 20}, {18.252, 20}, {23.387, -7.757}, {51.346, -7.757}}, color = {0, 0, 128}, thickness = 3), Ellipse(visible = true, origin = {-9.903, -8}, lineColor = {128, 128, 128}, fillColor = {128, 128, 128}, fillPattern = FillPattern.Solid, extent = {{-2, -2}, {2, 2}}), Text(visible = true, origin = {40, 20}, textColor = {128, 128, 128}, extent = {{-18.921, -12}, {18.921, 12}}, textString = "1", fontName = "Lato"), Line(visible = true, origin = {-47.217, 12.243}, points = {{-7.669, -20}, {18.252, -20}, {27.217, 7.757}, {51.346, 7.757}}, color = {0, 0, 128}, thickness = 3), Ellipse(visible = true, origin = {-10, 20}, lineColor = {255, 0, 0}, fillColor = {255, 0, 0}, fillPattern = FillPattern.Solid, extent = {{-3, -3}, {3, 3}}), Text(visible = true, origin = {-40, -20}, textColor = {128, 128, 128}, extent = {{-18.921, -12}, {18.921, 12}}, textString = "0", fontName = "Lato")}), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end PerformanceIndicator; diff --git a/BusinessSimulation/Converters/Lookup/SShapedNegative.mo b/BusinessSimulation/Converters/Lookup/SShapedNegative.mo new file mode 100644 index 0000000..ea48a4f --- /dev/null +++ b/BusinessSimulation/Converters/Lookup/SShapedNegative.mo @@ -0,0 +1,24 @@ +within BusinessSimulation.Converters.Lookup; + +block SShapedNegative "Symmettric S-shaped curve with negative slope around origin (0,0)" + extends Interfaces.PartialConverters.SISO; + parameter Real upperBound(min = 0) = 1 "Upper asymptote (upperBound > 0)"; + parameter Real s(min = 1) = 2 "Slope controls gradient of curve"; +equation + y = -upperBound * (s ^ u - 1) / (s ^ u + 1); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The SShapedNegative lookup-function is a point symmetric, s-shaped growth function with respect to the origin (0,0) that has a negative slope. The curve has two parameters: An upperBound (lowerBound = -upperBound) and a slope s which is given as a positive number.

+

The output y is obtained by the following formula:

+

\"y

+ + + + + + +
Graph of the Lookup-Function for Different Slopes (upperBound = 1)
\"Graph.svg\"
+

See also

+

SShapedPositive

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, rotation = -270, points = {{50, 0}, {-50, 0}}, color = {128, 128, 128}, thickness = 1), Line(visible = true, rotation = -540, points = {{50, 0}, {-50, 0}}, color = {128, 128, 128}, thickness = 1), Line(visible = true, origin = {16.063, 14.39}, points = {{18.186, -32.823}, {-9.408, -32.823}, {-23.387, 7.757}, {-51.346, 7.757}}, color = {0, 0, 128}, thickness = 3, smooth = Smooth.Bezier), Ellipse(visible = true, origin = {0.097, 0}, lineColor = {255, 0, 0}, fillColor = {255, 0, 0}, fillPattern = FillPattern.Solid, extent = {{-3, -3}, {3, 3}}), Text(visible = true, origin = {44.871, -8}, textColor = {128, 128, 128}, extent = {{-18.921, -12}, {18.921, 12}}, textString = "u", fontName = "Lato", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {-8.921, 47}, textColor = {128, 128, 128}, extent = {{-18.921, -12}, {18.921, 12}}, textString = "y", fontName = "Lato", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end SShapedNegative; diff --git a/BusinessSimulation/Converters/Lookup/SShapedPositive.mo b/BusinessSimulation/Converters/Lookup/SShapedPositive.mo new file mode 100644 index 0000000..7234324 --- /dev/null +++ b/BusinessSimulation/Converters/Lookup/SShapedPositive.mo @@ -0,0 +1,23 @@ +within BusinessSimulation.Converters.Lookup; + +block SShapedPositive "Symmettric S-shaped curve with positive slope around origin (0,0)" + extends Interfaces.PartialConverters.SISO; + parameter Real upperBound(min = 0) = 1 "Upper asymptote (upperBound > 0)"; + parameter Real s(min = 1) = 2 "Slope controls gradient of curve (s > 1)"; +equation + y = upperBound * (s ^ u - 1) / (s ^ u + 1); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The SShapedPositive lookup-function is a point symmetric, s-shaped growth function with respect to the origin (0,0) that has a positive slope. The curve has two parameters: An upperBound (lowerBound = -upperBound) and a slope s which is given as a positive number.

+

The output y is obtained by the following formula:

+

\"y

+ + + + + + +
Graph of the Lookup-Function for Different Slopes (upperBound = 1)
\"Graph.svg\"
+

See also

+

SShapedNegative

"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, rotation = -270, points = {{50, 0}, {-50, 0}}, color = {128, 128, 128}, thickness = 1), Line(visible = true, rotation = -540, points = {{50, 0}, {-50, 0}}, color = {128, 128, 128}, thickness = 1), Line(visible = true, origin = {16.063, -15.61}, points = {{18.186, 32.823}, {-9.408, 32.823}, {-23.387, -7.757}, {-51.346, -7.757}}, color = {0, 0, 128}, thickness = 3, smooth = Smooth.Bezier), Ellipse(visible = true, origin = {0.097, 0}, lineColor = {255, 0, 0}, fillColor = {255, 0, 0}, fillPattern = FillPattern.Solid, extent = {{-3, -3}, {3, 3}}), Text(visible = true, origin = {41.079, -8}, textColor = {128, 128, 128}, extent = {{-18.921, -12}, {18.921, 12}}, textString = "u", fontName = "Lato", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {-8.921, 48}, textColor = {128, 128, 128}, extent = {{-18.921, -12}, {18.921, 12}}, textString = "y", fontName = "Lato", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end SShapedPositive; diff --git a/BusinessSimulation/Converters/Lookup/TableFunction.mo b/BusinessSimulation/Converters/Lookup/TableFunction.mo new file mode 100644 index 0000000..409fd62 --- /dev/null +++ b/BusinessSimulation/Converters/Lookup/TableFunction.mo @@ -0,0 +1,60 @@ +within BusinessSimulation.Converters.Lookup; + +block TableFunction "Table function defined by external data on file using Modelica's CombiTable format" + import Modelica.Blocks.Types.{Extrapolation,Smoothness}; + import BusinessSimulation.Types.TimeBases; + import BusinessSimulation.Types.UnitChoices; + extends Interfaces.PartialConverters.SISO; + extends Icons.InterpolationTable; + parameter Boolean convertInput = false "= true, if the input value is a rate or time variable that needs to be converted" annotation(Dialog(group = "Time Conversion")); + parameter Boolean inputIsRate = false "= true, if the input is given in units of time, otherwise it is assumed to be a rate" annotation(Dialog(group = "Time Conversion", enable = convertInput)); + parameter Boolean convertOutput = false "= true, if the output value is a rate or time variable that needs to be converted" annotation(Dialog(group = "Time Conversion")); + parameter Boolean outputIsRate = false "= true, if the output is given in units of time, otherwise it is assumed to be a rate" annotation(Dialog(group = "Time Conversion", enable = convertOutput)); + parameter TimeBases timeBaseInput = TimeBases.seconds "TimeBase to convert from (default = seconds)" annotation(Evaluate = true, Dialog(enable = convertInput, group = "Time Conversion")); + parameter TimeBases timeBaseTableIn = modelSettings.modelDisplayTimeBase "TimeBase used for the lookup table input (default = modelDisplayTimeBase)" annotation(Evaluate = true, Dialog(enable = convertInput, group = "Time Conversion")); + parameter TimeBases timeBaseTableOut = modelSettings.modelDisplayTimeBase "TimeBase used for the table output (default = modelSettings.modelDisplayTimeBase)" annotation(Evaluate = true, Dialog(enable = convertOutput, group = "Time Conversion")); + parameter TimeBases timeBaseOutput = TimeBases.seconds "TimeBase used for the output (default = seconds)" annotation(Evaluate = true, Dialog(enable = convertOutput, group = "Time Conversion")); + parameter Boolean tableOnFile = false "= true, if table is defined on file or in function usertab (combiTable1D.tableOnFile)" annotation(Dialog(group = "TableDataDefinition")); + parameter Real table[:, :] = fill(0.0, 0, 2) "Table matrix (grid = first column; e.g., table=[0,2]) (combiTable1D.table)" annotation(Dialog(group = "TableDataDefinition", enable = not tableOnFile)); + parameter String tableName = "NoName" "Name of the table in the file containing the data" annotation(Dialog(group = "TableDataDefinition", enable = tableOnFile)); + parameter String fileNameURI = modelSettings.lookupDataFileURI "URI of the file to read the data from (default = modelSettings.lookupDataFileURI)" annotation(Dialog(group = "TableDataDefinition", enable = tableOnFile)); + parameter Smoothness smoothness = Smoothness.LinearSegments "Smoothness of table interpolation" annotation(Dialog(group = "TableDataInterpretation")); + parameter Integer column(min = 2) = 2 "Column of table to be interpolated" annotation(Dialog(group = "TableDataInterpretation")); + // only one column is used in this component + parameter Boolean verboseRead = true "= true, if info message that file is loading is to be printed (combiTable1D.verboseRead)" annotation(Dialog(group = "TableDataDefinition", enable = tableOnFile)); + parameter Extrapolation extrapolation = Modelica.Blocks.Types.Extrapolation.HoldLastPoint "Extrapolation of data outside the definition range (combiTable.extrapolation)" annotation(Dialog(group = "TableDataInterpretation")); + parameter Boolean verboseExtrapolation = false "= true, if warning messages are to be printed if table input is outside the definition range (combiTable.verboseExtrapolation)" annotation(Dialog(group = "TableDataInterpretation")); +protected + outer ModelSettings modelSettings; + parameter String fileName = if tableOnFile then Modelica.Utilities.Files.loadResource(fileNameURI) else "NoName" "Absolute path to the file specified by fileName" annotation(Dialog(group = "Initialization", enable = false)); + RateConversion rateConversionIn(timeBaseA = timeBaseInput, timeBaseB = timeBaseTableIn) if convertInput and inputIsRate "Convert the input (rate) to another time base" annotation(Placement(visible = true, transformation(origin = {-90, 30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + PassThrough noConversionIn if not convertInput "Use input as is" annotation(Placement(visible = true, transformation(origin = {-90, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + TimeConversion timeConversionIn(timeBaseA = timeBaseInput, timeBaseB = timeBaseTableIn) if convertInput and not inputIsRate "Convert the input to another time base" annotation(Placement(visible = true, transformation(origin = {-90, -30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Modelica.Blocks.Tables.CombiTable1Ds combiTable(fileName = fileName, tableName = tableName, smoothness = smoothness, tableOnFile = tableOnFile, table = table, columns = {column}, verboseRead = verboseRead, extrapolation = extrapolation, verboseExtrapolation = verboseExtrapolation) annotation(Placement(visible = true, transformation(origin = {0, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + PassThrough noConversionOut if not convertOutput "Use output as is" annotation(Placement(visible = true, transformation(origin = {60, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + RateConversion rateConversionOut(timeBaseA = timeBaseTableOut, timeBaseB = timeBaseOutput) if convertOutput and outputIsRate "Convert the output (rate) to 1/s" annotation(Placement(visible = true, transformation(origin = {60, 27.063}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + TimeConversion timeConversionOut(timeBaseA = timeBaseTableOut, timeBaseB = timeBaseOutput) if convertOutput and not outputIsRate "Convert the output to seconds" annotation(Placement(visible = true, transformation(origin = {60, -30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + assert(column >= 2 and column <= size(table, 2), "column is out of range"); + connect(u, noConversionIn.u) annotation(Line(visible = true, origin = {-134, 0}, points = {{-36, 0}, {36, 0}}, color = {1, 37, 163})); + connect(noConversionIn.y, combiTable.u) annotation(Line(visible = true, origin = {-47, 0}, points = {{-35, 0}, {35, 0}}, color = {1, 37, 163})); + connect(u, rateConversionIn.u) annotation(Line(visible = true, origin = {-127, 15}, points = {{-43, -15}, {7, -15}, {7, 15}, {29, 15}}, color = {1, 37, 163})); + connect(rateConversionIn.y, combiTable.u) annotation(Line(visible = true, origin = {-43.5, 15}, points = {{-38.5, 15}, {3.5, 15}, {3.5, -15}, {31.5, -15}}, color = {1, 37, 163})); + connect(u, timeConversionIn.u) annotation(Line(visible = true, origin = {-127, -15}, points = {{-43, 15}, {7, 15}, {7, -15}, {29, -15}}, color = {1, 37, 163})); + connect(timeConversionIn.y, combiTable.u) annotation(Line(visible = true, origin = {-43.5, -15}, points = {{-38.5, -15}, {3.5, -15}, {3.5, 15}, {31.5, 15}}, color = {1, 37, 163})); + connect(combiTable.y[1], noConversionOut.u) annotation(Line(visible = true, origin = {31.5, 0}, points = {{-20.5, 0}, {20.5, 0}}, color = {1, 37, 163})); + connect(noConversionOut.y, y) annotation(Line(visible = true, origin = {114, 0}, points = {{-46, 0}, {46, 0}}, color = {1, 37, 163})); + connect(combiTable.y[1], rateConversionOut.u) annotation(Line(visible = true, origin = {28.25, 13.531}, points = {{-17.25, -13.531}, {-3.25, -13.531}, {-3.25, 13.531}, {23.75, 13.531}}, color = {1, 37, 163})); + connect(combiTable.y[1], timeConversionOut.u) annotation(Line(visible = true, origin = {28.25, -15}, points = {{-17.25, 15}, {-3.25, 15}, {-3.25, -15}, {23.75, -15}}, color = {1, 37, 163})); + connect(timeConversionOut.y, y) annotation(Line(visible = true, origin = {107, -15}, points = {{-39, -15}, {-7, -15}, {-7, 15}, {53, 15}}, color = {1, 37, 163})); + connect(rateConversionOut.y, y) annotation(Line(visible = true, origin = {107, 13.531}, points = {{-39, 13.532}, {-7, 13.531}, {-7, -13.531}, {53.268, -13.531}}, color = {1, 37, 163})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This converter uses the Modelica CombiTable format to read in a 1-D table function from file. For more explanation regarding the 1-D Modelica CombiTable interpolation see Modelica.Blocks.Tables.CombiTable1Ds.

+

Notes

+

The Modelica CombiTable format can be generated by Wolfram Mathematica using Export[]:

+

Export[ filename, { {\"TableName1\", table1}, {\"TableName2\", table2}, ... }, \"MCTT\" ]

+

where table1, table2, ... are 2-dimensional arrays. By default all lookup data are assumed to be included in a single file whose name is given by the global parameter lookupDataFileURI.

+

See also

+

TableFunctionVectorLinearTimeTable

"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end TableFunction; diff --git a/BusinessSimulation/Converters/Lookup/TableFunctionVector.mo b/BusinessSimulation/Converters/Lookup/TableFunctionVector.mo new file mode 100644 index 0000000..a017c17 --- /dev/null +++ b/BusinessSimulation/Converters/Lookup/TableFunctionVector.mo @@ -0,0 +1,35 @@ +within BusinessSimulation.Converters.Lookup; + +block TableFunctionVector "Table function for vector input and output using Modelica's CombiTable format" + import Modelica.Blocks.Types.{Extrapolation,Smoothness}; + extends Interfaces.PartialConverters.MIMO_nin; + extends Icons.InterpolationTable; + parameter Boolean tableOnFile = false "= true, if table is defined on file or in function usertab (combiTable1D.tableOnFile)" annotation(Dialog(group = "TableDataDefinition")); + parameter Real table[:, :] = fill(0.0, 0, 2) "Table matrix (grid = first column; e.g., table=[0,2]) (combiTable1D.table)" annotation(Dialog(group = "TableDataDefinition", enable = not tableOnFile)); + parameter String tableName = "NoName" "Name of the table in the file containing the data" annotation(Dialog(group = "TableDataDefinition", enable = tableOnFile)); + parameter String fileNameURI = modelSettings.lookupDataFileURI "URI of the file to read the data from (default = lookupDataFileURI)" annotation(Dialog(group = "TableDataDefinition", enable = tableOnFile)); + parameter Smoothness smoothness = Smoothness.LinearSegments "Smoothness of table interpolation" annotation(Dialog(group = "TableDataInterpretation")); + parameter Integer[nin] columns = fill(2, nin) "Columns of table to be interpolated (length must be equal to length of input and output vectors)" annotation(Dialog(group = "TableDataInterpretation")); + parameter Boolean verboseRead = true "= true, if info message that file is loading is to be printed (combiTable1D.verboseRead)" annotation(Dialog(group = "TableDataDefinition", enable = tableOnFile)); + parameter Extrapolation extrapolation = Extrapolation.LastTwoPoints "Extrapolation of data outside the definition range (combiTable1D.extrapolation)" annotation(Dialog(group = "TableDataInterpretation")); + parameter Boolean verboseExtrapolation = false "= true, if warning messages are to be printed if table input is outside the definition range (combiTable1D.verboseExtrapolation)" annotation(Dialog(group = "TableDataInterpretation")); +protected + outer ModelSettings modelSettings; + parameter String fileName = if tableOnFile then Modelica.Utilities.Files.loadResource(fileNameURI) else "NoName" "Absolute path to the file specified by fileName" annotation(Dialog(group = "Initialization", enable = false)); + Modelica.Blocks.Tables.CombiTable1D combiTable1D(smoothness = smoothness, tableOnFile = tableOnFile, tableName = tableName, fileName = fileName, verboseRead = verboseRead, table = table, columns = columns, extrapolation = extrapolation, verboseExtrapolation = verboseExtrapolation) "Modelica combi table" annotation(Placement(visible = true, transformation(origin = {0, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(u, combiTable1D.u) annotation(Line(visible = true, origin = {-91, 0}, points = {{-79, 0}, {79, 0}}, color = {1, 37, 163})); + connect(combiTable1D.y, y) annotation(Line(visible = true, origin = {85.5, 0}, points = {{-74.5, 0}, {74.5, 0}}, color = {1, 37, 163})); + // assert statements + assert(size(columns, 1) == nin, "Columns vector does not match length of input vector"); + // assert(min(columns) >= 2 and max(columns) <= size(table, 2), "Columns are out of range"); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This converter uses the Modelica CombiTable format to read in a 1-D table function from file. For more explanation regarding the 1-D Modelica CombiTable interpolation see Modelica.Blocks.Tables.CombiTable1D.

+

Notes

+

The Modelica CombiTable format can be generated by Wolfram Mathematica using Export[]:

+

Export[ filename, { {\"TableName1\", table1}, {\"TableName2\", table2}, ... }, \"MCTT\" ]

+

where table1, table2, ... are 2-dimensional arrays. By default all lookup data are assumed to be included in a single file whose name is given by the global parameter lookupDataFileURI.

+

See also

+

TableFunctionLinearTimeTable

"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end TableFunctionVector; diff --git a/BusinessSimulation/Converters/Lookup/package.mo b/BusinessSimulation/Converters/Lookup/package.mo new file mode 100644 index 0000000..c321d80 --- /dev/null +++ b/BusinessSimulation/Converters/Lookup/package.mo @@ -0,0 +1,14 @@ +within BusinessSimulation.Converters; + +package Lookup "Table- or Lookup-Functions" + extends Icons.Package; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Table- or Lookup-Functions usually map some variable (usually normalized as a dimensionless input) onto a real number by either providing a parametric funcion or a table of values which is then used for interpolation. Typically lookup functions are nonlinear functions and introduce nonlinearity to dynamic models [3, Ch. 14].

+

Acknowledgements

+

The parametric lookup functions presented in this package are to a great part inspired by an article written by Khalid Saeed and Arit Irmaridiris [4]. They either directly use the proposed functional form from that article or were slightly modified by the author of the Business Simulation Library using Wolfram Mathematica.

+
+
+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {8.727, -28.173}, points = {{-53.606, 0}, {47.157, 0}}, color = {255, 255, 255}, thickness = 3, arrow = {Arrow.None, Arrow.Filled}, arrowSize = 10), Line(visible = true, origin = {-40, 11.52}, rotation = -270, points = {{-48.025, 0}, {9.546, 0}, {38.48, 0}}, color = {255, 255, 255}, thickness = 3, arrow = {Arrow.None, Arrow.Filled}, arrowSize = 10), Line(visible = true, origin = {11.346, -8.899}, points = {{13.937, 32.823}, {-9.408, 32.823}, {-23.387, -7.757}, {-51.346, -7.757}}, color = {255, 255, 255}, thickness = 5, smooth = Smooth.Bezier)}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Lookup; diff --git a/BusinessSimulation/Converters/Lookup/package.order b/BusinessSimulation/Converters/Lookup/package.order new file mode 100644 index 0000000..c7ec27d --- /dev/null +++ b/BusinessSimulation/Converters/Lookup/package.order @@ -0,0 +1,11 @@ +ConcaveLookupNegative +ConcaveLookupPositive +ConvexLookupNegative +ConvexLookupPositive +JanoschekPositive +JanoschekNegative +PerformanceIndicator +SShapedNegative +SShapedPositive +TableFunction +TableFunctionVector diff --git a/BusinessSimulation/Converters/Max.mo b/BusinessSimulation/Converters/Max.mo new file mode 100644 index 0000000..27ed444 --- /dev/null +++ b/BusinessSimulation/Converters/Max.mo @@ -0,0 +1,13 @@ +within BusinessSimulation.Converters; + +block Max "Return the largest value" + extends Interfaces.PartialConverters.SI2SO; +equation + y = max(u1, u2); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output y is the maximum of the inputs u1 and u2.

+

See also

+

Vector.Max

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {0, 0, 128}, extent = {{-40.484, -12}, {40.484, 12}}, textString = "MAX", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Max; diff --git a/BusinessSimulation/Converters/Min.mo b/BusinessSimulation/Converters/Min.mo new file mode 100644 index 0000000..82591ce --- /dev/null +++ b/BusinessSimulation/Converters/Min.mo @@ -0,0 +1,12 @@ +within BusinessSimulation.Converters; + +block Min "Return the smallest value" + extends Interfaces.PartialConverters.SI2SO; +equation + y = min(u1, u2); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output y is the minimum of the inputs u1 and u2.

+

See also

+

Vector.Min

"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {0, 0, 128}, extent = {{-40.484, -12}, {40.484, 12}}, textString = "MIN", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Min; diff --git a/BusinessSimulation/Converters/PassThrough.mo b/BusinessSimulation/Converters/PassThrough.mo new file mode 100644 index 0000000..e2db917 --- /dev/null +++ b/BusinessSimulation/Converters/PassThrough.mo @@ -0,0 +1,12 @@ +within BusinessSimulation.Converters; + +block PassThrough "Output is identical to input" + extends Interfaces.PartialConverters.SISO; +equation + y = u; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output y is identical to the input u.

+

Notes

+

This component is most often useful as a conditional component: Graphical components and their connections are automatically removed when the component is not active, so the PassThrough component can be used to switch bewtween different structural configurations inside a component (e.g. have an input be modified or unmodified according to some switch as is done in BusinessSimulation.SourcesOrSinks.ExponentialGrowth where the input rate is turned to a force of interest or left unchanged according to a structural parameter).

", revisions = ""), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {-4.277, 0}, points = {{-80.493, 0}, {80.493, 0}}, color = {0, 0, 128}, thickness = 2.5, arrowSize = 0)}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end PassThrough; diff --git a/BusinessSimulation/Converters/PolynomialFunction.mo b/BusinessSimulation/Converters/PolynomialFunction.mo new file mode 100644 index 0000000..9e957ec --- /dev/null +++ b/BusinessSimulation/Converters/PolynomialFunction.mo @@ -0,0 +1,14 @@ +within BusinessSimulation.Converters; + +block PolynomialFunction "Transform the input according to a polynomial function with given coefficients" + extends Interfaces.PartialConverters.SISO; + parameter Real a[:] = {0, 1} "Vector of coefficients (a_0, a_1, ..., a_n)"; +protected + parameter Integer n(min = 0) = size(a, 1) - 1 "Degree of the polynomial function"; +equation + y = Functions.polynomialFunction(a = a, x = u); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The PolynomialFunction converter transforms the input signal u according to a polynomial function of degree n:

+

\"y

"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {-1.78, 2.761}, textColor = {0, 0, 128}, extent = {{-60, -12}, {60, 12}}, textString = "P(x)", fontName = "Lato Black", textStyle = {TextStyle.Bold, TextStyle.Italic})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end PolynomialFunction; diff --git a/BusinessSimulation/Converters/Power.mo b/BusinessSimulation/Converters/Power.mo new file mode 100644 index 0000000..654f060 --- /dev/null +++ b/BusinessSimulation/Converters/Power.mo @@ -0,0 +1,15 @@ +within BusinessSimulation.Converters; + +block Power "Exponentiation of input" + extends Interfaces.PartialConverters.SISO; + Interfaces.Connectors.RealInput u_exponent if not hasConstantExponent "The exponent for the exponentiation (optional)" annotation(Placement(visible = true, transformation(origin = {-145, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {0, 80}, extent = {{-10, 10}, {10, -10}}, rotation = -90))); + parameter Real exponent = 1 "Constant exponent for the exponentiation (optional)" annotation(Dialog(enable = hasConstantExponent)); + parameter Boolean hasConstantExponent = true "= true, if the exponent is a constant parameter" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); +equation + y = if hasConstantExponent then u ^ exponent else u ^ u_exponent; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output y is the exponentiationen of base u to either a constant power exponent or a variable power u_exponent.

+
y = u ^ exponent
+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {0, 0, 128}, extent = {{-40.484, -12}, {40.484, 12}}, textString = "POWER", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Power; diff --git a/BusinessSimulation/Converters/Product_2.mo b/BusinessSimulation/Converters/Product_2.mo new file mode 100644 index 0000000..5075ca6 --- /dev/null +++ b/BusinessSimulation/Converters/Product_2.mo @@ -0,0 +1,13 @@ +within BusinessSimulation.Converters; + +block Product_2 "Inputs are multiplied" + extends Interfaces.PartialConverters.SI2SO; +equation + y = u1 * u2; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output y is the product of inputs u1 and u2.

+

See also

+

Product_3Vector.Product

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, points = {{15, 15}, {-15, -15}}, color = {0, 0, 128}, thickness = 4, arrowSize = 0), Line(visible = true, rotation = -270, points = {{15, 15}, {-15, -15}}, color = {0, 0, 128}, thickness = 4, arrowSize = 0)}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Product_2; diff --git a/BusinessSimulation/Converters/Product_3.mo b/BusinessSimulation/Converters/Product_3.mo new file mode 100644 index 0000000..994d596 --- /dev/null +++ b/BusinessSimulation/Converters/Product_3.mo @@ -0,0 +1,13 @@ +within BusinessSimulation.Converters; + +block Product_3 "Inputs are multiplied" + extends Interfaces.PartialConverters.SI3SO; +equation + y = u1 * u2 * u3; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output y is the product of the inputs u1, u2, and u3.

+

See also

+

Product_2Vector.Product

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, points = {{15, 15}, {-15, -15}}, color = {0, 0, 128}, thickness = 4, arrowSize = 0), Line(visible = true, rotation = -270, points = {{15, 15}, {-15, -15}}, color = {0, 0, 128}, thickness = 4, arrowSize = 0)}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Product_3; diff --git a/BusinessSimulation/Converters/RateConversion.mo b/BusinessSimulation/Converters/RateConversion.mo new file mode 100644 index 0000000..73739a4 --- /dev/null +++ b/BusinessSimulation/Converters/RateConversion.mo @@ -0,0 +1,24 @@ +within BusinessSimulation.Converters; + +block RateConversion "Converts a rate given per time base A to a rate per time base B" + import BusinessSimulation.Types.TimeBases; + extends Icons.Converter; + Interfaces.Connectors.RealInput u annotation(Placement(visible = true, transformation(origin = {-145, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealOutput y(quantity = "Rate", unit = unitOutput) annotation(Placement(visible = true, transformation(origin = {160, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {80, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + parameter TimeBases timeBaseA = modelSettings.modelDisplayTimeBase "TimeBase to convert from" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter TimeBases timeBaseB = TimeBases.seconds "TimeBase to convert to (default = seconds)" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + outer ModelSettings modelSettings; +protected + parameter String unitOutput = "1/" + BusinessSimulation.Constants.timeBaseUnits[timeBaseB] "Unit for the output" annotation(Dialog(tab = "Ïnitialization", enable = false)); +equation + y = u * 1 / BusinessSimulation.Constants.timeBaseConversionFactors[timeBaseA, timeBaseB]; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output y is derived from converting the input u assumed to be given as a rate in units of timeBaseA to a rate given in units of timeBaseB

+

Notes

+

The best way to work with time in Modelica is to use the SIunit [s] for all internal representations and calculations while making use of displayUnit to convert input and output to and from s to another unit of time preferred by the modeler. That way models will be compatible with models from other domains.

+

Nevertheless, there may be use cases where within the model working with other timeBases will be necessary. Thus there may be need to convert from one time base to another which this converter fulfills.

+

See also

+

TimeConversion

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, 25}, textColor = {128, 128, 128}, extent = {{-56.96, -9}, {56.96, 9}}, textString = "RATE", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, textColor = {0, 0, 128}, extent = {{-58.48, -12}, {58.48, 12}}, textString = "TIME BASE", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {0, -25}, textColor = {128, 128, 128}, extent = {{-56.96, -9}, {56.96, 9}}, textString = "A → B", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end RateConversion; diff --git a/BusinessSimulation/Converters/Rescale.mo b/BusinessSimulation/Converters/Rescale.mo new file mode 100644 index 0000000..e15ba0f --- /dev/null +++ b/BusinessSimulation/Converters/Rescale.mo @@ -0,0 +1,20 @@ +within BusinessSimulation.Converters; + +block Rescale "Rescales input to run from y_min to y_max over the range u_min to u_max" + extends Interfaces.PartialConverters.SISO; + parameter Real u_min "Minimum value for the original range [u_min, u_max]"; + parameter Real u_max "Maximum value for the original range [u_min, u_max]"; + parameter Real y_min = 0 "Minimum value for the transformed range [y_min, y_max]"; + parameter Real y_max = 1 "Maximum value for the transformed range [y_min, y_max]"; +equation + assert(u_min < u_max, "Minimum value must be less than maximum"); + y = Functions.rescale(u, {u_min, u_max}, {y_min, y_max}); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The input u will be rescaled to run from y_min to y_max over the range u_min to u_max to obtain the output y.

+

Implementation

+
+
y = Functions.rescale( x, {u_min,u_max}, {y_min, y_max});
+

See also  

+

Functions.rescale

", revisions = ""), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {0, 0, 128}, extent = {{-40, -12}, {40, 12}}, textString = "RESCALE", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Rescale; diff --git a/BusinessSimulation/Converters/Special/GameInput_BETA.mo b/BusinessSimulation/Converters/Special/GameInput_BETA.mo new file mode 100644 index 0000000..79d5b24 --- /dev/null +++ b/BusinessSimulation/Converters/Special/GameInput_BETA.mo @@ -0,0 +1,23 @@ +within BusinessSimulation.Converters.Special; + +block GameInput_BETA "Enable user input, if gaming mode is activated" + extends Interfaces.PartialConverters.SO; + Interfaces.Connectors.RealInput u "Input to be used if gaming = false" annotation(Placement(visible = true, transformation(origin = {-145, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, 0}, extent = {{-10, -10}, {10, 10}}, rotation = -360))); + Interfaces.Connectors.RealInput u_User if modelSettings.gaming "User input to be used if gaming = true" annotation(Placement(visible = true, transformation(origin = {-145, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {0, 80}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); +protected + outer ModelSettings modelSettings; + ConstantConverter zero(final value = 0) if not modelSettings.gaming "Dummy input for gaming = false" annotation(Placement(visible = true, transformation(origin = {-60, 5}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Logical.Switch chooseInput "Choose the right input" annotation(Placement(visible = true, transformation(origin = {0, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Logical.ConstantConverterBoolean gamingQ(value = modelSettings.gaming) "= true, if gaming mode is activated" annotation(Placement(visible = true, transformation(origin = {-20, 60}, extent = {{-10, -10}, {10, 10}}, rotation = -360))); +equation + connect(chooseInput.y, y) annotation(Line(visible = true, origin = {83.681, 0}, points = {{-76.319, 0}, {76.319, 0}}, color = {1, 37, 163})); + connect(u, chooseInput.u2) annotation(Line(visible = true, origin = {-47, -22.5}, points = {{-98, -17.5}, {7, -17.5}, {7, 17.5}, {39, 17.5}}, color = {1, 37, 163})); + connect(u_User, chooseInput.u1) annotation(Line(visible = true, origin = {-47, 12.5}, points = {{-98, 27.5}, {7, 27.5}, {7, -7.5}, {39, -7.5}}, color = {1, 37, 163})); + connect(zero.y, chooseInput.u1) annotation(Line(visible = true, origin = {-31, 5}, points = {{-23, 0}, {23, 0}}, color = {1, 37, 163})); + connect(gamingQ.y, chooseInput.u_cond) annotation(Line(visible = true, origin = {-4.992, 42.663}, points = {{-10.008, 17.337}, {5.004, 17.337}, {5.004, -34.675}}, color = {190, 52, 178})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This component allows to easily set up a model for either gaming = true (e.g. the user has to provide an input u_User that is then used in the model) or as a regular model (e.g. the model provides the input u that can be used if gaming = false).

+

Notes

+

The input u_User is conditional upon the global boolean parameter gaming. If there are to be corresponding user inputs at the top level of a model, then these should be connected to the appropriate u_User inputs of GameInput components at deeper levels. These top level inputs should then also be made conditional, so that the model will be balanced for the case gaming = false as well.

", revisions = ""), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Ellipse(visible = true, lineColor = {0, 0, 128}, fillColor = {255, 255, 255}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-58, -58}, {58, 58}}), Text(visible = true, textColor = {128, 0, 128}, extent = {{-31.731, -40}, {31.731, 40}}, textString = "?", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end GameInput_BETA; diff --git a/BusinessSimulation/Converters/Special/RangeAssert.mo b/BusinessSimulation/Converters/Special/RangeAssert.mo new file mode 100644 index 0000000..03e9f28 --- /dev/null +++ b/BusinessSimulation/Converters/Special/RangeAssert.mo @@ -0,0 +1,25 @@ +within BusinessSimulation.Converters.Special; + +block RangeAssert "Do assert() checks to monitor an admissable range of values" + extends Icons.Converter; + import BusinessSimulation.Constants.inf; + Interfaces.Connectors.RealInput u "Real input" annotation(Placement(visible = true, transformation(origin = {-160, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + parameter Real maxValue = inf "Upper value for admissable range"; + parameter Real minValue = -inf "Lower value for admissable range"; + parameter Boolean causeError = true "= true, if level = AssertionLevel.error" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); +equation + if causeError then + assert(u <= maxValue, "Value out of range (too high)", level = AssertionLevel.error); + assert(u >= minValue, "Value out of range (too low)", level = AssertionLevel.error); + else + assert(u <= maxValue, "Value out of range (too high)", level = AssertionLevel.warning); + assert(u >= minValue, "Value out of range (too low)", level = AssertionLevel.warning); + end if; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The component will set up the following assert functions:

+
assert(u <= maxValue, \"Value out of range (too high)\", level = AssertionLevel.error);
assert(u >= minValue, \"Value out of range (too low)\", level = AssertionLevel.error);
+
+

See also

+

VariableRangeAssert

"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, 1.656}, textColor = {255, 0, 0}, extent = {{-56.96, -12}, {56.96, 12}}, textString = "assert", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {0, -25}, textColor = {128, 128, 128}, extent = {{-56.96, -9}, {56.96, 9}}, textString = "min ≤ u ≤ max", fontName = "Lato Black", textStyle = {TextStyle.Bold})})); +end RangeAssert; diff --git a/BusinessSimulation/Converters/Special/VariableRangeAssert.mo b/BusinessSimulation/Converters/Special/VariableRangeAssert.mo new file mode 100644 index 0000000..8e07340 --- /dev/null +++ b/BusinessSimulation/Converters/Special/VariableRangeAssert.mo @@ -0,0 +1,25 @@ +within BusinessSimulation.Converters.Special; + +block VariableRangeAssert "Do assert() checks to monitor an admissable range of values" + extends Icons.Converter; + import BusinessSimulation.Constants.inf; + Interfaces.Connectors.RealInput u "Real input" annotation(Placement(visible = true, transformation(origin = {-145, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealInput u_max "Real input of maximum value" annotation(Placement(visible = true, transformation(origin = {-145, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, 50}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealInput u_min "Real input of minimum value" annotation(Placement(visible = true, transformation(origin = {-145, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, -50}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + parameter Boolean causeError = true "= true, if level = AssertionLevel.error" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); +equation + if causeError then + assert(u <= u_max, "Value out of range (too high)", level = AssertionLevel.error); + assert(u >= u_min, "Value out of range (too low)", level = AssertionLevel.error); + else + assert(u <= u_max, "Value out of range (too high)", level = AssertionLevel.warning); + assert(u >= u_min, "Value out of range (too low)", level = AssertionLevel.warning); + end if; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The component will set up the following assert functions:

+
assert(u <= u_max, \"Value out of range (too high)\", level = AssertionLevel.error);
assert(u >= u_min, \"Value out of range (too low)\", level = AssertionLevel.error);
+
+

See also

+

RangeAssert

"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, 1.656}, textColor = {255, 0, 0}, extent = {{-56.96, -12}, {56.96, 12}}, textString = "assert", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {0, -25}, textColor = {128, 128, 128}, extent = {{-56.96, -9}, {56.96, 9}}, textString = "min ≤ u ≤ max", fontName = "Lato Black", textStyle = {TextStyle.Bold})})); +end VariableRangeAssert; diff --git a/BusinessSimulation/Converters/Special/package.mo b/BusinessSimulation/Converters/Special/package.mo new file mode 100644 index 0000000..3281765 --- /dev/null +++ b/BusinessSimulation/Converters/Special/package.mo @@ -0,0 +1,12 @@ +within BusinessSimulation.Converters; + +package Special "Special converters - often used as utility functions" + extends Icons.Package; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This package contains converters that are more or less technical.

+
+
+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {255, 255, 255}, extent = {{-96.85, -20}, {96.85, 20}}, textString = "SPECIAL", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Special; diff --git a/BusinessSimulation/Converters/Special/package.order b/BusinessSimulation/Converters/Special/package.order new file mode 100644 index 0000000..0bad12a --- /dev/null +++ b/BusinessSimulation/Converters/Special/package.order @@ -0,0 +1,3 @@ +GameInput_BETA +RangeAssert +VariableRangeAssert diff --git a/BusinessSimulation/Converters/TimeConversion.mo b/BusinessSimulation/Converters/TimeConversion.mo new file mode 100644 index 0000000..429a992 --- /dev/null +++ b/BusinessSimulation/Converters/TimeConversion.mo @@ -0,0 +1,24 @@ +within BusinessSimulation.Converters; + +block TimeConversion "Converts a time signal from time base A to time base B" + import BusinessSimulation.Types.TimeBases; + extends Icons.Converter; + Interfaces.Connectors.RealInput u annotation(Placement(visible = true, transformation(origin = {-145, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealOutput y(quantity = "Time", unit = unitOutput) annotation(Placement(visible = true, transformation(origin = {160, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {80, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + parameter TimeBases timeBaseA = modelSettings.modelDisplayTimeBase "TimeBase to convert from" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter TimeBases timeBaseB = TimeBases.seconds "TimeBase to convert to (default = seconds)" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + outer ModelSettings modelSettings; +protected + parameter String unitOutput = BusinessSimulation.Constants.timeBaseUnits[timeBaseB] "Unit for the output" annotation(Evaluate = true, Dialog(enable = false, tab = "Initialization")); +equation + y = u * BusinessSimulation.Constants.timeBaseConversionFactors[timeBaseA, timeBaseB]; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output y is derived from converting the input u assumed to be given in units of timeBaseA to timeBaseB

+

Notes

+

The best way to work with time in Modelica is to use the SIunit [s] for all internal representations and calculations while making use of displayUnit to convert input and output to and from s to another unit of time preferred by the modeler. That way models will be compatible with models from other domains.

+

Nevertheless, there may be use cases where within the model working with other timeBases will be necessary. Thus there may be need to convert from one time base to another which this converter fulfills.

+

See also

+

RateConversion

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, 1.656}, textColor = {0, 0, 128}, extent = {{-56.96, -12}, {56.96, 12}}, textString = "TIME BASE", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {0, -25}, textColor = {128, 128, 128}, extent = {{-56.96, -9}, {56.96, 9}}, textString = "A → B", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end TimeConversion; diff --git a/BusinessSimulation/Converters/Vector/ArithmeticMean.mo b/BusinessSimulation/Converters/Vector/ArithmeticMean.mo new file mode 100644 index 0000000..e9c78e0 --- /dev/null +++ b/BusinessSimulation/Converters/Vector/ArithmeticMean.mo @@ -0,0 +1,31 @@ +within BusinessSimulation.Converters.Vector; + +block ArithmeticMean "(Weighted) arithmetic mean" + extends Interfaces.PartialConverters.MISO; + parameter Real[nin] weights = ones(nin) "Weights to be used for inputs" annotation(Dialog(enable = useWeights and hasConstantWeights)); + parameter Boolean useWeights = false "= true, if the output is to be a weighted arithmetic mean" annotation(Dialog(group = "Structural Parameters")); + parameter Boolean hasConstantWeights = true "= true, if the weights are constant" annotation(Dialog(group = "Structural Parameters", enable = useWeights)); + Interfaces.Connectors.RealMultiInput u_weights[nin] if useWeights and not hasConstantWeights "Input of weights" annotation(Placement(visible = true, transformation(origin = {-145, 35}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {0, 80}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); +protected + Interfaces.Connectors.RealMultiInput[nin] constWeights = weights if not useWeights or hasConstantWeights; + Interfaces.Connectors.RealMultiOutput[nin] w; +equation + connect(constWeights, w); + connect(u_weights, w); + y = Functions.arithmeticMean(u, w); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The scalar output y is obtained as a convex combination of the components of the input vector u:

+

\"y

+

Notes

+ +

See also

+

+arithmeticMean, +GeometricMean +

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {0, 0, 128}, extent = {{-40.484, -12}, {40.484, 12}}, textString = "MEAN", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {0, -20}, textColor = {128, 128, 128}, extent = {{-43.883, -9}, {43.883, 9}}, textString = "Arithmetic", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end ArithmeticMean; diff --git a/BusinessSimulation/Converters/Vector/Clip.mo b/BusinessSimulation/Converters/Vector/Clip.mo new file mode 100644 index 0000000..b8980d7 --- /dev/null +++ b/BusinessSimulation/Converters/Vector/Clip.mo @@ -0,0 +1,15 @@ +within BusinessSimulation.Converters.Vector; + +block Clip "Clips input vector so that all components remain within a given interval" + import BusinessSimulation.Constants.inf; + extends Interfaces.PartialConverters.MIMO_nin; + parameter Real minValue = -inf "Minimum value (default = - infinity)"; + parameter Real maxValue = inf "Maximum value (default = infinity)"; +algorithm + y := Functions.clip(u, {minValue, maxValue}); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The input vector u will be clipped to make sure that its components remain within the interval [minValue, maxValue] before it is given as output vector y having the same dimensions.

+

See also

+

Functions.clip

", revisions = ""), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {0, 0, 128}, extent = {{-36.812, -12}, {36.812, 12}}, textString = "CLIP", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Clip; diff --git a/BusinessSimulation/Converters/Vector/ComplementFractions.mo b/BusinessSimulation/Converters/Vector/ComplementFractions.mo new file mode 100644 index 0000000..a8cebff --- /dev/null +++ b/BusinessSimulation/Converters/Vector/ComplementFractions.mo @@ -0,0 +1,14 @@ +within BusinessSimulation.Converters.Vector; + +block ComplementFractions "Taking a vector of k fractions of 1 and adding another fraction as to achieve a total of 1" + extends Interfaces.PartialConverters.MO(redeclare replaceable type OutputType = Units.Fraction); + Interfaces.Connectors.RealMultiInput[nout - 1] u "Inputs, the total of which should be less than one" annotation(Placement(visible = true, transformation(origin = {-145, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +protected + Real y_comp "The complement of the total input with regard to 1 or zero"; +equation + y_comp = max(0, 1 - sum(u)); + y = cat(1, u, vector(y_comp)); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The vector output y is obtained by adding another element y_comp to the list of inputs so that the total is 1. If the sum of the inputs is larger than one, then the element added to the list of inputs will be zero. 

"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {16.393, 0}, textColor = {0, 0, 128}, extent = {{-40.484, -12}, {40.484, 12}}, textString = "= 1", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {-22, 6}, textColor = {0, 0, 128}, extent = {{-22.881, -36.024}, {22.881, 36.024}}, textString = "∑", fontName = "Lato", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end ComplementFractions; diff --git a/BusinessSimulation/Converters/Vector/ConstantConverter.mo b/BusinessSimulation/Converters/Vector/ConstantConverter.mo new file mode 100644 index 0000000..38b965f --- /dev/null +++ b/BusinessSimulation/Converters/Vector/ConstantConverter.mo @@ -0,0 +1,19 @@ +within BusinessSimulation.Converters.Vector; + +block ConstantConverter "A list of constant values is turned into a constant vector of signals" + extends Icons.ConstantConverter; + extends Interfaces.Basics.OutputTypeChoice; + RealMultiOutput[size(value, 1)] y annotation(Placement(visible = true, transformation(origin = {152.114, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {60, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + parameter OutputType[:] value = {0} "List of constant values"; +equation + y = value; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The parameter value (a vector) is used to set the continous output y making it a vector of constant-valued signals.

+

Notes

+ +

See also

+

ConstantConverterConstantConverterRateConstantConverterTimeConstantConverterBoolean

"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, 60}, textColor = {0, 0, 128}, extent = {{-100, -6}, {100, 6}}, textString = "%value", fontName = "Lato")})); +end ConstantConverter; diff --git a/BusinessSimulation/Converters/Vector/ConstantConverterRate.mo b/BusinessSimulation/Converters/Vector/ConstantConverterRate.mo new file mode 100644 index 0000000..1b6f8b0 --- /dev/null +++ b/BusinessSimulation/Converters/Vector/ConstantConverterRate.mo @@ -0,0 +1,32 @@ +within BusinessSimulation.Converters.Vector; + +block ConstantConverterRate "A list of constant rates is turned into a vector of rate signals" + import BusinessSimulation.Types.TimeBases; + import BusinessSimulation.Units.{Rate,Dimensionless}; + extends Icons.ConstantConverter; + extends Interfaces.Basics.OutputTypeChoice_Rate; + RealMultiOutput[nout] y annotation(Placement(visible = true, transformation(origin = {151.657, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {60, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + parameter Real[:] value = {0} "Vector of constant rates given in the unit pertaining to OutputType [y.unit * s] per time base"; + parameter String timeBaseString = "second" "Time base of the rates entered (default = per second)" annotation(choices(choice = "second", choice = "minute", choice = "hour", choice = "day", choice = "week", choice = "month", choice = "quarter", choice = "year")); +protected + parameter Integer nout = size(value, 1) "Length of the vector" annotation(Evaluate = true, Dialog(tab = "Initialization", enable = false)); + parameter TimeBases timeBase = Functions.stringToTimeBase(timeBaseString) "Element of the enumeration TimeBases corresponding to the timeBase given as string" annotation(Dialog(tab = "Initialization", enable = false)); + RateConversion[nout] convertRate(each timeBaseA = timeBase, each timeBaseB = TimeBases.seconds) "Convert the rate input to a rate per seconds" annotation(Placement(visible = true, transformation(origin = {80, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + ConstantConverter ratesInTimeBase(value = value) annotation(Placement(visible = true, transformation(origin = {0, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(convertRate.y, y) annotation(Line(visible = true, origin = {119.829, 0}, points = {{-31.829, 0}, {31.829, -0}}, color = {1, 37, 163})); + connect(ratesInTimeBase.y, convertRate.u) annotation(Line(visible = true, origin = {39, 0}, points = {{-33, 0}, {33, 0}}, color = {1, 37, 163})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The parameter value (a vector) is used to set the continous output y making it a vector of constant-valued signals. The output will always give rates per second, but rates can be entered in non-SI-units of time using the parameter timeBaseString.

+

Notes

+ +

Examples

+

Given OutputType = Units.VolumeFlowRate, value = {1,2,3}, timeBase = \"minute\" will result in the output y = {0.0166 [m3/s], 0.0333 [m3/s], 0.05 [m3/s]}. +

See also

+

ConstantConverterConstantConverterTime

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, 60}, textColor = {0, 0, 128}, extent = {{-100, -6}, {100, 6}}, textString = "%value per %timeBaseString", fontName = "Lato")})); +end ConstantConverterRate; diff --git a/BusinessSimulation/Converters/Vector/ConstantConverterTime.mo b/BusinessSimulation/Converters/Vector/ConstantConverterTime.mo new file mode 100644 index 0000000..03686ab --- /dev/null +++ b/BusinessSimulation/Converters/Vector/ConstantConverterTime.mo @@ -0,0 +1,25 @@ +within BusinessSimulation.Converters.Vector; + +block ConstantConverterTime "A list of constant time values is turned into a vector of constant time signals" + import BusinessSimulation.Units.Time; + import BusinessSimulation.Types.TimeBases; + extends Icons.ConstantConverter; + extends Interfaces.Basics.OutputTypeChoice_Time(redeclare final type OutputType = Time); + RealMultiOutput[nout] y annotation(Placement(visible = true, transformation(origin = {151.87, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {60, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + parameter Real[:] value = {0} "List of constant time values"; + parameter String unitTime = "s" "Unit of time for the values entered (default = 's')" annotation(choices(choice = "s", choice = "m", choice = "h", choice = "d", choice = "wk", choice = "mo", choice = "qtr", choice = "yr")); +protected + parameter Integer nout = size(value, 1) "Length of vector" annotation(Evaluate = true, Dialog(tab = "Initialization", enable = false)); + parameter TimeBases timeBase = Functions.stringToTimeBase(unitTime) "Element of the enumeration TimeBases corresponding to the unit of time given as string" annotation(Dialog(tab = "Initialization", enable = false)); + ConstantConverter timesInUnitTime(value = value) annotation(Placement(visible = true, transformation(origin = {-0, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + TimeConversion[nout] convertTime(each timeBaseA = timeBase, each timeBaseB = TimeBases.seconds) "Convert the time input to seconds" annotation(Placement(visible = true, transformation(origin = {70, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(convertTime.y, y) annotation(Line(visible = true, origin = {114.935, 0}, points = {{-36.935, 0}, {36.935, -0}}, color = {1, 37, 163})); + connect(timesInUnitTime.y, convertTime.u) annotation(Line(visible = true, origin = {34, -0}, points = {{-28, -0}, {28, 0}}, color = {1, 37, 163})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The parameter value (a vector) is used to set the continous output y making it a vector of constant-valued signals. The output will always give times in seconds [s], but values can be entered in non-SI-units of time using the parameter unitTime.

+

See also

+

ConstantConverterConstantConverterRate

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, 60}, textColor = {0, 0, 128}, extent = {{-100, -6}, {100, 6}}, textString = "%value %unitTime", fontName = "Lato")})); +end ConstantConverterTime; diff --git a/BusinessSimulation/Converters/Vector/DotProduct.mo b/BusinessSimulation/Converters/Vector/DotProduct.mo new file mode 100644 index 0000000..e5acc4a --- /dev/null +++ b/BusinessSimulation/Converters/Vector/DotProduct.mo @@ -0,0 +1,20 @@ +within BusinessSimulation.Converters.Vector; + +block DotProduct "Dot product of two vectors of equal length" + extends Interfaces.PartialConverters.SO; + parameter Integer nin(min = 2) = 2 "Elements in the input vectors (length)" annotation(Dialog(group = "Structural Parameters")); + Interfaces.Connectors.RealMultiInput[nin] u1 "Input vector 1" annotation(Placement(visible = true, transformation(origin = {-145, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80.378, 50.378}, extent = {{-10.378, -10.378}, {10.378, 10.378}}, rotation = 0))); + Interfaces.Connectors.RealMultiInput[nin] u2 "Input vector 2" annotation(Placement(visible = true, transformation(origin = {-145, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80.378, -50.378}, extent = {{-10.378, -10.378}, {10.378, 10.378}}, rotation = 0))); + Times times(nin = nin) annotation(Placement(visible = true, transformation(origin = {-27.609, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Total total(nin = nin) annotation(Placement(visible = true, transformation(origin = {27.609, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(u1, times.u1) annotation(Line(visible = true, origin = {-76.412, 22.519}, points = {{-68.588, 17.481}, {16.412, 17.481}, {16.412, -17.481}, {40.841, -17.557}}, color = {0, 0, 127})); + connect(u2, times.u2) annotation(Line(visible = true, origin = {-76.412, -22.519}, points = {{-68.588, -17.481}, {16.412, -17.481}, {16.412, 17.481}, {40.841, 17.481}}, color = {0, 0, 127})); + connect(times.y, total.u) annotation(Line(visible = true, origin = {-0.006, 0}, points = {{-20.24, 0}, {20.24, 0}}, color = {0, 0, 127})); + connect(y, total.y) annotation(Line(visible = true, origin = {97.486, 0}, points = {{62.514, 0}, {-62.514, 0}}, color = {0, 0, 127})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output y is the dot product of the input vectors u1 and u2 which have the same length nin.

+

The dot product is defined as follows:

+

\"y

"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {0, 0, 128}, extent = {{-40.484, -12}, {40.484, 12}}, textString = "Dot", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end DotProduct; diff --git a/BusinessSimulation/Converters/Vector/GeometricMean.mo b/BusinessSimulation/Converters/Vector/GeometricMean.mo new file mode 100644 index 0000000..8399841 --- /dev/null +++ b/BusinessSimulation/Converters/Vector/GeometricMean.mo @@ -0,0 +1,32 @@ +within BusinessSimulation.Converters.Vector; + +block GeometricMean "(Weighted) geometric mean" + extends Interfaces.PartialConverters.MISO; + parameter Real[nin] weights = ones(nin) "Weights to be used for inputs" annotation(Dialog(enable = useWeights and hasConstantWeights)); + parameter Boolean useWeights = false "= true, if the output is to be a weighted geometric mean" annotation(Dialog(group = "Structural Parameters")); + parameter Boolean hasConstantWeights = true "= true, if the weights are constant" annotation(Dialog(group = "Structural Parameters", enable = useWeights)); + Interfaces.Connectors.RealMultiInput u_weights[nin] if useWeights and not hasConstantWeights "Input of weights" annotation(Placement(visible = true, transformation(origin = {-145, 35}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {0, 80}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); +protected + Interfaces.Connectors.RealMultiInput[nin] constWeights = weights if not useWeights or hasConstantWeights; + Interfaces.Connectors.RealMultiOutput[nin] w; +equation + connect(constWeights, w); + connect(u_weights, w); + y = Functions.geometricMean(u, w); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The scalar output y is obtained as the geometric mean of the components of the input vector u. Optionally weights can be given, either as constants (weights) or as variable inputs (u_weights).

+

\"y

+

Notes

+
+ +

See also

+

+geometricMean, +ArithmeticMean

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {0, 0, 128}, extent = {{-40.484, -12}, {40.484, 12}}, textString = "MEAN", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {0, -20}, textColor = {128, 128, 128}, extent = {{-40.484, -9}, {40.484, 9}}, textString = "Geometric", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end GeometricMean; diff --git a/BusinessSimulation/Converters/Vector/Max.mo b/BusinessSimulation/Converters/Vector/Max.mo new file mode 100644 index 0000000..769fa65 --- /dev/null +++ b/BusinessSimulation/Converters/Vector/Max.mo @@ -0,0 +1,10 @@ +within BusinessSimulation.Converters.Vector; + +block Max "Max function for vectors" + extends Interfaces.PartialConverters.MISO; +equation + y = max(u); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The scalar output y is obtained as the maximum of all components in the input vector u.

", revisions = ""), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {0, 0, 128}, extent = {{-40.484, -12}, {40.484, 12}}, textString = "MAX", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Max; diff --git a/BusinessSimulation/Converters/Vector/Min.mo b/BusinessSimulation/Converters/Vector/Min.mo new file mode 100644 index 0000000..fa44c8f --- /dev/null +++ b/BusinessSimulation/Converters/Vector/Min.mo @@ -0,0 +1,10 @@ +within BusinessSimulation.Converters.Vector; + +block Min "Min function for vectors" + extends Interfaces.PartialConverters.MISO; +equation + y = min(u); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The scalar output y is obtained as the minimum of all components in the input vector u.

", revisions = ""), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {0, 0, 128}, extent = {{-40.484, -12}, {40.484, 12}}, textString = "MIN", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Min; diff --git a/BusinessSimulation/Converters/Vector/Product.mo b/BusinessSimulation/Converters/Vector/Product.mo new file mode 100644 index 0000000..9aae976 --- /dev/null +++ b/BusinessSimulation/Converters/Vector/Product.mo @@ -0,0 +1,14 @@ +within BusinessSimulation.Converters.Vector; + +block Product "Gives the product of all components of the input vector" + extends Interfaces.PartialConverters.MISO; +equation + y = product(u); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output y is derived as a multiplication of n inputs u given as an vector:

+

\"y_i

+

See also

+

Product_2Product_3

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {-2, 6}, textColor = {0, 0, 128}, extent = {{-22.881, -36.024}, {22.881, 36.024}}, textString = "∏", fontName = "Lato", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Product; diff --git a/BusinessSimulation/Converters/Vector/ProportionalSplitFactors.mo b/BusinessSimulation/Converters/Vector/ProportionalSplitFactors.mo new file mode 100644 index 0000000..507361e --- /dev/null +++ b/BusinessSimulation/Converters/Vector/ProportionalSplitFactors.mo @@ -0,0 +1,26 @@ +within BusinessSimulation.Converters.Vector; + +block ProportionalSplitFactors "Convert a vector of weights to a vector of fractions adding to one" + extends Interfaces.PartialConverters.MIMO_nin(redeclare replaceable type OutputType = Units.Fraction); + import BusinessSimulation.Constants.inf; + parameter Boolean shiftInputs = true "= true, if all values are to be shifted to prevent negative inputs, otherwise negative inputs are simply set to zero"; +protected + Real shift = if shiftInputs then min(0., min(u)) else 0. "The lowest negative weight or zero"; + Real u_adj[nin] = if shiftInputs then u .- shift else Functions.clip(u, {0., inf}) "All weights are shifted or clipped, so that no weight is below zero"; + Real totalWeight = sum(u_adj) "Sum over adjusted weights"; +equation + // assume uniform split if weights add up to zero + y = if totalWeight > 0 then u_adj / totalWeight else fill(1 / nin, nin); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Given a vector u of weights, the converter will give an output vector y of fractions so that:

+

\"y_i

+

If the weights do add up to zero equal proportions are assumed:

+

\"y_i

+

Notes

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {-0.699, 21}, textColor = {0, 0, 128}, extent = {{-20.133, -12}, {20.133, 12}}, textString = "u", fontName = "Lato", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {-13.119, -22}, textColor = {0, 0, 128}, extent = {{-22.881, -24}, {22.881, 24}}, textString = "∑", fontName = "Lato", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {8.009, 13}, textColor = {0, 0, 128}, extent = {{-6.991, -6}, {6.991, 6}}, textString = "i", fontName = "Lato", textStyle = {TextStyle.Bold}), Line(visible = true, rotation = -45, points = {{20, 20}, {-20, -20}}, color = {0, 0, 128}, thickness = 4), Text(visible = true, origin = {12.301, -27}, textColor = {0, 0, 128}, extent = {{-20.133, -12}, {20.133, 12}}, textString = "u", fontName = "Lato", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {21.009, -35}, textColor = {0, 0, 128}, extent = {{-6.991, -6}, {6.991, 6}}, textString = "i", fontName = "Lato", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end ProportionalSplitFactors; diff --git a/BusinessSimulation/Converters/Vector/Rescale.mo b/BusinessSimulation/Converters/Vector/Rescale.mo new file mode 100644 index 0000000..2116608 --- /dev/null +++ b/BusinessSimulation/Converters/Vector/Rescale.mo @@ -0,0 +1,20 @@ +within BusinessSimulation.Converters.Vector; + +block Rescale "Rescales the components of input vector u to run from y_min to y_max over the range u_min to u_max" + import BusinessSimulation.Constants.inf; + extends Interfaces.PartialConverters.MIMO_nin; + parameter Real u_min = -inf "Minimum value of the original range [u_min, u_max]" annotation(Dialog(enable = enterInputRange)); + parameter Real u_max = inf "Maximum value of the original range [u_min, u_max]" annotation(Dialog(enable = enterInputRange)); + parameter Real y_min = 0 "Minimum value of the transformed range [y_min, y_max]"; + parameter Real y_max = 1 "Maximum value of the transformed range [y_min, y_max]"; + parameter Boolean enterInputRange = false "= true, if instead of using {min(u),max(u)} the range {u_min, u_max} is to be explicitly given" annotation(Dialog(group = "Structural Parameters")); +equation + y = if enterInputRange then Functions.rescaleVector(u, {u_min, u_max}, {y_min, y_max}) else Functions.rescaleVector(u, {min(u), max(u)}, {y_min, y_max}); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The vector output y is obtained by rescaling all components of the input vector u to run from y_min to y_max over the range min to max.

+

Notes

+

Care has to be taken if enterInputRange = false, as then a vector of identical values will cause division by zero.

+

See also

+

RescaleFunctions.rescaleVector

", revisions = ""), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {0, 0, 128}, extent = {{-53.405, -12}, {53.405, 12}}, textString = "RESCALE", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Rescale; diff --git a/BusinessSimulation/Converters/Vector/ScalarMultiplication.mo b/BusinessSimulation/Converters/Vector/ScalarMultiplication.mo new file mode 100644 index 0000000..05ab6a4 --- /dev/null +++ b/BusinessSimulation/Converters/Vector/ScalarMultiplication.mo @@ -0,0 +1,17 @@ +within BusinessSimulation.Converters.Vector; + +block ScalarMultiplication "Multiplication of a vector with a scalar" + extends Interfaces.Basics.BaseConverter; + parameter Integer nin(min = 2) = 2 "Length of input vector" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + Interfaces.Connectors.RealMultiInput[nin] u1 "Input vector of length nin" annotation(Placement(visible = true, transformation(origin = {-145, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80.378, 49.622}, extent = {{-10.378, -10.378}, {10.378, 10.378}}, rotation = 0))); + Interfaces.Connectors.RealInput u2 "Input of scalar value" annotation(Placement(visible = true, transformation(origin = {-145, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80.378, -49.622}, extent = {{-10.378, -10.378}, {10.378, 10.378}}, rotation = 0))); + RealMultiOutput y[nin] "Output vector" annotation(Placement(visible = true, transformation(origin = {150, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {75, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + y = u1 * u2; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output vector y is obtained by multiplying the input vector u1 with the scalar input u2:

+

\"y_i

+

The vectors y and u1 will have the same length nin.

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, points = {{15, 15}, {-15, -15}}, color = {0, 0, 128}, thickness = 4, arrowSize = 0), Line(visible = true, rotation = -270, points = {{15, 15}, {-15, -15}}, color = {0, 0, 128}, thickness = 4, arrowSize = 0)}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end ScalarMultiplication; diff --git a/BusinessSimulation/Converters/Vector/Sum.mo b/BusinessSimulation/Converters/Vector/Sum.mo new file mode 100644 index 0000000..4cc4498 --- /dev/null +++ b/BusinessSimulation/Converters/Vector/Sum.mo @@ -0,0 +1,16 @@ +within BusinessSimulation.Converters.Vector; + +block Sum "Add two vectors of equal length" + extends Interfaces.Basics.BaseConverter; + Interfaces.Connectors.RealMultiInput u1[nin] "Input vector 1" annotation(Placement(visible = true, transformation(origin = {-145, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, -50}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealMultiInput u2[nin] "Input vector 2" annotation(Placement(visible = true, transformation(origin = {-145, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, 50}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + RealMultiOutput y[nin] "Output with same dimension as inputs" annotation(Placement(visible = true, transformation(origin = {153.198, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {74.167, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + parameter Integer nin(min = 2) = 2 "Length of input and output vectors" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); +equation + y = u1 + u2; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output vector y is the sum of the input vectors u1 and u2, which need to have length nin:

+

\"y_i

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, rotation = -225, points = {{15, 15}, {-15, -15}}, color = {0, 0, 128}, thickness = 4, arrowSize = 0), Line(visible = true, rotation = -315, points = {{15, 15}, {-15, -15}}, color = {0, 0, 128}, thickness = 4, arrowSize = 0)}), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Sum; diff --git a/BusinessSimulation/Converters/Vector/Times.mo b/BusinessSimulation/Converters/Vector/Times.mo new file mode 100644 index 0000000..265705d --- /dev/null +++ b/BusinessSimulation/Converters/Vector/Times.mo @@ -0,0 +1,16 @@ +within BusinessSimulation.Converters.Vector; + +block Times "Elementwise multiplication of two vectors of the same length" + extends Interfaces.Basics.BaseConverter; + Interfaces.Connectors.RealMultiInput[nin] u1 "Input vector 1" annotation(Placement(visible = true, transformation(origin = {-145, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-79.622, 49.622}, extent = {{-10.378, -10.378}, {10.378, 10.378}}, rotation = 0))); + Interfaces.Connectors.RealMultiInput[nin] u2 "Input vector 2" annotation(Placement(visible = true, transformation(origin = {-145, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-79.622, -50.378}, extent = {{-10.378, -10.378}, {10.378, 10.378}}, rotation = 0))); + RealMultiOutput[nin] y "Output vector of the same length as inputs" annotation(Placement(visible = true, transformation(origin = {150, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {75, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + parameter Integer nin(min = 2) = 2 "Length of input and output vectors" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); +equation + y = u1 .* u2; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output vector y is obtained by elementwise multiplication of the input vectors u1 and u2, which need to have the same length nin:

+

\"y_i

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, points = {{15, 15}, {-15, -15}}, color = {0, 0, 128}, thickness = 4, arrowSize = 0), Line(visible = true, rotation = -270, points = {{15, 15}, {-15, -15}}, color = {0, 0, 128}, thickness = 4, arrowSize = 0)}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Times; diff --git a/BusinessSimulation/Converters/Vector/Total.mo b/BusinessSimulation/Converters/Vector/Total.mo new file mode 100644 index 0000000..7c546a6 --- /dev/null +++ b/BusinessSimulation/Converters/Vector/Total.mo @@ -0,0 +1,12 @@ +within BusinessSimulation.Converters.Vector; + +block Total "Gives the sum over all components of a vector" + extends Interfaces.PartialConverters.MISO; +equation + y = sum(u); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The scalar output y is obtained by adding all components of the input vector u:

+

\"y_i

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {-2, 6}, textColor = {0, 0, 128}, extent = {{-22.881, -36.024}, {22.881, 36.024}}, textString = "∑", fontName = "Lato", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Total; diff --git a/BusinessSimulation/Converters/Vector/package.mo b/BusinessSimulation/Converters/Vector/package.mo new file mode 100644 index 0000000..ff0c7ef --- /dev/null +++ b/BusinessSimulation/Converters/Vector/package.mo @@ -0,0 +1,14 @@ +within BusinessSimulation.Converters; + +package Vector "Converters with vector input and/or vector output" + extends Icons.Package; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This package ontains converters where either input or output or both can be vectors of a given dimension.

+

Technical Notes

+

There is currently no support in Wolfram SystemModeler for flexible array sizes (\":\") for connectors used with blocks. Therefore the actual size of array inputs has to be given as a parameter upon instantiating a converter in a model.

+
+
+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Ellipse(visible = true, lineColor = {255, 255, 255}, lineThickness = 8, extent = {{-30, -30}, {30, 30}}), Polygon(visible = true, origin = {-48.263, 0}, rotation = -1440, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-10, 10}, {10, 0}, {-10, -10}, {-10, 10}}), Ellipse(visible = true, origin = {-51.403, 0}, lineColor = {255, 255, 255}, fillColor = {113, 166, 201}, fillPattern = FillPattern.Solid, extent = {{-3.32, -3.32}, {3.32, 3.32}}), Polygon(visible = true, origin = {50, 0}, rotation = -1080, lineColor = {76, 112, 136}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-10, 10}, {10, 0}, {-10, -10}, {-10, 10}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Vector; diff --git a/BusinessSimulation/Converters/Vector/package.order b/BusinessSimulation/Converters/Vector/package.order new file mode 100644 index 0000000..0f2a696 --- /dev/null +++ b/BusinessSimulation/Converters/Vector/package.order @@ -0,0 +1,17 @@ +ArithmeticMean +Clip +ComplementFractions +ConstantConverter +ConstantConverterRate +ConstantConverterTime +DotProduct +GeometricMean +Max +Min +Product +ProportionalSplitFactors +Rescale +ScalarMultiplication +Sum +Times +Total diff --git a/BusinessSimulation/Converters/ZeroIfNegative.mo b/BusinessSimulation/Converters/ZeroIfNegative.mo new file mode 100644 index 0000000..746dff1 --- /dev/null +++ b/BusinessSimulation/Converters/ZeroIfNegative.mo @@ -0,0 +1,25 @@ +within BusinessSimulation.Converters; + +block ZeroIfNegative "The input will be set to zero, if it is negative" + extends Interfaces.PartialConverters.SISO; + parameter Boolean strict = true "= true, if strict limits with noEvent(..)" annotation(Evaluate = true, Dialog(tab = "Advanced")); +equation + if strict then + y = smooth(0, noEvent(if u < 0 then 0 else u)); + else + y = smooth(0, if u < 0 then 0 else u); + end if; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output y will be identical with the input u whenever u is greater than or equal to zero. It will be zero in all other cases.

+

Implementation

+

In the default setting (strict = false) in the Advanced tab, nonnegativity will be strictly ovserved:

+
  if strict then
+    y = smooth(0, noEvent(if u < 0 then 0 else u));
+  else
+    y = smooth(0, if u < 0 then 0 else u);
+  end if;

+

See also

+

ClipClipProcessTime

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0.484, 0}, textColor = {0, 0, 128}, extent = {{-40.484, -12}, {40.484, 12}}, textString = "0 if < 0", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end ZeroIfNegative; diff --git a/BusinessSimulation/Converters/package.mo b/BusinessSimulation/Converters/package.mo new file mode 100644 index 0000000..87c34c9 --- /dev/null +++ b/BusinessSimulation/Converters/package.mo @@ -0,0 +1,15 @@ +within BusinessSimulation; + +package Converters "Information processing (blocks)" + extends Icons.Package; + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Ellipse(visible = true, lineColor = {255, 255, 255}, lineThickness = 8, extent = {{-30, -30}, {30, 30}}), Polygon(visible = true, origin = {50, 0}, rotation = -1080, lineColor = {76, 112, 136}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-10, 10}, {10, 0}, {-10, -10}, {-10, 10}}), Polygon(visible = true, origin = {-45.805, 21}, rotation = -1080, lineColor = {76, 112, 136}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-10, 10}, {10, 0}, {-10, -10}, {-10, 10}}), Polygon(visible = true, origin = {-45.805, -21}, rotation = -1080, lineColor = {76, 112, 136}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-10, 10}, {10, 0}, {-10, -10}, {-10, 10}})}), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This library contains input/output blocks (converters): One or more information inputs are (instantaneously) transformed by some function given one or more outputs.

+

See also

+

+Tutorial.ElementaryBuildingBlocks +

+

+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+"), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Converters; diff --git a/BusinessSimulation/Converters/package.order b/BusinessSimulation/Converters/package.order new file mode 100644 index 0000000..e9c1d44 --- /dev/null +++ b/BusinessSimulation/Converters/package.order @@ -0,0 +1,33 @@ +DiscreteDelay +Logical +Lookup +Vector +Special +Abs +AccumulationFunction +Add_2 +Add_3 +Clip +ClipProcessTime +ConstantConverter +ConstantConverterRate +ConstantConverterTime +Division +Division_Guarded +DmnlInput +Exp +Gain +Gap +Log +Max +Min +PassThrough +PolynomialFunction +Power +Product_2 +Product_3 +ForceOfInterest +RateConversion +Rescale +TimeConversion +ZeroIfNegative diff --git a/BusinessSimulation/Examples/AssemblyLine.mo b/BusinessSimulation/Examples/AssemblyLine.mo new file mode 100644 index 0000000..43a3335 --- /dev/null +++ b/BusinessSimulation/Examples/AssemblyLine.mo @@ -0,0 +1,56 @@ +within BusinessSimulation.Examples; + +model AssemblyLine "Modeling of a production process" + extends Icons.Example; + inner ModelSettings modelSettings(modelTimeHorizon = 25) annotation(Placement(visible = true, transformation(origin = {-125, -75}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + ModelOutput modelOutput "Main Output of the Model" annotation(Placement(visible = true, transformation(origin = {130, -60}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {90, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + + expandable connector ModelOutput "Main output" + extends Icons.DataOutPort; + import BusinessSimulation.Units.Material; + Material incomingStore "Inventory for raw material"; + Material machine1 "Material in first batch production"; + Material movingOn "Material on conveyor belt"; + Material intermediateStore "Material in buffer stock"; + Material machine2 "Material in second batch production"; + Material outgoingInventory "Finished goods inventory"; + end ModelOutput; +protected + SourcesOrSinks.Growth beingReleased(rate = 2, hasConstantRate = true) "Material flowing into the assembly line" annotation(Placement(visible = true, transformation(origin = {-80, 30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Stocks.MaterialStock incomingStore(initialValue = 7, redeclare replaceable type OutputType = Units.Material) "Buffer stock for incoming material" annotation(Placement(visible = true, transformation(origin = {-40, 30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Stocks.Oven machine1(hasConstantBatchSize = true, hasConstantProcessingTime = true, batchSize = 4, processingTime = 1, unloadingTime = 1, redeclare replaceable type OutputType = Units.Material) "First processing unit" annotation(Placement(visible = true, transformation(origin = {40, 30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Flows.Unidirectional.Transition loading1(hasConstantRate = true, rate = 2) "Loading the processing unit" annotation(Placement(visible = true, transformation(origin = {0, 30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Flows.Unidirectional.OutflowDynamicStock enteringBelt "Outflow from machine 1" annotation(Placement(visible = true, transformation(origin = {80, 30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Stocks.MaterialStock intermediateStore(initialValue = 0, redeclare replaceable type OutputType = Units.Material) "Buffer stock for material" annotation(Placement(visible = true, transformation(origin = {40, -30}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Flows.Unidirectional.OutflowDynamicStock leavingBelt "Entering the intermediate store" annotation(Placement(visible = true, transformation(origin = {80, -30}, extent = {{10, -10}, {-10, 10}}, rotation = -360))); + Stocks.Oven machine2(hasConstantBatchSize = true, hasConstantProcessingTime = true, batchSize = 2, processingTime = 0.5, unloadingTime = 0.5, redeclare replaceable type OutputType = Units.Material) "First processing unit" annotation(Placement(visible = true, transformation(origin = {-40, -30}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Flows.Unidirectional.Transition loading2(hasConstantRate = true, rate = 2) "Loading the processing unit" annotation(Placement(visible = true, transformation(origin = {0, -30}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Flows.Unidirectional.OutflowDynamicStock unloading2 "Outflow from machine 1" annotation(Placement(visible = true, transformation(origin = {-80, -30}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Stocks.MaterialStock outgoingInventory(initialValue = 0, redeclare replaceable type OutputType = Units.Material) "Finished goods for shipment" annotation(Placement(visible = true, transformation(origin = {-120, -30}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Stocks.SimpleConveyor movingOn(initialValue = 0, delayTime = 2, redeclare replaceable type OutputType = Units.Material) "Conveyor belt transport" annotation(Placement(visible = true, transformation(origin = {110, 0}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); +equation + connect(beingReleased.massPort, incomingStore.inflow) annotation(Line(visible = true, origin = {-60, 30}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(incomingStore.outflow, loading1.portA) annotation(Line(visible = true, origin = {-20, 30}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(loading1.portB, machine1.inflow) annotation(Line(visible = true, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128}, origin = {20, 30})); + connect(machine1.outflow, enteringBelt.portA) annotation(Line(visible = true, origin = {60, 30}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(leavingBelt.portB, intermediateStore.inflow) annotation(Line(visible = true, origin = {60, -30}, points = {{10, 0}, {-10, 0}}, color = {128, 0, 128})); + connect(intermediateStore.outflow, loading2.portA) annotation(Line(visible = true, points = {{10, 0}, {-10, 0}}, color = {128, 0, 128}, origin = {20, -30})); + connect(loading2.portB, machine2.inflow) annotation(Line(visible = true, points = {{10, 0}, {-10, 0}}, color = {128, 0, 128}, origin = {-20, -30})); + connect(unloading2.portB, outgoingInventory.inflow) annotation(Line(visible = true, origin = {-100, -30}, points = {{10, 0}, {-10, 0}}, color = {128, 0, 128})); + connect(machine2.outflow, unloading2.portA) annotation(Line(visible = true, origin = {-60, -30}, points = {{10, 0}, {-10, 0}}, color = {128, 0, 128})); + connect(enteringBelt.portB, movingOn.inflow) annotation(Line(visible = true, origin = {103.333, 23.333}, points = {{-13.333, 6.667}, {6.667, 6.667}, {6.667, -13.333}}, color = {128, 0, 128})); + connect(movingOn.outflow, leavingBelt.portA) annotation(Line(visible = true, origin = {103.333, -23.333}, points = {{6.667, 13.333}, {6.667, -6.667}, {-13.333, -6.667}}, color = {128, 0, 128})); + connect(incomingStore.y1, modelOutput.incomingStore) annotation(Line(visible = true, origin = {12.625, -17.5}, points = {{-42.125, 42.5}, {-37.625, 42.5}, {-37.625, -42.5}, {117.375, -42.5}}, color = {192, 192, 192})); + connect(movingOn.y1, modelOutput.movingOn) annotation(Line(visible = true, origin = {113.333, -43.5}, points = {{-8.333, 33}, {-8.333, -16.5}, {16.667, -16.5}}, color = {192, 192, 192})); + connect(intermediateStore.y2, modelOutput.intermediateStore) annotation(Line(visible = true, origin = {74.749, -47.5}, points = {{-24.249, 12.5}, {-19.749, 12.5}, {-19.749, -12.5}, {55.251, -12.5}}, color = {192, 192, 192})); + connect(outgoingInventory.y2, modelOutput.outgoingInventory) annotation(Line(visible = true, origin = {-47.375, -47.5}, points = {{-62.125, 12.5}, {-57.625, 12.5}, {-57.625, -12.5}, {177.375, -12.5}}, color = {192, 192, 192})); + connect(machine1.y1, modelOutput.machine1); + connect(machine2.y1, modelOutput.machine2); + annotation(__Wolfram(PlotSet(plots = {Plot(name = "Inventories", identifier = "inventories", preferred = true, caption = "Incoming and outgoing inventories", subPlots = {SubPlot(curves = {Curve(x = time, y = modelOutput.incomingStore), Curve(x = time, y = modelOutput.outgoingInventory)})})})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}), graphics = {Text(visible = true, origin = {0, 75}, textColor = {76, 112, 136}, extent = {{-140, -6}, {140, 6}}, textString = "Assembly Line", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), experiment(StartTime = 0, StopTime = 25), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Usually in System Dynamics modeling we take the \"high road\" of a macro-level, strategic view on business systems and accordingly we will very often be content with modeling a production line using a →DelayN where production time is distributed around some mean duration. In this example we take a meso-level perspective of modeling a simple assembly line that borders on discrete-event modeling—albeit not yet focussing single entities.

+

In modeling an assembly line we here use SimpleConveyor and Oven being dynamical stocks with inherent (hidden) dynamics: The SimpleConveyor is like a conveyor belt, that transports stuff from one stock to another using a fixed, exact amount of time. The Oven represents an idealized batch process, where a processor is loaded, then closes its doors to process the loaded material in a fixed amount of time, to then unload it into the next stage.

+

Acknowledgments

+

The example is taken from Peter Junglas [18, pp. 247-252].

+")); +end AssemblyLine; diff --git a/BusinessSimulation/Examples/LookupFunctions.mo b/BusinessSimulation/Examples/LookupFunctions.mo new file mode 100644 index 0000000..cd94d0d --- /dev/null +++ b/BusinessSimulation/Examples/LookupFunctions.mo @@ -0,0 +1,62 @@ +within BusinessSimulation.Examples; + +model LookupFunctions "Demonstration of lookup-functions" + extends Icons.Example; + ModelOutput modelOutput "The main model output" annotation(Placement(visible = true, transformation(origin = {120, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {80.808, -6.712}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + parameter Real slope1To50(min = 1, max = 50) = 2 "Slope parameter (general)"; + parameter Real slope(min = 0) = slope1To50 "Determines the gradient of the curve (Janoschek and S-Shaped)"; + parameter Real slopeUpTo1(min = 0, max = 1) = 0.5 "Slope parameter (0< slope <= 1) (concaveLookupPosisitve)"; + parameter Real interceptUpward(min = 0, max = 1) = 0. "Value of y when input is zero or less (y0) for upward sloping functions"; + parameter Real interceptDownward(min = 1) = 2. "Value of y when input is zero or less (y0) for downward sloping functions"; + parameter Real upperBound = 2 "Upper asymptote for u <= 0 (upperBound > lowerBound) (Janoschek and S-Shaped)"; + parameter Real lowerBound = 0 "Lower asymptote for u -> infinity (Janoschek)"; + parameter Real x_ref(min = 0) = 1 "x-value for point of inflection(>0) (Janoschek)"; + parameter Real y_ref = 1 "y-value for point of inflection(lowerBound < y_ref < upperBound) (Janoschek)"; + parameter Real table[:, :] = {{0, 0}, {2, 4}, {4, 6}, {6, 8}} "Table matrix (grid = first column; e.g., table=[0,2]) (combiTable1D.table) (tableFunction.table)"; + parameter Modelica.Blocks.Types.Smoothness smoothness = Modelica.Blocks.Types.Smoothness.LinearSegments "Smoothness of table interpolation (tableFunction.smoothness)"; + parameter Modelica.Blocks.Types.Extrapolation extrapolation = Modelica.Blocks.Types.Extrapolation.HoldLastPoint "Extrapolation of data outside the definition range (combiTable.extrapolation) (tableFunction.extrapolation)"; + inner ModelSettings modelSettings(modelTimeHorizon = 10) annotation(Placement(visible = true, transformation(origin = {-110, -75}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + InformationSources.RampInput '0..10'(height = 10, duration = 10, offset = 0, startTime = 0) "Ramp from 0 to 10 in 10 units of time" annotation(Placement(visible = true, transformation(origin = {-110, 10}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + InformationSources.RampInput '-5..5'(offset = -5, height = 10, duration = 10) "Ramp from -5 to 5 in 10 units of time" annotation(Placement(visible = true, transformation(origin = {10, 10}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + + expandable connector ModelOutput "Main Output" + extends Icons.DataOutPort; + end ModelOutput; +protected + Converters.Lookup.ConcaveLookupNegative concaveLookupNegative(s = slope1To50, y0 = interceptDownward) annotation(Placement(visible = true, transformation(origin = {-50, 80}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Lookup.ConcaveLookupPositive concaveLookupPositive(s = slopeUpTo1, y0 = interceptUpward) annotation(Placement(visible = true, transformation(origin = {-50, 55}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Lookup.ConvexLookupNegative convexLookupNegative(y0 = interceptDownward) annotation(Placement(visible = true, transformation(origin = {-50, 25}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Lookup.ConvexLookupPositive convexLookupPositive(s = slope1To50, y0 = interceptUpward) annotation(Placement(visible = true, transformation(origin = {-50, -5}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Lookup.JanoschekNegative janoschek_negative_x_y(growthRate = slope, x_ref = x_ref, y_ref = y_ref, lowerBound = lowerBound, upperBound = upperBound) annotation(Placement(visible = true, transformation(origin = {-50, -35}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Lookup.JanoschekPositive janoschek_positive_x_y(lowerBound = lowerBound, upperBound = upperBound, growthRate = slope, x_ref = x_ref, y_ref = y_ref) annotation(Placement(visible = true, transformation(origin = {-50, -65}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Lookup.SShapedNegative sShapedNegative_origin(s = slope, upperBound = upperBound) annotation(Placement(visible = true, transformation(origin = {70, 30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Lookup.SShapedPositive sShapedPositive_origin(s = slope, upperBound = upperBound) annotation(Placement(visible = true, transformation(origin = {70, -10}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Lookup.TableFunction tableFunction(table = table, tableOnFile = false, extrapolation = extrapolation, smoothness = smoothness) annotation(Placement(visible = true, transformation(origin = {-50, -90}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect('0..10'.y, concaveLookupPositive.u) annotation(Line(visible = true, origin = {-71.503, 32.5}, points = {{-30.497, -22.5}, {-8.497, -22.5}, {-8.497, 22.5}, {13.503, 22.5}}, color = {0, 0, 127})); + connect('0..10'.y, convexLookupNegative.u) annotation(Line(visible = true, origin = {-71.503, 17.5}, points = {{-30.497, -7.5}, {-8.497, -7.5}, {-8.497, 7.5}, {13.503, 7.5}}, color = {0, 0, 127})); + connect('0..10'.y, janoschek_positive_x_y.u) annotation(Line(visible = true, origin = {-71.503, -27.5}, points = {{-30.497, 37.5}, {-8.497, 37.5}, {-8.497, -37.5}, {13.503, -37.5}}, color = {0, 0, 127})); + connect('0..10'.y, convexLookupPositive.u) annotation(Line(visible = true, origin = {-71.503, 2.5}, points = {{-30.497, 7.5}, {-8.497, 7.5}, {-8.497, -7.5}, {13.503, -7.5}}, color = {0, 0, 127})); + connect('0..10'.y, janoschek_negative_x_y.u) annotation(Line(visible = true, origin = {-71.503, -12.5}, points = {{-30.497, 22.5}, {-8.497, 22.5}, {-8.497, -22.5}, {13.503, -22.5}}, color = {0, 0, 127})); + connect('-5..5'.y, sShapedNegative_origin.u) annotation(Line(visible = true, origin = {29.997, 20}, points = {{-11.997, -10}, {10.003, -10}, {10.003, 10}, {32.003, 10}}, color = {0, 0, 127})); + connect('-5..5'.y, sShapedPositive_origin.u) annotation(Line(visible = true, origin = {39.997, 0}, points = {{-21.997, 10}, {0.003, 10}, {0.003, -10}, {22.003, -10}}, color = {0, 0, 127})); + connect('0..10'.y, tableFunction.u) annotation(Line(visible = true, origin = {-87.117, -40}, points = {{-14.883, 50}, {7.117, 50}, {7.117, -50}, {29.117, -50}}, color = {1, 37, 163})); + connect('0..10'.y, concaveLookupNegative.u) annotation(Line(visible = true, origin = {-80, 45}, points = {{-22, -35}, {0, -35}, {0, 35}, {22, 35}}, color = {1, 37, 163})); + connect(concaveLookupNegative.y, modelOutput.concaveLookupNegative) annotation(Line(visible = true, origin = {9.5, 20}, points = {{-51.5, 60}, {-29.5, 60}, {-29.5, -60}, {110.5, -60}}, color = {192, 192, 192})); + connect(concaveLookupPositive.y, modelOutput.concaveLookupPositive) annotation(Line(visible = true, origin = {9.5, 7.5}, points = {{-51.5, 47.5}, {-29.5, 47.5}, {-29.5, -47.5}, {110.5, -47.5}}, color = {192, 192, 192})); + connect(convexLookupNegative.y, modelOutput.convexLookupNegative) annotation(Line(visible = true, origin = {9.5, -7.5}, points = {{-51.5, 32.5}, {-29.5, 32.5}, {-29.5, -32.5}, {110.5, -32.5}}, color = {192, 192, 192})); + connect(convexLookupPositive.y, modelOutput.convexLookupPositive) annotation(Line(visible = true, origin = {9.5, -22.5}, points = {{-51.5, 17.5}, {-29.5, 17.5}, {-29.5, -17.5}, {110.5, -17.5}}, color = {192, 192, 192})); + connect(janoschek_negative_x_y.y, modelOutput.janoschekNegative) annotation(Line(visible = true, origin = {9.5, -37.5}, points = {{-51.5, 2.5}, {-29.5, 2.5}, {-29.5, -2.5}, {110.5, -2.5}}, color = {192, 192, 192})); + connect(janoschek_positive_x_y.y, modelOutput.janoschekPositive) annotation(Line(visible = true, origin = {9.919, -52.5}, points = {{-51.919, -12.5}, {-29.919, -12.5}, {-29.919, 12.5}, {110.081, 12.5}}, color = {192, 192, 192})); + connect(tableFunction.y, modelOutput.tableFunction) annotation(Line(visible = true, origin = {9.5, -65}, points = {{-51.5, -25}, {-29.5, -25}, {-29.5, 25}, {110.5, 25}}, color = {192, 192, 192})); + connect(sShapedNegative_origin.y, modelOutput.sShapedNegative) annotation(Line(visible = true, origin = {99.5, -5}, points = {{-21.5, 35}, {0.5, 35}, {0.5, -35}, {20.5, -35}}, color = {192, 192, 192})); + connect(sShapedPositive_origin.y, modelOutput.sShapedPositive) annotation(Line(visible = true, origin = {99.5, -25}, points = {{-21.5, 15}, {0.5, 15}, {0.5, -15}, {20.5, -15}}, color = {192, 192, 192})); + annotation(__Wolfram(PlotSet(plots = {Plot(name = "Concave Lookup", identifier = "concave", caption = "Concave lookup with positive and negative slopes.", subPlots = {SubPlot(title = "Negative", identifier = "neg", curves = {Curve(x = time, y = modelOutput.concaveLookupNegative)}), SubPlot(title = "Positive", identifier = "pos", curves = {Curve(x = time, y = modelOutput.concaveLookupPositive)})}), Plot(name = "Convex Lookup", identifier = "convex", caption = "Convex lookups with positive and negative slopes.", subPlots = {SubPlot(title = "Negative", identifier = "neg", curves = {Curve(x = time, y = modelOutput.convexLookupNegative)}), SubPlot(curves = {Curve(x = time, y = modelOutput.convexLookupPositive)})}), Plot(name = "Table Function", identifier = "table", caption = "Classical table function lookup.", subPlots = {SubPlot(curves = {Curve(x = time, y = modelOutput.tableFunction)})}), Plot(name = "Janosckek's Growth Function", identifier = "janoschek", caption = "Janoschek's growth function with positive and negative slopes.", subPlots = {SubPlot(title = "Positive", identifier = "pos", curves = {Curve(x = time, y = modelOutput.janoschekPositive)}), SubPlot(title = "Negative", identifier = "neg", curves = {Curve(x = time, y = modelOutput.janoschekNegative)})}), Plot(name = "S-shaped Lookup", identifier = "sshaped", caption = "S-shaped Lookup with positive and negative slope", subPlots = {SubPlot(title = "Positive", identifier = "pos", curves = {Curve(x = '-5..5'.y, y = modelOutput.sShapedPositive)}), SubPlot(title = "Negative", identifier = "neg", curves = {Curve(x = '-5..5'.y, y = modelOutput.sShapedNegative)})})})), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This example demonstrates the use of parametric and table functions in models and may serve as a little \"sandbox\". While table functions are still frequently used, the advantage of parametric functions is their smoothness—at least in the relevant range—and the better calibration/identification options.

+

See also

+

+Converters.Lookup +

+"), experiment(StartTime = 0, StopTime = 10, NumberOfIntervals = 10000, __Wolfram_Algorithm = "dassl", __Wolfram_SynchronizeWithRealTime = false), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}), graphics = {Text(visible = true, origin = {60, 80}, textColor = {76, 112, 136}, extent = {{-50, -6}, {50, 6}}, textString = "Lookup Converters", fontName = "Lato Black", textStyle = {TextStyle.Bold}, horizontalAlignment = TextAlignment.Left), Text(visible = true, origin = {60, 70}, textColor = {128, 128, 128}, extent = {{-50, -3}, {50, 3}}, textString = "Parametric- or Interpolating-Functions", fontName = "Lato", textStyle = {TextStyle.Bold}, horizontalAlignment = TextAlignment.Left)})); +end LookupFunctions; diff --git a/BusinessSimulation/Examples/LotkaVolterraEquationsRevisited.mo b/BusinessSimulation/Examples/LotkaVolterraEquationsRevisited.mo new file mode 100644 index 0000000..86ffe67 --- /dev/null +++ b/BusinessSimulation/Examples/LotkaVolterraEquationsRevisited.mo @@ -0,0 +1,86 @@ +within BusinessSimulation.Examples; + +model LotkaVolterraEquationsRevisited "Predator-prey dynamics with an additional predator" + import BusinessSimulation.Units.Rate; + extends Icons.Example; + ModelOutput modelOutput "Main output for the model" annotation(Placement(visible = true, transformation(origin = {130, -60}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {90, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + inner ModelSettings modelSettings(init = BusinessSimulation.Types.InitializationOptions.FixedValue, modelTimeHorizon(displayUnit = "yr") = 4415040000, dt(displayUnit = "yr") = 7884000) annotation(Placement(visible = true, transformation(origin = {-130, -90}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Theta theta(foxRabbit_beta(displayUnit = "1/yr")) annotation(Placement(visible = true, transformation(origin = {-110, -90}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + + expandable connector ModelOutput "Main output of the model" + import BusinessSimulation.Units.{Population}; + extends Icons.DataOutPort; + Population wolves(unit = "wolves") "Wolf population"; + Population foxes(unit = "foxes") "Fox population"; + Population rabbits(unit = "rabbits") "Rabbit population"; + end ModelOutput; + + model Theta "Parameter definitions for the Base Case" + import BusinessSimulation.Units.{Population,Rate}; + extends Icons.Theta; + // initial values for populations + parameter Population IRA(unit = "rabbits") = 25 "Initial rabbit population"; + parameter Population IFO(unit = "foxes") = 2 "Initial fox population"; + parameter Population IWO(unit = "wolves") = 4 "Initial wolf population"; + // rates + parameter Rate foxRabbit_beta(displayUnit = "1/yr") = 6.34195839675292e-10 "Rabbit fractional death rate per fox"; + parameter Rate foxRabbit_delta(displayUnit = "1/yr") = 6.34195839675292e-10 "Fox fractional reproduction rate per rabbit"; + parameter Rate foxesDeathRate(displayUnit = "1/yr") = 1.26839167935058e-08 "Fractional death rate for fox popultion"; + parameter Rate rabbitsReproRate(displayUnit = "1/yr") = 3.17097919837646e-09 "Fractional reproduction rate for rabbit population"; + parameter Rate wolfRabbit_beta(displayUnit = "1/yr") = 6.34195839675292e-10 "Rabbit fractional death rate per wolf"; + parameter Rate wolfRabbit_delta(displayUnit = "1/yr") = 3.17097919837646e-10 "Wolf fractional reproduction rate per rabbit"; + parameter Rate wolvesDeathRate(displayUnit = "1/yr") = 1.26839167935058e-08 "Fractopmaö death rate for wolf population"; + parameter Rate wolfFox_beta(displayUnit = "1/yr") = 1.26839167935058e-09 "Fox fractional death rate per wolf"; + parameter Rate wolfFox_delta(displayUnit = "1/yr") = 2.53678335870117e-09 "Wolf fractional reproduction rate per fox"; + end Theta; +protected + Stocks.MaterialStock rabbits(initialValue = theta.IRA) "Population of rabbits" annotation(Placement(visible = true, transformation(origin = {-70, -30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Stocks.MaterialStock foxes(initialValue = theta.IFO) "Population of foxes" annotation(Placement(visible = true, transformation(origin = {10, -30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Stocks.MaterialStock wolves(initialValue = theta.IWO) "Population of wolves" annotation(Placement(visible = true, transformation(origin = {60, 30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + SourcesOrSinks.ExponentialGrowth reproduction(fractionalRate = theta.rabbitsReproRate, hasConstantRate = true) annotation(Placement(visible = true, transformation(origin = {-110, -30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + SourcesOrSinks.ExponentialDecline foxesStarving(hasConstantRate = true, fractionalRate = theta.foxesDeathRate) "Mortality for foxes" annotation(Placement(visible = true, transformation(origin = {51.709, -30}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Flows.Interaction.NonlinearInteraction fox_rabbit_predation(hasConstantFactorA = true, hasConstantFactorB = true, a_AB = -theta.foxRabbit_beta, b_AB = theta.foxRabbit_delta) "Foxes predating on rabbits" annotation(Placement(visible = true, transformation(origin = {-30, -30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Flows.Interaction.NonlinearInteraction wolf_rabbit_predation(hasConstantFactorA = true, hasConstantFactorB = true, a_AB = -theta.wolfRabbit_beta, b_AB = theta.wolfRabbit_delta) "Wolves predating on rabbits" annotation(Placement(visible = true, transformation(origin = {-50, 5}, extent = {{-10, -10}, {10, 10}}, rotation = -270))); + Flows.Interaction.NonlinearInteraction wolf_fox_predation(hasConstantFactorA = true, hasConstantFactorB = true, a_AB = -theta.wolfFox_beta, b_AB = theta.wolfFox_delta) "Wolves predating on foxes" annotation(Placement(visible = true, transformation(origin = {30, 5}, extent = {{-10, -10}, {10, 10}}, rotation = -270))); + SourcesOrSinks.ExponentialDecline wolvesStarving(hasConstantRate = true, fractionalRate = theta.wolvesDeathRate) "Mortality for foxes" annotation(Placement(visible = true, transformation(origin = {100, 30}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); +equation + connect(reproduction.massPort, rabbits.inflow) annotation(Line(visible = true, origin = {-90, -30}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(rabbits.outflow, fox_rabbit_predation.portA) annotation(Line(visible = true, origin = {-50, -30}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(fox_rabbit_predation.portB, foxes.inflow) annotation(Line(visible = true, origin = {-10, -30}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(foxes.outflow, foxesStarving.massPort) annotation(Line(visible = true, origin = {30.855, -30}, points = {{-10.855, 0}, {10.855, 0}}, color = {128, 0, 128})); + connect(wolf_rabbit_predation.portA, rabbits.outflow) annotation(Line(visible = true, origin = {-53.333, -21.667}, points = {{3.333, 16.667}, {3.333, -8.333}, {-6.667, -8.333}}, color = {128, 0, 128})); + connect(wolf_fox_predation.portA, foxes.outflow) annotation(Line(visible = true, origin = {26.667, -21.667}, points = {{3.333, 16.667}, {3.333, -8.333}, {-6.667, -8.333}}, color = {128, 0, 128})); + connect(wolves.outflow, wolvesStarving.massPort) annotation(Line(visible = true, origin = {80, 30}, points = {{-10, 0}, {10, -0}}, color = {128, 0, 128})); + connect(wolves.inflow, wolf_rabbit_predation.portB) annotation(Line(visible = true, origin = {-16.667, 25}, points = {{66.667, 5}, {-33.333, 5}, {-33.333, -10}}, color = {128, 0, 128})); + connect(wolves.inflow, wolf_fox_predation.portB) annotation(Line(visible = true, origin = {36.667, 25}, points = {{13.333, 5}, {-6.667, 5}, {-6.667, -10}}, color = {128, 0, 128})); + connect(rabbits.y1, modelOutput.rabbits) annotation(Line(visible = true, origin = {-7.375, -47.5}, points = {{-52.125, 12.5}, {-42.625, 12.5}, {-42.625, -12.5}, {137.375, -12.5}}, color = {192, 192, 192})); + connect(foxes.y1, modelOutput.foxes) annotation(Line(visible = true, origin = {52.625, -47.5}, points = {{-32.125, 12.5}, {-22.625, 12.5}, {-22.625, -12.5}, {77.375, -12.5}}, color = {192, 192, 192})); + connect(wolves.y1, modelOutput.wolves) annotation(Line(visible = true, origin = {90.125, -17.5}, points = {{-19.625, 42.5}, {-10.125, 42.5}, {-10.125, -42.5}, {39.875, -42.5}}, color = {192, 192, 192})); + annotation(experiment(StartTime = 0, StopTime = 4415040000, __Wolfram_DisplayTimeUnit = "yr"), __Wolfram(PlotSet(plots = {Plot(name = "Populations", identifier = "populations", preferred = true, caption = "Population dynamics for foxes, rabbits, and wolves", subPlots = {SubPlot(curves = {Curve(x = time, y = modelOutput.foxes), Curve(x = time, y = modelOutput.rabbits), Curve(x = time, y = modelOutput.wolves)}, range = Range(xmin = 0, xmax = 140, xunit = "yr", ymin = -5.25, ymax = 100))}), Plot(name = "Phase Plot I", identifier = "foxes-rabbits", caption = "Phase plot for foxes and rabbits.", subPlots = {SubPlot(curves = {Curve(x = modelOutput.foxes, y = modelOutput.rabbits)})}), Plot(name = "Phase Plot II", identifier = "foxes-wolves", caption = "Phase plot for foxes and wolves.", subPlots = {SubPlot(curves = {Curve(x = modelOutput.foxes, y = modelOutput.wolves)})})})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}), graphics = {Text(visible = true, origin = {-70, -70}, textColor = {76, 112, 136}, extent = {{-25, -6}, {25, 6}}, textString = "PREY", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {0, 80}, textColor = {76, 112, 136}, extent = {{-140, -6}, {140, 6}}, textString = "Lotka-Volterra Equations Revisited", fontName = "Lato Black"), Text(visible = true, origin = {0, 70}, textColor = {76, 112, 136}, extent = {{-140, -3}, {140, 3}}, textString = "Example given by Michael Tiller in 'Modelica by Example'", fontName = "Lato", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {59.769, -70}, textColor = {76, 112, 136}, extent = {{-38, -6}, {38, 6}}, textString = "PREDATORS", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {-6.771, -70}, textColor = {76, 112, 136}, extent = {{-25, -6}, {25, 6}}, textString = "vs.", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This model extends the two species model given in the example →LotkaVolterraSystems by introducing a third species: wolves. Wolves predate on both, rabbits and foxes.

+

We can immediately extend the model for two species by introducing another material stock for wolves. As predators wolves will also be connected to a process of exponential decline (e.g. starvation in absence of prey). Since wolves predate on rabbits and foxes, there will be two nonlinear interactions between the stock of wolves and the other stocks. As before, the predator side (portB) of the NonlinearInteraction flow will be connected to the inflow port for wolves, while the prey side (portA) will be connected to the outflow port of rabbits and foxes.

+
Model Output
+ + + + + + + +
Simulation Results
\"TimePlot.svg\"
+

Notes

+ +

Acknowledgments

+

The model presented here comes from Michael Tiller's excellent introduction \"Modelica by Example\" (see Object-Oriented Modeling>Components>Examples>Lotka-Volterra Equations Revisited), which ships with SystemModeler and can also be found online.

+

See also

+

LotkaVolterraSystems, +Tutorial.UnitsInBusinessSimulations

+")); +end LotkaVolterraEquationsRevisited; diff --git a/BusinessSimulation/Examples/LotkaVolterraSystems.mo b/BusinessSimulation/Examples/LotkaVolterraSystems.mo new file mode 100644 index 0000000..4cfced8 --- /dev/null +++ b/BusinessSimulation/Examples/LotkaVolterraSystems.mo @@ -0,0 +1,68 @@ +within BusinessSimulation.Examples; + +model LotkaVolterraSystems "Predator-prey dynamics" + import BusinessSimulation.Units.Rate; + extends Icons.Example; + ModelOutput modelOutput "Main output of the model" annotation(Placement(visible = true, transformation(origin = {130, -60}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {90, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + parameter Rate alpha(displayUnit = "1/yr") = 3.17097919837646e-9 "Reproduction rate of prey"; + parameter Rate beta(displayUnit = "1/yr") = 6.34195839675292e-10 "Mortality rate of prey per predator"; + parameter Rate gamma(displayUnit = "1/yr") = 1.26839167935058e-8 "Mortality rate of predator"; + parameter Rate delta(displayUnit = "1/yr") = 6.34195839675292e-10 "Reproduction rate of predators per prey"; + inner ModelSettings modelSettings(modelDisplayTimeBase = BusinessSimulation.Types.TimeBases.years, dt(displayUnit = "yr") = 7884000, modelTimeHorizon(displayUnit = "yr") = 3153600000) annotation(Placement(visible = true, transformation(origin = {-135, -75}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + + expandable connector ModelOutput + extends Icons.DataOutPort; + import BusinessSimulation.Units.Population; + Population rabbits(unit = "rabbits") "Rabbit population"; + Population foxes(unit = "foxes") "Fox population"; + Population prey "Prey population"; + Population predators "Predator population"; + end ModelOutput; +protected + Stocks.MaterialStock prey(initialValue = 10, init = BusinessSimulation.Types.InitializationOptions.FixedValue, redeclare replaceable type OutputType = Units.Population) annotation(Placement(visible = true, transformation(origin = {-50, -30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Stocks.MaterialStock predators(initialValue = 10, init = BusinessSimulation.Types.InitializationOptions.FixedValue, redeclare replaceable type OutputType = Units.Population) annotation(Placement(visible = true, transformation(origin = {30, -30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Stocks.MaterialStock rabbits(initialValue = 10, init = BusinessSimulation.Types.InitializationOptions.FixedValue, redeclare replaceable type OutputType = Units.Population(unit = "rabbits")) annotation(Placement(visible = true, transformation(origin = {-50, 30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Stocks.MaterialStock foxes(initialValue = 10, init = BusinessSimulation.Types.InitializationOptions.FixedValue, redeclare replaceable type OutputType = Units.Population(unit = "foxes")) annotation(Placement(visible = true, transformation(origin = {30, 30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + SourcesOrSinks.ExponentialGrowth reproducing(fractionalRate = alpha, hasConstantRate = true) annotation(Placement(visible = true, transformation(origin = {-90, 30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + SourcesOrSinks.ExponentialDecline starving(hasConstantRate = true, fractionalRate = gamma) "Foxes mortality in absense of prey" annotation(Placement(visible = true, transformation(origin = {70, 30}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Flows.Interaction.NonlinearInteraction predation(hasConstantFactorA = true, hasConstantFactorB = true, a_AB = -beta, b_AB = delta) "Foxes predating on rabbits" annotation(Placement(visible = true, transformation(origin = {-10, 30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Flows.Interaction.LotkaVolterra predating(hasConstantAlpha = true, hasConstantBeta = true, hasConstantGamma = true, hasConstantDelta = true, alpha = alpha, beta = beta, delta = delta, gamma = gamma, redeclare replaceable type OutputType_A = Rate(unit = "individuals/s"), redeclare replaceable type OutputType_B = Rate(unit = "individuals/s")) annotation(Placement(visible = true, transformation(origin = {-10, -30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(prey.outflow, predating.portA) annotation(Line(visible = true, origin = {-30, -30}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(predating.portB, predators.inflow) annotation(Line(visible = true, origin = {10, -30}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(reproducing.massPort, rabbits.inflow) annotation(Line(visible = true, origin = {-70, 30}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(rabbits.outflow, predation.portA) annotation(Line(visible = true, origin = {-30, 30}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(predation.portB, foxes.inflow) annotation(Line(visible = true, origin = {10, 30}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(foxes.outflow, starving.massPort) annotation(Line(visible = true, origin = {50, 30}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(rabbits.y2, modelOutput.rabbits) annotation(Line(visible = true, origin = {-19.685, -20}, points = {{-40.815, 45}, {-50.315, 45}, {-50.315, -40}, {149.685, -40}}, color = {192, 192, 192})); + connect(prey.y1, modelOutput.prey) annotation(Line(visible = true, origin = {7.625, -47.5}, points = {{-47.125, 12.5}, {-37.625, 12.5}, {-37.625, -12.5}, {122.375, -12.5}}, color = {192, 192, 192})); + connect(predators.y1, modelOutput.predators) annotation(Line(visible = true, origin = {67.625, -47.5}, points = {{-27.125, 12.5}, {-17.625, 12.5}, {-17.625, -12.5}, {62.375, -12.5}}, color = {192, 192, 192})); + connect(foxes.y1, modelOutput.foxes) annotation(Line(visible = true, origin = {70.125, -17.5}, points = {{-29.625, 42.5}, {-15.125, 42.5}, {-15.125, -42.5}, {59.875, -42.5}}, color = {192, 192, 192})); + annotation(experiment(StartTime = 0, StopTime = 3153600000, __Wolfram_DisplayTimeUnit = "yr"), __Wolfram(PlotSet(plots = {Plot(name = "Population Dynamics", identifier = "population-plot", preferred = true, caption = "Population dynamics for rabbits and foxes", subPlots = {SubPlot(curves = {Curve(x = time, y = modelOutput.foxes), Curve(x = time, y = modelOutput.rabbits)}, range = Range(xunit = "yr"))}), Plot(name = "Phase Plot", identifier = "phase-plot", caption = "In the phase plot the oscillatory behavior of the system manifests as an orbit around a focal point.", subPlots = {SubPlot(curves = {Curve(x = modelOutput.rabbits, y = modelOutput.foxes)})})})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}), graphics = {Text(visible = true, origin = {0, 80}, textColor = {76, 112, 136}, extent = {{-140, -6}, {140, 6}}, textString = "Lotka-Volterra Systems", fontName = "Lato Black"), Text(visible = true, origin = {0, 70}, textColor = {76, 112, 136}, extent = {{-140, -3}, {140, 3}}, textString = "Example given by Michael Tiller in 'Modelica by Example'", fontName = "Lato", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {118.123, 11.585}, textColor = {76, 112, 136}, extent = {{-21.877, -6}, {21.877, 6}}, textString = "Explicit", fontName = "Lato", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {118.123, -11.585}, textColor = {76, 112, 136}, extent = {{-21.877, -6}, {21.877, 6}}, textString = "Generic", fontName = "Lato", textStyle = {TextStyle.Bold}), Line(visible = true, origin = {46.667, 0}, points = {{-186.667, 0}, {93.333, 0}, {93.333, 0}}, color = {76, 112, 136}, thickness = 1)}), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This is the basic two species model of predation from ecology—the so called Lotka-Volterra-Model [17].

+

In the upper model we recognize more explicitly that both populations, rabbits and foxes, have independent processes of exponential growth (the prey population's net rate of growth) and exponential decline (the predator's net rate of negative growth when there is no prey). The predation is modeled using an an →interaction (a special kind of flow element). It introduces nonlinearity, as there is some fractional rate (beta, delta) that is multiplied with rabbits(t) ⋅ foxes(t). Predation results in an outflow from the rabbit population (increased deaths) and an inflow to the prey population (increased reproduction).

+

The model below shows the same model structure in a generalized, more compact fashion using the interaction flow component →LotkaVolterra .

+
Model Output
+ + + + + + + +
Simulaton Results
\"Graph.svg\"
+

Notes

+ +

Acknowledgments

+

The model presented here comes from Michael Tiller's excellent introduction \"Modelica by Example\" (see Describing Behavior>Basic Equations>Examples>Lotka-Volterra System), which ships with SystemModeler and can also be found online.

+

See also

+

LotkaVolterra, NonlinearInteraction, ExponentialGrowthExponentialDecline

+")); +end LotkaVolterraSystems; diff --git a/BusinessSimulation/Examples/LoveHateDynamics.mo b/BusinessSimulation/Examples/LoveHateDynamics.mo new file mode 100644 index 0000000..bb5582d --- /dev/null +++ b/BusinessSimulation/Examples/LoveHateDynamics.mo @@ -0,0 +1,29 @@ +within BusinessSimulation.Examples; + +model LoveHateDynamics "Romeo and Juliet model as introduced by Strogatz" + extends Icons.Example; + Stocks.InformationLevel romeo(initialValue = romeoInitial) annotation(Placement(visible = true, transformation(origin = {-50, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Stocks.InformationLevel juliet(initialValue = julietInitial) annotation(Placement(visible = true, transformation(origin = {50, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Flows.Interaction.LinearInteraction loving(a_A = romeoIntrinsic, b_B = julietIntrinsic, a_B = romeoExtrinsic, b_A = julietExtrinsic, hasConstantGrowthRates = true, hasConstantFractionalGrowthRates = true, hasConstantCouplingCoefficients = true, a_0 = 0, b_0 = 0) "Interacting forces of love" annotation(Placement(visible = true, transformation(origin = {0.275, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + parameter Real romeoInitial = 1 "Initial level (should be different from 0 to find non-trivial steady state solution) (romeo.initialValue)"; + parameter Real julietInitial = 0 "Initial level (should be different from 0 to find non-trivial steady state solution) (juliet.initialValue)"; + parameter Units.Rate romeoIntrinsic = 0 "Gain for Romeo's feelings independent from Juliet"; + parameter Units.Rate julietIntrinsic = 0 "Gain for Juliet's feelings independent from Romeo"; + parameter Units.Rate romeoExtrinsic = -1 "Gain for Romeo's love aroused by Juliet"; + parameter Units.Rate julietExtrinsic = 1 "Gain for Juliet's love aroused by Romeo"; + inner ModelSettings modelSettings annotation(Placement(visible = true, transformation(origin = {-50, -70}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(loving.portA, romeo.outflow) annotation(Line(visible = true, origin = {-24.863, -0}, points = {{15.138, 0}, {-15.137, -0}}, color = {128, 0, 128})); + connect(loving.portB, juliet.inflow) annotation(Line(visible = true, origin = {25.137, 0}, points = {{-14.862, -0}, {14.863, 0}}, color = {128, 0, 128})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Using the →LinearInteraction we can model Steven H. Strogatz' differential equation model for the dynamics in a love affair—conspiciously between Juliet and Romeo [.

+

In his example—given in 1988—Strogatz described Romeo as a \"fickle\" lover who is turned off the more Juliet starts to warm up to him. On the other hand, the more Juliet dislikes him, the more he starts to approach Juliet. Juliet in comparison is a rather \"regular\" lover: The more Romeo loves her, the more she will love him and, conversely, the more he hates her, the more she hates him.

+

To put this in mathematical form, we use stocks to account for Romeo's (reomeo) and Juliet's feelings (reomeo) at any time in the simulation. We define, that 1 is to describe the highest possible degree of love, while -1 is to express the highest possible degree of hate. Initially, Romeo is fully in love with Juliet (i.e.romeoInitial = 1), while Juliet does not care about him (i.e.julietInitial = 1).

+

The relationship's dynamics arise from coupled differential equations, which can be compactly expressed using an → Interaction flow. Using a bit of shorthand notation, the system is described more generally by the following equations:

+

\"Formula.svg\"

+

The change in the states for Romeo (R) and Juliet (J) depends upon coupling coefficients. Both lovers have an intrinsic and and extrinsic coupling coefficient. In our example, there is no intrinsic coupling (i.e. romeoIntrinsic = julietIntrinsic = 0). The extrinsic coupling factors given according to the above description are: romeoExtrinsic = -1, julietExtrinsic = 1:

+

\"Formula.svg\"

+

Simulating the example quickly shows, why the technical term for this system is harmonic oscillator.

+"), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}), graphics = {Text(visible = true, origin = {0, 80}, textColor = {76, 112, 136}, extent = {{-140, -6}, {140, 6}}, textString = "Dynamics of Love and Hate", fontName = "Lato Black")}), __Wolfram(PlotSet(plots = {Plot(name = "PhasePlot", identifier = "phaseplot", preferred = true, subPlots = {SubPlot(curves = {Curve(x = romeo.y, y = juliet.y)})}), Plot(name = "LoveDynamics", identifier = "timeseries", subPlots = {SubPlot(curves = {Curve(x = time, y = juliet.y), Curve(x = time, y = romeo.y)})})})), experiment(StartTime = 0, StopTime = 10)); +end LoveHateDynamics; diff --git a/BusinessSimulation/Examples/ManagingEmployment.mo b/BusinessSimulation/Examples/ManagingEmployment.mo new file mode 100644 index 0000000..00c5a89 --- /dev/null +++ b/BusinessSimulation/Examples/ManagingEmployment.mo @@ -0,0 +1,62 @@ +within BusinessSimulation.Examples; + +model ManagingEmployment "Human resource planning" + extends Icons.Example; + ModelOutput modelOutput "The model's main output" annotation(Placement(visible = true, transformation(origin = {120, -35}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {87.542, -1.783}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + inner ModelSettings modelSettings(gaming = true, lookupDataFileURI = "modelica://BusinessSimulation/Resources/SampleTable1D.txt", modelDisplayTimeBase = BusinessSimulation.Types.TimeBases.years, modelTimeHorizon(displayUnit = "yr") = 315360000, dt(displayUnit = "yr") = 7884000) annotation(Placement(visible = true, transformation(origin = {-130, -82.855}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + + expandable connector ModelOutput "The model's main output" + extends Icons.DataOutPort; + Units.Labor workforce "The workforce given as FTE"; + Units.Labor desiredWorkforce "The desired workforce"; + Units.Time_years experience "Average workexperience in the workforce"; + end ModelOutput; +protected + SourcesOrSinks.Growth hiring annotation(Placement(visible = true, transformation(origin = {-30, -10}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Stocks.DelayN workforce(hasConstantDelayTime = false, hasStockInfoOutput = true, n = 3, redeclare replaceable type OutputType = Units.Labor, initialValue = 750) annotation(Placement(visible = true, transformation(origin = {10, -10}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + MoleculesOfStructure.Policy.FirstOrderStockAdjustment recruitingPolicy(adjTime(displayUnit = "yr") = 15768000) "How many people are needed" annotation(Placement(visible = true, transformation(origin = {-60, 30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Stocks.HinesCoflow expertise(initialValue = 252288000, hasStockInfoOutput = false, redeclare replaceable type OutputType = Units.Time_years) "Average erperience of employees" annotation(Placement(visible = true, transformation(origin = {10, -50}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + SourcesOrSinks.Growth gainingExperience(hasConstantRate = false, rate.displayUnit = "1/yr") annotation(Placement(visible = true, transformation(origin = {-30, -50}, extent = {{-10, 10}, {10, -10}}, rotation = 0))); + Converters.ConstantConverterRate gainingExperienceRate(value = 31536000, timeBaseString = "year", redeclare replaceable type ValueType = Units.Time_years) annotation(Placement(visible = true, transformation(origin = {-70, -70}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Flows.Unidirectional.OutflowDynamicStock attrition annotation(Placement(visible = true, transformation(origin = {50, -10}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + SourcesOrSinks.Cloud cloud1 annotation(Placement(visible = true, transformation(origin = {90, -10}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Converters.ConstantConverterTime employmentPeriod(value = 157680000, redeclare replaceable type OutputType = Units.Time_years) "Average length of employment" annotation(Placement(visible = true, transformation(origin = {40, 20}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Converters.DiscreteDelay.Smooth perceivedAttrition(delayTime(displayUnit = "yr") = 31536000, init = BusinessSimulation.Types.InitializationOptions.SteadyState) "The rate of leaving the company" annotation(Placement(visible = true, transformation(origin = {10, 60}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + InformationSources.RampInput experienceNewEmployees(redeclare replaceable type OutputType = Units.Time_years, offset = 157680000, startTime(displayUnit = "yr") = 31536000, height = -94608000, duration(displayUnit = "yr") = 126144000) "The prior experience of new employees given in years" annotation(Placement(visible = true, transformation(origin = {-117.141, -30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + InformationSources.RampInput desiredWorkforce(offset = 750, startTime(displayUnit = "yr") = 31536000, height = 450, duration(displayUnit = "yr") = 189216000, redeclare replaceable type OutputType = Units.Labor) "The desired Workforce given in FTE" annotation(Placement(visible = true, transformation(origin = {-118.276, 30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(hiring.massPort, workforce.inflow) annotation(Line(visible = true, origin = {-10, -10}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(recruitingPolicy.y, hiring.u) annotation(Line(visible = true, origin = {-39.667, 20}, points = {{-9.333, 10}, {4.667, 10}, {4.667, -20}}, color = {1, 37, 163})); + connect(workforce.y_stockInfo, expertise.u_stockInfo) annotation(Line(visible = true, origin = {19.333, -14.933}, points = {{-1.333, 15.333}, {-1.333, 19.933}, {10.667, 19.933}, {10.667, -15.067}, {-9.333, -15.067}, {-9.333, -25.067}}, color = {128, 0, 128})); + connect(gainingExperience.massPort, expertise.inflow) annotation(Line(visible = true, origin = {-10, -50}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(gainingExperienceRate.y, gainingExperience.u) annotation(Line(visible = true, origin = {-44.667, -66.667}, points = {{-19.333, -3.333}, {9.667, -3.333}, {9.667, 6.667}}, color = {1, 37, 163})); + connect(workforce.outflow, attrition.portA) annotation(Line(visible = true, origin = {30, -10}, points = {{-10, 0}, {10, 0}}, color = {255, 0, 0})); + connect(attrition.portB, cloud1.massPort) annotation(Line(visible = true, origin = {70, -10}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(employmentPeriod.y, workforce.u) annotation(Line(visible = true, origin = {14.667, 13.333}, points = {{19.333, 6.667}, {-9.667, 6.667}, {-9.667, -13.333}}, color = {1, 37, 163})); + connect(attrition.y, perceivedAttrition.u) annotation(Line(visible = true, origin = {43.121, 40.133}, points = {{11.879, -39.733}, {11.879, 19.867}, {-23.758, 19.867}}, color = {1, 37, 163})); + connect(perceivedAttrition.y, recruitingPolicy.u_outflow) annotation(Line(visible = true, origin = {-36.667, 53.667}, points = {{36.667, 6.333}, {-18.333, 6.333}, {-18.333, -12.667}}, color = {1, 37, 163})); + connect(workforce.y2, recruitingPolicy.u_current) annotation(Line(visible = true, origin = {-30.1, 22.2}, points = {{29.6, -37.2}, {20.1, -37.2}, {20.1, 27.8}, {-34.9, 27.8}, {-34.9, 18.8}}, color = {1, 37, 163})); + connect(experienceNewEmployees.y, expertise.u) annotation(Line(visible = true, origin = {-33.047, -33.333}, points = {{-76.094, 3.333}, {38.047, 3.333}, {38.047, -6.667}}, color = {1, 37, 163})); + connect(desiredWorkforce.y, recruitingPolicy.u_reference) annotation(Line(visible = true, origin = {-98.138, 30}, points = {{-12.138, 0}, {27.138, 0}}, color = {1, 37, 163})); + connect(workforce.y1, modelOutput.workforce) annotation(Line(visible = true, origin = {47.625, -27.5}, points = {{-27.125, 12.5}, {-22.625, 12.5}, {-22.625, -7.5}, {72.375, -7.5}}, color = {192, 192, 192})); + connect(desiredWorkforce.y, modelOutput.desiredWorkforce) annotation(Line(visible = true, origin = {-37.569, -2.5}, points = {{-72.707, 32.5}, {-42.431, 32.5}, {-42.431, -32.5}, {157.569, -32.5}}, color = {192, 192, 192})); + connect(expertise.y, modelOutput.experience) annotation(Line(visible = true, origin = {50, -36.533}, points = {{-35, -3.067}, {-35, 1.533}, {70, 1.533}}, color = {192, 192, 192})); + annotation(__Wolfram(PlotSet(plots = {Plot(name = "Workforce and Experience", identifier = "workforce-experience", preferred = true, caption = "The workforce closely follows the desired level (Fig1); average workexperience drops significantly over the next years (Fig2).", subPlots = {SubPlot(title = "Workforce", identifier = "Fig1", curves = {Curve(x = time, y = modelOutput.workforce), Curve(x = time, y = modelOutput.desiredWorkforce)}), SubPlot(title = "Experiece", identifier = "Fig2", curves = {Curve(x = time, y = modelOutput.experience)})})})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}), graphics = {Text(visible = true, origin = {0, 80}, textColor = {76, 112, 136}, extent = {{-140, -6}, {140, 6}}, textString = "Managing Employment", fontName = "Lato Black")}), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

In this stylized model of human resource management, we are using →FirstOrderStockAdjustment to control the rate of hiring to keep a company's workforce at the desired level given in full time equivalents (FTE). The workforce in the present case is reduced by attrition as the average employment period is 5 years—we will model this delay as an exponential delay of 3rd order.

+

At the start of the simulation we will have the workforce meet its desired level of 750 FTE. The desired workforce will then ramp up by 450 FTE starting at the end of the first year over a time of six years.

+

We would like to keep track of the average experience of the workforce, which we will simply measure in years of relevant work experience. New employees will arrive with an experience of 5 years, but we assume that this will fall to just 2 years starting at the end of the first year over four years due to fierce competition for experienced workers. At the start of the simulation, the average experience in our company is around 8 years.

+
Model Output
+ +

Notes

+ +"), experiment(StartTime = 0, StopTime = 315360000, __Wolfram_DisplayTimeUnit = "yr")); +end ManagingEmployment; diff --git a/BusinessSimulation/Examples/SIR.mo b/BusinessSimulation/Examples/SIR.mo new file mode 100644 index 0000000..f8ca3ae --- /dev/null +++ b/BusinessSimulation/Examples/SIR.mo @@ -0,0 +1,65 @@ +within BusinessSimulation.Examples; + +model SIR "Classical epidemic model by Kermack and McKendrick" + extends Icons.Example; + inner ModelSettings modelSettings(modelDisplayTimeBase = BusinessSimulation.Types.TimeBases.days) annotation(Placement(visible = true, transformation(origin = {-115, -75}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + + expandable connector ModelOutput "The model's main output" + import BusinessSimulation.Units.{Amount,Rate}; + extends Icons.DataOutPort; + Amount infected(displayUnit = "million") "Infected population"; + Amount susceptible(displayUnit = "million") "Susceptible population"; + Amount removed(displayUnit = "million") "Removed population"; + end ModelOutput; + + ModelOutput modelOutput "The model's main output" annotation(Placement(visible = true, transformation(origin = {130, -60}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {90, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + parameter Converters.ConstantConverter.OutputType baseReproductionNumber(displayUnit = "each") = 2.5 "Value of constant output (R0.value)"; + parameter Converters.ConstantConverterTime.OutputType infPeriod(displayUnit = "d") = 432000 "Length of the infectious perid (infectiousPeriod.value)"; + parameter Integer n(min = 1) = 3 "Order of the exponential delay (infected.n)"; +protected + Stocks.MaterialStock susceptible(initialValue(displayUnit = "million") = 1e6, redeclare replaceable type OutputType = Units.Amount) "Population in the susceptible stage of the disease" annotation(Placement(visible = true, transformation(origin = {-90, -30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Stocks.MaterialStock removed(redeclare replaceable type OutputType = Units.Amount) annotation(Placement(visible = true, transformation(origin = {70, -30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Stocks.DelayN infected(n = n, initialValue = 1, hasConstantDelayTime = false, delayTime.unit = "d", redeclare replaceable type OutputType = Units.Amount) "Population in the infectious stage of the disease" annotation(Placement(visible = true, transformation(origin = {-10, -30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + MoleculesOfStructure.Actuators.Diffusion becoming_infected(hasConstantOtherAdopters = true, hasConstantOtherPopulation = false, hasConstantFractionalAdoptionRate = true, hasConstantAdoptionFraction = true, nextStageIsInfluencing = true, fractionalAdoptionRate = 0, adoptionFraction = 1) "The infection is spread by a process of social diffusion" annotation(Placement(visible = true, transformation(origin = {-50, -30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Flows.Unidirectional.OutflowDynamicStock being_removed annotation(Placement(visible = true, transformation(origin = {30, -30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ConstantConverterTime infectiousPeriod(value(displayUnit = "d") = infPeriod) "Time interval during which an individual is infectious" annotation(Placement(visible = true, transformation(origin = {20, 0}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Converters.ConstantConverter R0(value(displayUnit = "each") = baseReproductionNumber) "Basic reproduction number for the infectious disease" annotation(Placement(visible = true, transformation(origin = {20, 25}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Converters.Division transmissionRate "Effective contact rate" annotation(Placement(visible = true, transformation(origin = {-30, 20}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Interfaces.Connectors.DataInPort inputDiffusion "Collected (named) input for the infection process" annotation(Placement(visible = true, transformation(origin = {-90, 5}, extent = {{-10, -10}, {10, 10}}, rotation = -810), iconTransformation(origin = {-63.333, 35.643}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(susceptible.outflow, becoming_infected.portA) annotation(Line(visible = true, origin = {-70, -30}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(becoming_infected.portB, infected.inflow) annotation(Line(visible = true, origin = {-30, -30}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(infected.outflow, being_removed.portA) annotation(Line(visible = true, origin = {10, -30}, points = {{-10, 0}, {10, 0}}, color = {255, 0, 0})); + connect(being_removed.portB, removed.inflow) annotation(Line(visible = true, origin = {50, -30}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(R0.y, transmissionRate.u1) annotation(Line(visible = true, origin = {-4, 25}, points = {{18, 0}, {-18, 0}}, color = {1, 37, 163})); + connect(infectiousPeriod.y, transmissionRate.u2) annotation(Line(visible = true, origin = {-0.439, 7.5}, points = {{14.439, -7.5}, {3.061, -7.5}, {3.061, 7.5}, {-21.561, 7.5}}, color = {1, 37, 163})); + connect(becoming_infected.dataIn, inputDiffusion) annotation(Line(visible = true, origin = {-72.5, -5}, points = {{17.5, -15}, {17.5, -5}, {-17.5, -5}, {-17.5, 10}}, color = {0, 0, 128})); + connect(removed.y, inputDiffusion.otherPopulation) annotation(Line(visible = true, origin = {-7.5, 25.1}, points = {{82.5, -44.7}, {82.5, 24.9}, {-82.5, 24.9}, {-82.5, -20.1}}, color = {1, 37, 163})); + connect(infectiousPeriod.y, infected.u) annotation(Line(visible = true, origin = {-5.333, -6.667}, points = {{19.333, 6.667}, {-9.667, 6.667}, {-9.667, -13.333}}, color = {1, 37, 163})); + connect(transmissionRate.y, inputDiffusion.contactRate) annotation(Line(visible = true, origin = {-72.667, 15}, points = {{34.667, 5}, {-17.333, 5}, {-17.333, -10}}, color = {1, 37, 163})); + connect(susceptible.y1, modelOutput.susceptible) annotation(Line(visible = true, origin = {-24.875, -47.5}, points = {{-54.625, 12.5}, {-50.125, 12.5}, {-50.125, -12.5}, {154.875, -12.5}}, color = {192, 192, 192})); + connect(infected.y1, modelOutput.infected) annotation(Line(visible = true, origin = {37.248, -47.5}, points = {{-36.748, 12.5}, {-32.248, 12.5}, {-32.248, -12.5}, {92.752, -12.5}}, color = {192, 192, 192})); + connect(removed.y1, modelOutput.removed) annotation(Line(visible = true, origin = {102.203, -47.5}, points = {{-21.703, 12.5}, {-17.203, 12.5}, {-17.203, -12.5}, {27.797, -12.5}}, color = {192, 192, 192})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The SIR model is a classical approach in mathematical epidemiology to study the spread of infectious diseases. The model goes back to William Ogilvy Kermack and Anderson Gray McKendrick [23] and is also called Kermack-McKendrick-Model.

+

The whole population is separated into three stocks(→modelOutput):

+ +

As in the example →SimpleProductionChainIII we are using the →Diffusion component to model social diffusion, e.g. spread by contact. The transmissionRate (β in the mathematical literature) is also sometimes called the effective contact rate which helps to understand why we have set the adoptionFraction to 1in the Diffusion component.

+ + + + + + +
Simulaton Results
\"Graph.svg\"
+

Notes

+ +"), experiment(StartTime = 0, StopTime = 8640000, __Wolfram_DisplayTimeUnit = "d"), __Wolfram(PlotSet(plots = {Plot(name = "SIR", identifier = "stocks", preferred = true, caption = "Susceptible, infected, and removed population.", subPlots = {SubPlot(curves = {Curve(x = time, y = modelOutput.infected), Curve(x = time, y = modelOutput.removed), Curve(x = time, y = modelOutput.susceptible)}, range = Range(yunit = "million"))})})), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}), graphics = {Text(visible = true, origin = {0, 75}, textColor = {76, 112, 136}, extent = {{-140, -6}, {140, 6}}, textString = "SIR Model of an Epidemic", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {0, 65}, textColor = {76, 112, 136}, extent = {{-140, -3}, {140, 3}}, textString = DynamicSelect("Kermack and McKendrick", "Kermack and McKendrick"), fontName = "Lato", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {-90, -60}, textColor = {128, 128, 128}, extent = {{-11.512, -12.439}, {11.512, 12.439}}, textString = "S", fontSize = 72, textStyle = {TextStyle.Bold}), Text(visible = true, origin = {-10, -60}, textColor = {128, 128, 128}, extent = {{-11.512, -12.439}, {11.512, 12.439}}, textString = "I", fontSize = 72, textStyle = {TextStyle.Bold}), Text(visible = true, origin = {70, -60}, textColor = {128, 128, 128}, extent = {{-11.512, -12.439}, {11.512, 12.439}}, textString = "R", fontSize = 72, textStyle = {TextStyle.Bold})})); +end SIR; diff --git a/BusinessSimulation/Examples/SimpleProductionChain.mo b/BusinessSimulation/Examples/SimpleProductionChain.mo new file mode 100644 index 0000000..d7e7403 --- /dev/null +++ b/BusinessSimulation/Examples/SimpleProductionChain.mo @@ -0,0 +1,73 @@ +within BusinessSimulation.Examples; + +model SimpleProductionChain "A first example" + extends Icons.Example; + inner ModelSettings modelSettings(modelDisplayTimeBase = BusinessSimulation.Types.TimeBases.months, dt(displayUnit = "mo") = 657000, modelTimeHorizon(displayUnit = "mo") = 157680000) annotation(Placement(visible = true, transformation(origin = {-135, -75}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + ModelOutput modelOutput "Main output for the model" annotation(Placement(visible = true, transformation(origin = {130, 10}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {90, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + + expandable connector ModelOutput "Expandable connector for model output" + import BusinessSimulation.Units.{Amount,Rate}; + extends Icons.DataOutPort; + Amount inventory "Finished goods inventory"; + Amount installedBase "Installed base for the product"; + Rate producing "Rate of production"; + Rate shipping "Rate of shipping to customers"; + Rate scrapping "Rate of scrapping at the end of useful life"; + end ModelOutput; +protected + Stocks.MaterialStock inventory(initialValue = 0, redeclare replaceable type OutputType = Units.Amount) "Finished goods inventory" annotation(Placement(visible = true, transformation(origin = {-50, -5}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Flows.Unidirectional.Transition shipping(hasConstantRate = false, rate(displayUnit = "1/mo") = 3.80517503805175e-06, redeclare replaceable type OutputType = Units.Rate) "Shippment to the customer at an exogenous rate" annotation(Placement(visible = true, transformation(origin = {-10, -5}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + SourcesOrSinks.Growth producing(hasConstantRate = false, rate(displayUnit = "1/mo") = 3.80517503805175e-05) "Production at a constant rate" annotation(Placement(visible = true, transformation(origin = {-90, -5}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Stocks.DelayN installedBase(hasConstantDelayTime = false, n = 4, delayTime(displayUnit = "yr") = 157680000, initialValue = 0, redeclare replaceable type OutputType = Units.Amount) "Product stays in use for around 5 years" annotation(Placement(visible = true, transformation(origin = {30, -5}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Flows.Unidirectional.OutflowDynamicStock scrapping "After its useful life has expired, products will be discarded" annotation(Placement(visible = true, transformation(origin = {70, -5}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ConstantConverterRate productionRate(value = 100, timeBaseString = "month", redeclare replaceable type ValueType = Types.Reals) annotation(Placement(visible = true, transformation(origin = {-120, 25}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + InformationSources.RampInput firstTimePurchases(offset(displayUnit = "1/mo") = 3.80517503805175e-06, height(displayUnit = "1/mo") = 3.42465753424658e-05, startTime(displayUnit = "mo") = 15768000, duration(displayUnit = "mo") = 47304000, redeclare replaceable type OutputType = Units.Rate) "Ramping up from 10 to 100 units per month starting at 6 mo for 18 mo" annotation(Placement(visible = true, transformation(origin = {-40, 25}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ConstantConverterTime usefulLife(value(displayUnit = "yr") = 157680000) "How long will a product be used on average" annotation(Placement(visible = true, transformation(origin = {5, 25}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + SourcesOrSinks.Cloud cloud1 annotation(Placement(visible = true, transformation(origin = {110, -5}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); +equation + connect(inventory.outflow, shipping.portA) annotation(Line(visible = true, origin = {-30, -5}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(shipping.portB, installedBase.inflow) annotation(Line(visible = true, origin = {10, -5}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(producing.massPort, inventory.inflow) annotation(Line(visible = true, origin = {-70, -5}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(installedBase.outflow, scrapping.portA) annotation(Line(visible = true, origin = {50, -5}, points = {{-10, 0}, {10, 0}}, color = {255, 0, 0})); + connect(scrapping.portB, cloud1.massPort) annotation(Line(visible = true, origin = {90, -5}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(productionRate.y, producing.u) annotation(Line(visible = true, origin = {-101.333, 18.333}, points = {{-12.667, 6.667}, {6.333, 6.667}, {6.333, -13.333}}, color = {1, 37, 163})); + connect(firstTimePurchases.y, shipping.u) annotation(Line(visible = true, origin = {-20.667, 18.333}, points = {{-11.333, 6.667}, {5.667, 6.667}, {5.667, -13.333}}, color = {1, 37, 163})); + connect(usefulLife.y, installedBase.u) annotation(Line(visible = true, origin = {20.333, 18.333}, points = {{-9.333, 6.667}, {4.667, 6.667}, {4.667, -13.333}}, color = {1, 37, 163})); + connect(producing.y, modelOutput.producing) annotation(Line(visible = true, origin = {-13.333, 8.467}, points = {{-71.667, -3.067}, {-71.667, 1.533}, {143.333, 1.533}}, color = {192, 192, 192})); + connect(shipping.y, modelOutput.shipping) annotation(Line(visible = true, origin = {40, 8.467}, points = {{-45, -3.067}, {-45, 1.533}, {90, 1.533}}, color = {192, 192, 192})); + connect(scrapping.y, modelOutput.scrapping) annotation(Line(visible = true, origin = {93.333, 8.467}, points = {{-18.333, -3.067}, {-18.333, 1.533}, {36.667, 1.533}}, color = {192, 192, 192})); + connect(inventory.y, modelOutput.inventory) annotation(Line(visible = true, origin = {13.333, 8.467}, points = {{-58.333, -3.067}, {-58.333, 1.533}, {116.667, 1.533}}, color = {192, 192, 192})); + connect(installedBase.y, modelOutput.installedBase) annotation(Line(visible = true, origin = {66.667, 8.467}, points = {{-31.667, -3.067}, {-31.667, 1.533}, {63.333, 1.533}}, color = {192, 192, 192})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This introductory example continues the example given in the →Tutorial (please read that section first, if you have not done so already). Here we consider a simple production chain for a company (e.g. ACME) producing a durable good (e.g. intruder alarm systems). Products will be produced at a constant rate of 100 units per month. The finished goods will be collected in a finished-goods inventory from where they will be shipped to customers. The inventory will be empty at the start of the simulation.

+

In this introductory example we will assume that there are only first-time purchases and that the rate of purchasing is also the rate of shipment to the customers. Initially the purchase rate will be 10 units per month, but due to some marketing initiative we assume that starting in month six the rate will ramp up to 100 units per month within 18 months after which it will remain at that level.

+

Units will remain in use for an average useful life of 5 years. After the useful life has expired, the units will be discarded. In this example, we will not consider replacement purchases.

+

The graph below shows different distributions for the useful life given an average life of 5 years. The order of the DelayN component determines the variance for the lifetime distribution. The dashed red lines show the 95th percentil and the red value above indicate the corresponding order <code<n. Since we assume, that 95% of the products will have been discarded after 10 years, it turns out that n = 4 produces a delay distribution matching the assumption.

+ + + + + + +
Distributions for Useful Life for Different Delay Orders n
\"UsefulLifeDistributions.png\"
+

In the lower half of the diagram we have included an event-driven process chain (EPC) model typically used in Business Process Modelling (BPM). It offers a nice analogy and allows the transition to a System Dynamics perspective coming from that background: While the process is valid for a single unit, in the continuous time simulation we are aggregating the processes (green) and events (red) over time. An event will thus turn into a stock counting the amount of \"material\" that is in a corresponding state at and given time. A process corresponds to a transition between states at a certain rate given as entities per period.

+

EPC always start and end with an event and accordingly we always have to start and end with a stock. In this case the first event is \"hidden\" as a stock with an infinite capacity inside the component of type Growth. AvailableProducts corresponds to the stock inventory, while \"product received\" pertains to installedBase.

+
Model Output
+ +

Notes

+

A lot of components will refer to variables contained in modelSettings. There should always be an instance of that class in the top level scope of any model.

+

See also

+

+Tutorial.StrategicBusinessSimulation, +SimpleProductionChainII, SimpleProductionChainIII, DelayN

+"), experiment(StartTime = 0, StopTime = 157680000, __Wolfram_DisplayTimeUnit = "mo"), __Wolfram(PlotSet(plots = {Plot(name = "Stocks", identifier = "stocks", preferred = true, caption = "Inventory levels off when production and shipping rates are identical.", subPlots = {SubPlot(curves = {Curve(x = time, y = modelOutput.installedBase), Curve(x = time, y = modelOutput.inventory)})}), Plot(name = "Flows", identifier = "flows", caption = "Shipping ramps up to the rate of production, while scrapping starts to become notable after about two years.", subPlots = {SubPlot(curves = {Curve(x = time, y = modelOutput.producing), Curve(x = time, y = modelOutput.scrapping), Curve(x = time, y = modelOutput.shipping)}, range = Range(yunit = "1/mo"))})})), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}), graphics = {Text(visible = true, origin = {0, 65}, textColor = {76, 112, 136}, extent = {{-140, -6}, {140, 6}}, textString = "Simple Production Chain", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Bitmap(visible = true, origin = {-11.743, -50.767}, fileName = "", imageSource = "iVBORw0KGgoAAAANSUhEUgAAA2EAAAD0CAYAAAASTy5SAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAEnQAABJ0Ad5mH3gAAD2oSURBVHhe7Z1ddxTXna/P9ckHmLt8hnyQs7JmrXORi7maXIwzXJjkgmTCJA6ZWJkzVmYs40TOmNghcTCxiYwjYmxeBGqpab1AIwkECIElLGELK0bYsoHI1sw++hX9T3Zqthq1urtqV+t51nqWurteulW79K/9066u+l8OAAAAAAAAMoMQBgAAAAAAkCGEMAAAAAAAgAwhhAEAAAAAAGQIIQwAAAAAACBDCGEAAAAAAAAZQggDAAAAAADIEEIYAAAAAABAhhDCAAAAAAAAMoQQBgAAAAAAkCGEMAAAAAAAgAwhhAEAAAAAAGQIIQwAAAAAACBDCGEAAAAAAAAZQggDAIiQ+/fvu6GhIWyB2pYAAAAxQQgDAIiQKxMTbrG317l/+AdswsXnnku2JQAAQEwQwgAAImNpaclNvvNOMFRg404eP55sUwAAgFgghAEARMQXX3zhKqWS++R73wsGCmxcbcuR4eFk2wIAAMQAIQwAICJmr151c7/4RTBM4PbVNr1+6VJtKwMAAOQLIQwAIBI++ugjd/7sWeeeeCIYJLAJN7bp+dOnk20MAACQN4QwAIBIuFAuu49+9KNwiMCm1bbVNgYAAMgbQhgAQATMz86666+/HgwP2Dqvv/KKm5ubq211AACAfCCEAQDkzOrqanIxjs+ffDIYHLB1ahuPDA4m2xwAACAvCGEAADkzOTbmlp57LhgasPUuPfNMss0BAADyghAGAJAjt+fm3HR/fzAsYPu80tfnFhcXa60AAACQLYQwAICcePDggRsaGnL39+wJBgVsn9rm2vZqAwAAgKwhhAEA5MSViQm30NsbDAnYfhf270/aAAAAIGsIYQAAOfDhhx+6iXfeCYYDzM6J48eTtgAAAMgSQhgAQMZ88cUXbmRoyH38/e8HgwFmp9pAbaE2AQAAyApCGABAxsxeverefemlYCjA7FVb3Lh8udY6AAAA7YcQBgCQIXfv3nXnz551//3EE8FAgNmrthg/fTppGwAAgCwghAEAZEj13Dn3x6efDoYBzE+1idoGAAAgCwhhAAAZMT87664fORIMAZi/13/zGzc/P19rLQAAgPZBCAMAyIDV1VVXKZXc2u7dwQCA+au2qQwOJm0FAADQTghhAAAZMDU+7pb27w92/jEeP+juTtoKAACgnRDCAADazO3bt93l/v5gpx/j83JfX9JmAAAA7YIQBgDQRh48eOCGh4bcZ9/+drDDj/GptlKbqe0AAADaASEMAKCNXJ2cdO+98EKws4/xurB/f9J2AAAA7YAQBgDQJj788EM3ceJEsJOP8Xvx+PGkDQEAAFoNIQwAoA2sr6+70eFhd+/73w928DF+1XajQ0NJWwIAALQSQhgAQBuYvXrVvfvyy8HOPRZHteGNy5drrQoAANAaCGEAAC3m7t27buzMGfdf3/hGsGOPxVFtOH76dNKmAAAArYIQBgDQYqqVivtjV1ewU4/FU21ZLZdrrQsAANA8hDAAgBYyPzvrZo4cCXbmO17djFqEphXcmUOH3K1btx79fgAAAE1CCAMAaBGffvqpO1cqubVvfjPYke94x8edW1kJTyu4alO1rdoYAACgWQhhAAAtYmojhLyv0aBAJ35H+P77jwxN6wA/+MlPkjYGAABoFkIYAEALuH37trt87Fiw814YNYrlY6/39z+apoAlZmcfve4HEk2Xei20vvv3//K61uMvW6DgevmNN5K2BgAAaAZCGABAkzx8+NCVh4bcZ9/5TrDjXggVkvxRLAtdeqzQJSx8SQtRFqAsoNnz9Pr03AKaHvvzFki1sdpabQ4AALBdCGEAAE1ydXLSvffznwc77YVQ4cgfqZIKXApieqwwZY9Nze+HMo2WCT1Or09hS2gePRcWyAroe88/n7Q5AADAdiGEAQA0wfLysrt44kSws14Y/VEv0w9e/iiWtFDlj2SlQ1saC2B+WCuwF995J2l7AACA7UAIAwDYJuvr625seNjde+qpYEe9MCo8+aNa0g9ewg9cFqT81zS/BbnQ+kyt08JagVWbq+21DwAAADQKIQwAYJvcnJlxN3/5y2AnvVCmTzfUczudMDRylT69UMsKC216boEsrV7fbFrBVNvfuHz50e8OAADQAIQwAIBtsLIRNMbOnnX/9Y//GOygF04fP5D5pxn6KkgZCl8KbTYyZiHNxwJb+tTGAqu2Hx8YSPYFAACARiCEAQBsg2ql4pZ//ONg5xx3jtoHquVyba8AAADYGoQwAIAGee/mTTfzu98FO+W485x59VX33nvv1fYOAACAx0MIAwBogE8//dSVSyX3p299K9ghx52n9gXtE9o3AAAAtgIhDACgAS6fP+/ef/75YGccd67v//u/u//zzf8XnSOXrtf2XAAAiAlCGABAA1yuVpMOd6gjjjvXWEPYs6++VdtzAQAgJghhAAANwOmImDbG0xFPjV0ihAEARAwhDACgQXRhjmu//W2wQ447T+0L2idighAGABA3hDAAgG3AJeozUvcUC92nLBJjvUQ9IQwAIG4IYQAA20A36NWNejvmZs2tUDdi1k2cQ9O2q9anG0aHpuVszDdrJoQBAMQNIQwAYJvcnJlxN3/5y2AHHVukgp1Gw0LTclZtf+Py5dreEBeEMACAuCGEAQBsk/X1dTc2POzuPfVUsJMejQoxGlGyERsLNRph8tm//y/LaH7DH4nabJn+/kfP9Vjv4y/jT5ONvK/wp0ei2nxsaCjZB2KEEAYAEDeEMACAJlheXnYX33kn2FGPRgs2/oiSXtMok/9chqbpsYJQvWUUmOy7W/7r6ef62cj7+s8jUm2uto8VQhgAQNwQwgAAmuTa5cvuvZhv4KxwZEFHKlAJf4RJYUdBKjTtccvosR+m/EAmhUbD6q3Dpmk+m5ZeTyS+9/Ofu2vV6qPPGymEMACAuCGEAQA0ycOHD115aMh99p3vBDvtuSv8cKMRsTQWpvQzNPpUbxmpZWykTT9tHX6QqrcOfxlTy/nvEYFqY7W12jxmCGEAAHFDCAMAaAG3b992l998M9hxz1UbYfJf84NR2s2m1VtGChvh8t9TWAB83Pv6IczWYcEuEi+/8Ya7PTf36LNFDCEMACBuCGEAAC3iUrXqPvjJT4Kd99wMjTClA096mvCfKxDVWyZ94Q0pNL9/GmS9ddgomT03LNhFoNp2amSk9sHihhAGABA3hDAAgBbx6aefunOlklv75jeDnfhc9L+r5asw5KOAFJq22evCpulneoRL84YC11bfV8EutHxOqk3VtmrjIkAIAwCIG0IYAEALmd8IFdcOHw525LG4qk3VtkWBEAYAEDeEMACAFlOtVNwfu7qCnXksnmrLC0NDtdYtBoQwAIC4IYQBALSYu3fvuvHTp91/feMbwU49Fke1odpSbVokCGEAAHFDCAMAaAOzV6+6d19+Odixx+KoNrwxMVFr1eJACAMAiBtCGABAG1hfX3ejw8Pu3ve/H+zcY/yq7UZLpaQtiwYhDAAgbghhAABt4sMPP3QXjx8PdvAxftV2Hy4s1FqzWBDCAADihhAGANBGrl665BYiutcVbs33XnjBXbV7lxUQQhgAQNwQwgAA2siDBw/c8NCQ++zb3w529jE+1VbljTZT2xUVQhgAQNwQwgAA2szt27fd9JtvBjv8GJ+X+/rc7bm5WusVk50Swj7//HN3584dNzJRdWdHzrmB4SE3tBGgsViq3UqjI+781GTSnmpXgE6HEAYAkAFTFy64D7q7g51+jEe10dTISK3Vikunh7D79++76uVLbnCj8/7Td37vvvrKfveVF3/svvyzp9yXer7t/jcWRrWX2k3tp3b8t2NH3NmhUtK+auedgH7PUDjFxi3SPkMIAwDIgNXVVVcpldza7t3Bzj/mr9pGbaS2KjqdHMKuXp9xZzY66d848vJGB/47wY49Flu169//9sWknW/cuFFr+c5lemLCLfb2BusSbt3Fnh43feFCbavGDyEMACAj5mdn3fXDh4MHD8zf67/5TdJGnUAnhjCdolapnnfdx/vc3zz/z8HOO3aWaueuY68n7d6ppyguLS25ybc2/k4DNQkbd7K/P9mmRYAQBgCQIRfOnXN/fPrp4MED81NtcmF4uNZKxafTQpg64EMjFbe771fBzjp2tk+89ouk/TstiK2trbnK0JD7ZO/eYF3CxtW21DbVto0dQhgAQIbcvXvXjZ8+7f77iSeCBxDMXrWF2kRt0yl0WgjTSMiTBLAdbRLEzo/V9ojOYGZqyt06cCBYl3D7aptq28YOIQwAIGNmr1517770UvDggdmrtpi9eLHWOp1BJ4UwfQes5+03gx1z3Fnq1ETtD53A8vKyq548GaxJ2LzVEyeSbRwzhDAAgIz54osv3Gi57D7+/veDBw/MTrXByOBg0iadwMil64mH3h5OQtiT3S//+bXPHjyszVUcdKUzXZyB74Ch1H4wsLE/FP2qievr625s4xiwsm9fsC5h82rbahtrW8cKIQwAIAc+/PBDN3H8ePDggdmpNvhwYaHWKsXn6//yQhK+Qt65+3FtruKgy5TrKoihDjnuTHXVRO0XRebGtWvu5sGDwZqErVPbWNs6VghhAAA5cWViwi3s3x88eGD7XejtdVfHOus7JgeOng4GsKdf6qvNURx0EQbdB4zL0KOv9oczpVJhL9KxsrLixs6edeu7dgXrErZObePxgYFkm8cIIQwAICcePHjw6OaSe/YEDyDYPrXNte3VBp2ERrtCIUynJxaNO3fuuGePHw12xHFn+8yxI8n+UUSqlYpb7uoK1iVsvdrW1XK5tvXjghAGAJAji4uLbvro0eDBA9vnlb4+d3turtYKnUXolMQinoo4MlF1X31lf7ATjjtb7RfnpyZre0px0H0IZ44cCdYkbJ8z +hw65+fn5WivEAyEMACBnJsfG3NIzzwQPHth6ta2nRkdrW7/zSJ+SqItzFJGzI+fcV178cbATjjtb7Rcnzg3V9pRisLq66iqlklvbvTtYl7B9aptXBgeTNogJQhgAQM7owKAr9H3+5JPBAwi2Tm3jGA/GrURXQvRDmEJZERkYHnJf/tlTwU447my1X5weLtX2lGIwNT7ulp57LliXsP0udXcnbRAThDAAgAjQaSrXX301ePDA1nn9lVeSbd3J6FL0fghTKCsi+s7elwIdcETtF9o/isLi3Jyb7u8P1iTMTp2GvhDR1XAJYQAAkXChXHYf/ehHwYMHNq+27fkCddyaQVdDVAD72nd7Cnl/MKFOdqgDjiiLEsJ0TzN9Vi7AlL92QaZY7jNHCAMAiISPPvrInT992rknnggeQLAJN7aptq228U7g1NilJIQV8dL0BiEM61mUEDY9MeEWe3vDdQkzd7Gnx01fuFBrnXwhhAEARMTs1atu7uc/Dx48cPvO/eIX7vrFi7Wt3PnYKYlFPRVREMKwnkUIYUtLS27yrbeCNQnzc7K/P2mbvCGEAQBExBdffOFGhofdJ9/7XvDggY2rbTlSKiXbdiehS9UX8dL0BiEM6xl7CFtbW3OVjc/4yd69wbqE+ak2UduojfKEEAYAEBnJf0//8IfgwQMbd/L4cbf03nu1rbtzuHSj2L8zIQzrGXsIm5macrcOHAjWJMxftY3aKE8IYQAAEXJF3yPgcsZNq+9iXBkbq23VzkQjfPfu3XM3br7rLk5ddsOVUVcaPudKQ8OP3HhcHhlzFyY2OoW3biXzFgFCGNYz5hC2vLzsqidPBmsSxmP1xImkrfKCEAYAECF2RS1s3liuhNVKLHgpdJ0pDbm+P5xwP3npNbfvp79yu7pecF//wfPu/+75SaIef+uZF90/Pfuy+9f/POSOnzqTbJepS9NRX6hEnzHU+UaU2j9iZH193Y2Vy25l375gxx/jUW2ktlKb5QEhDAAAoEAsffihOzcymgQvhSqFLLsn2FZVOFNge/PtU8lI2Z07d2prjwdCGNYz1hB249o1d/PgwWCnH+NTbaU2ywNCGAAAQAHQyJeFL41shcLVdtTI2dunBpIwFtOpioQwrGeMIWxlZcWNnT3r1nftCnb4MT7VVuMDA0nbZQ0hDAAAIHL0fa+zg6Vk9EqjWKEw1aw6XfH0mcHke2MxQAjDesYYwqqVilvu6gp29jFe1WbVcrnWitlBCAMAAIgUffdLF9R4vf9t93d7nw2Gp1aqgHf4zbfc2Pn8b2ZKCMN6xhbC5mdn3cyRI8FOPsbvzKFDbn5+vtaa2UAIAwAAiJCHDx+6yti4e/7Xv2vb6Ndm/sfLryWnPuZ5bzVCGNYzphC2urrqKqWSW9u9O9jBx/hV21UGB5O2zApCGAAAQGQo/Gg0Slc8DIWkLNRFP8rnKrVPlD2EMKxnTCFsanzcLXFLkcK71N2dtGVWEMIAAAAiQ6cgagQsFI6ytPeV3+V2aiIhDOsZSwhbnJtz0/39wU49Fs8rfX1uYWGh1rrthRAGAAAQEXPz867/nVOZn4K4mfqO2Mz12dqnyw5CGNYzhhBm93O8v2dPsEPf0e7f/2gjhKYVWLVl0qYZ3F+SEAYAABAJukS8rlAYSwCT+iwnTp/J/MbOhDCsZwwhbHpiwi329gY78x2vTtvTZd1D07aq1qGwE5qWo4s9PW76QvvPACCEAQAARMJwZTS5VHwoDOWp7ks2XD5X+5TZQAjDeuYdwpaWltzkW28FO/E7wvfff2Ro2ladnW1+HW1ysr8/aeN2QggDAACIAI006UbMoRAUg29sfLY7d+7UPm37IYRhPfMMYWtra66y8f6f7N0b7MDnrp0qqO+qGX7Y0WP/AhSaX6+nb1hs80t/fs0n9ZqtT4HKn9cf4Uovq9fSp/vZuiJRbas2Vlu3C0IYAABAzuhqiMPnKm5X1wvBABSDX//B8xsd3+HaJ24/hDCsZ54hbGZqyt06cCDYeY9CCz0WeCyMWdiyAGTP7TU/qGlZe27rs/n1uv9cy/ohyh/hCi1r84qIL2qiNlZbtwtCGAAAQM5oFOxIi0bBLlx9t7ZW5w69PRycZ7v+6kh/ZqNhhDCsZ14hbHl52VVPngx22qNRIcgfiVIAEhZ4hB+a9NifX2od/qiVP9JloU6Pbd0WsqSWs/nTAc0MLReh1RMnkjZvB4QwAACAnNEl6XVfrlDwadR7q5/V1urce0t/DM6zXfV9tYuT7fvPsA8hDOuZRwhbX193Y+WyW9m3L9hhj0Y/BEl/JMwPUP78/iiY1HO9HgpLfkALrU/odf99/ekyFPwiVG2tNlfbtxpCGAAAQM6cKQ25v9v7bDD4NOIP/vP1ZH1/vPdJ8lM80fVicN7tqCslDm581iwghGE98whhN65dczcPHgx21qNS4UYByJ4rNFngUfixAGWmQ5u0EaxQkNI0C21+IJNaRuhxKKCZWi4d/CJVba62bzWEMAAAgBz59NNP3fFTZ4Khp1Gn311M1lm6eNV98Md7f34cmne76gIdWVyuPvYQtrh6z71+fTI4LWavfnTHlW/PBacVyaxD2MpG0Bg7e9at79oV7KhHo41cWaiy53ZKoILPZqNe/nMLbba8hTrNJ2x9fgiz0GXL2nNbVj9tOS1TkBCmNh8fGEj2gVZCCAMAAMiR27dvu+d//btg4GnUzx78KVmnRr/eKl9MHmtULDTvdtVpkzdu/uV7Z1vhswcPk++n3bn7ce2VxxN7CBNPj5wMTlPIEaFpefvxnx5s+rm3qtaRdwDdTgjTfrhdqpWKW+7qCnbSo1IhRyHIDwwWfKSNcPnLSB8LVabCkmHrt5ExC2nC1u2HK39Zf72az7B1Razavlou1z5wayCEAQAA5Ii+D9aKe4P99LV3kvVpBMxeW/v8i+Q1naboz9uMumfY+eqjgLdVFL5s+a//ywvuwNHT7tKN92pTw8Qcwv72zZeSzxiaFrP2ufUzNH2rtmIdzbqdEKb97+mX+tybg+MNBbJbN264mSNHgp3z6CzQaX5Fc+bQITc/P1/bK5qHEAYAAJAj5ZGxJNhYSNmuNxYe3VjUP/1QF+YQumKiP28z6jL6Z4Ya+4+wH8LSqlN8auxSbc6/EEsI02mHhgUPjQJpNMhGvIQ/MuSPFGkenQIojc1GouxUwdB76qf/nppXr2tdPprur1PLGJqm57Y+kZ43/XsYeh9N87F15WGjIUyhK7TvKZDVG6FdXV11lVLJre3eHeyYR6dGm0IjXdi02gcqg4PJPtEKCGEAAAA5Uho+l9yDK91BbFQb9fIvxGGnJOqKif68zaiLc4Reb4XqFNtpizGEMAtE9tweWxCywOPPZ+HGwpMFKgs3Ck/+On0t9FhI03wWtiwA2XP/NXsvC2T2XOuz+e1z+etLhyix2bI2b3qb5KUuZPO17/YkI6vmk90vu+/+9NVE7Uvms6++lfwM7XOmlgmdMju1EWiWnnsu2CmPUmHfwcKWu9TdnewTrYAQBgAAkCODQ8NNXxnRwpZ/KqJp4UynK6anbcd2hjDrCL97+04UIUwhJB1UpB+OpB9MLAjZNC1vYc3mDa1TCgtrUu9h6w0tp+f+/FL4o1b+NK3LPovW7f8O/ucOBTQzvVxehvafVqn9UCNki3NzbppAgymv9PW5hYWF5O+lGQhhAAAAOVLaCGHNBhs77VBhbLNpOl0xPW27Nnoq2GanI2okwzq8Cl4+sZyOqDAi/OAhbLRK+uFGPy042eiTjS5Jrcem+6bDm9R89r7+e0ib31+3vZ+mhcKSTdPj9Pr8z+2/b9pQ8MvDUwNnklMMtW+Z2of0XUM5cun6n9XprtrHQvugafui/RPg4cOHyT5494c/DHbEceeqfUL7xn1diKQJCGEAAAA50uzpiDr9UGjEKzTdLtihKyeGpjeqRu00etcIfghTZ1enh6mjXO/iCLGEMOmHG3vsT/eDicKLhRvNnx5R0nM//Jha3kKQKWy9Ws4ClNRjYc+lP4KVDlKaJiy0CX99/udKBzRf4Qe/vGz0HwEKVv5+nA5doX1Rox3TR48GO+K4c9VImEZJm4UQBgAAkCPDldHkYhd+B7ERdSEOoRGv0HRpl64PjZQ1qgKjgmMjqINbr7MbIu8QpgBjIcUCj8KHH3SkhTILJppmwUlBxp9mz21ZX72fP03P7X3S7+G/Zp/Rntt7a3kLdfb5/c8tbFnNJ2xZPbdlpYU5fzvYtLzcTgjTd8Z0ZU6Njm11P0y+E9bdHeyM484z+U7Y6Ght72gOQhgAAECOXL5yze376a+CgWcr2k2Z6wUsu3JivaC2VXU5/fLo+WR97SSGkTAfCywKJBZKpAUTPU6HJQUZzetjy6VVQPLn9QNTOviZFuoM+4zSPovQslqH/7n997L12+f2lxX+ejWf8NeVh42GsO1SuKsjFlmd3hfxd/CSqyNu7AtcHREAAKADmLk+u+0Qpvt/ic1ORTTtlMTHzbcV9VkVHNtNDCGsWRVY/ABTT2EhCB9vViFMzM/OumuHDwc75jtSuzpgK2+ybDd9Dk2LRO0D2hdaBSEMAAAgRz766CP39qmBYOB5nFs5FdG0UxJ1WmBo+lb97e/fTj5zuyl6CLPRpNC0tApqoZEu3NwsQ5ioVipuuasr2DnHFqhgp5Gw0LQIVNtXy43dH/FxEMIAAAByZrA01PRl6rNQV3EcGCy5L754dNn7dlL0ELbZKYQhdVqh/x0sfLxZh7CVlRU3PjDg1nftCnbSo1FBxkaq/FDj8/77f3ndRqAMe73eMrohtEaEdOqg8Jexafbcp977ahl/ekSqzdX22gdaCSEMAAAgZ65cvdrU98Ky8lvPvOhGxi/UPnV7KXoIw/aadQgTN65dczcPHgx21KPQgo0fvuw1BTP/uX6mp+mnglC9ZfRcKIClX/ef2+Otvq//PDLV5mr7VkMIAwAAyBmd3vd6/9vB4BOTWZ2KKAhhWM88Qtj6+robK5fdyr59wc56 +7trIlEKOvaZQ5Y8wWeAJTTPrLeOHKT0XdjENjWZptEiP661Dr9t8pojwohxq67FSKWn7VkMIAwAAiIDScLmp+4W1W11G/0xpKJNTEQUhDOuZRwgTy8vLrnryZLDDnrt+CDI1KpbGponQ6FO9ZTS/P9Kmx7YOYUGq3jr8ZaSFR3sekdUTJ5I2bweEMAAAgAjQCNObx08GA1AMaqRubn6+9mnbDyEM65lXCBMz09Nuvrc32GnPVY0w+d/HkmKzEabNpm32ukx/d8veMx0A661D+CFM6/CDXSTeOnDAzVSrjz5vGyCEAQAARMLwuUryvatQCMpTfSaN1GU1CiYIYVjPPEPY2tqaqwwPu0/27g123nMzPcIkRfo1f5of2ixcic2WUdDyl9FjG/XyT4MUm61D89s69FP4wS4C1bbJ/eE22rpdEMIAAAAi4d69e+7MYCm5CmEoDOWhPsvxU2fcnTt/fdPhdkMIw3rmGcLE0tKSm9xspCcP09/VMhWE0mw2bSvLCP/3tnnTgWur76vwJdPL56za9oNbt2ofsj0QwgAAACJCV0qM6SIdvzrSn9xQOmsIYVjPvEOYmJ6YcIs9PcFOPBbXxd5eNz06Wmvl9kEIAwAAiIyx8xdc7yu/C4aiLP3JS6+54cpopqchGoQwrGcMIez+/fvJ57i/Z0+wM4/FU22ZtKmdYtlGCGEAAACRodBzbmQ013uH6b2z/h6YDyEM6xlDCBMLCwtu+ujRYIcei+eVvj63ODdXa932QggDAACIkIcPHyZB7D9efi0Yktrp87/+3UYAO5d8hrwghGE9YwlhYmp83C11dwc79Vgc1YZTGZyGaBDCAAAAIkWjUDo18fCbbwXDUqvVRTj0HbC8TkH0IYRhPWMKYaurq4+upLd7d7Bzj/GrtlMbqi2zghAGAAAQObowxjsDg+6fnn05GJ5aoW7G/IcTA+7ylWu5BzBBCMN6xhTCxPzsrLt2+HCwg4/xq7ZTG2YJIQwAAKAA6GbO+o6Wbuj89R88HwxS21HhSyNtZ4fKyXvEAiEM6xlbCBPVSsUtd3UFO/kYr2qzarlca8XsIIQBAAAUiNu3b7vBoWH3mzfeSkbGtnNPMS2jGzD/9vdvu9LGuubm56MY/fIhhGE9YwxhKysrbnxgwK3v2hXs7GN8qq3UZmq7rCGEAQAAFBDdPHn0wsWkM6ow9a//eSgJVhrZ+ru9z/45bOmxRs40TVc87H/nlBsYLCXfNdM6YgtfBiEM6xljCBM3rl1zNw8eDHb4MT7VVmqzPCCEAQAAFBydRnjr1i1XHhlzpXIlGSk79MYxN1gaSh7rVMPz1YvJd8vu3bsXbfDyIYRhPWMNYevr626sXHYr+/YFO/0Yj2qjsVIpabM8iD6E2Y3wsHmzuPFcLHz++efJf3hHJqru7Mg5NzAc3iYYt2q30uiIOz81mbSn2nWnQO1rnTup9vk82f2y++xBfpeYbxa1XajzjSi1f8TK8vKyq548Gez4YzxWT5xI2iovog9h0xMTbrG3N7jxcOsu9vS46QsXalu1c1Fnq3r5khvc6Lz/9J3fu6++st995cUfuy//7Cn3pUARx3hVe6nd1H5qx387dsSdHSol7bsTOtXUvta4U2pfmndv30lORzw1dqn2SvEghGE9Yw5hYmZ62s1Tw6P11oEDbqZarbVWPkQdwpaWltzkW28FNx427mR/f7JNO5Wr12fcmY1O+jeOvLzRgf9OsGhjsVW7/v1vX0za+caNG7WW7zyofa2102tfiDcHx5MQ9vRLfbVXigchDOsZewhbW1tzleFh98nevcG6hPmpNknu67bRRnkSbQhLdt6NPzB23taZ7HQb2zTvna7V6BS1SvW86z7e5/7m+X8OFmvsLNXOXcdeT9q9005RpPa13k6tffVQ+FII+9p3e2qvFA9CGNYz9hAmkn+o9fcH6xLm59SxY+6DW7dqrZQf0YawmampZKgwtPFw+ybDrxvbtlNQB3xopOJ29/0qWKSxs33itV8k7d9JQYza1x47rfbVQ98DU/hSCJOXbrxXm1Is1MnmNHIMqf2iCCFMJKeW9/QE6xJmr07znx4drbVOvkQZwvhCY3vN+4uIrUQjIU8SwHa0SRA7P1bbI4oNta+9dlLtq8fIpet/DmDy2Vffqk0pFrowj74XGvq7x52t9ovTw6XanhI3dpGl+3v2BOsSZqfaIGmLSL5XHl0I49Ke7Te5JOfGNs7rkpytQt8B63n7zWCBxp2lTk3U/lBkqH3tt1Nq3+OwUxHNop6SqCvb6sI8ob953NlqvzhdKdf2lPhZWFhw00ePBusSZueVvj63ODdXa5X8iS6EcZO7bMzz5nStQP/F0MUZ+A4YSu0HAxv7Q5Gvmkjty8ai176t8PV/eeGvQpi8c/fj2tTiMDV9ObkyauhvHne22i90C5oiMTU+7pa6u4N1Cduvtv1UJKchGlGFsJWVFTd29qxb37UruAGxdWobjw8MJNu8iOgy5boKYqg4485UV03UflFEqH3ZWfTa9zjs0vRpdbXEoqF7A/YcPxr8e8edrW5Zov2jSKyurj66It/u3cHahO1T21zbXm0QE1GFsGql4pa7uoIbEFuvtnW1XJzhfEMXYdB9wLgMPfpqfzizUWSLeJEOal+2FrX2bYVDbw8HQ9h3f/pqbY7ioL9l3RuQWo++2h+0XxSx1s/Pzrprhw8H6xK2T21zbfvYiCaEaePMHDkS3HjYPmcOHXLz8/O1VigG+u/Xs/x3FAM+U8D/jlL78rGItW8rPNn9cjCESV01sWhcmp5ORrlDf++4M9X+MHTxfG0PKR780y1bY/6nWxQhjCHa/EyGaAcHoxuirYfOA+d7AhhS+8X5qcnanhI/1L78LGLt2wq6HL08cPR0Erx0kQ57rYghTN/z1Pc9+f4vSu0Hp0uDhf7+r06F1inRnH7efmM//TyKEJZ8WfG554IbENtv8mXFjTYoClwxCzdT+8WJc8W4d4yg9uVr0WpfI5wau5SEsKJent5HVz7VzfhDf/O4s+yEK+EKLsSUjbFfiCn3EKZLRU5zN/Hc1WU7dQnVIsC9Y3Azi3TvGGpfHBap9jVCJ4UwoXsB6p6Aob973BnqnqADYyO1PaLYcEuS9pvckqRUivqWJLmGMA0ncwO7OIztBnb10OfU3fJDRRp3ttovtH/EDrUvHotU+xqh00KYLsIwNFIhiO1Qd28EsDPnhgt5MY7N4Ob87bUIN+fPNYRNT0y4xd7e4MbD7F3s6XHTFy7UWide1GEKFWlEWYQQRu2Ly6LUvkbotBAm1AGvVM8np6TxHbGdodpZ7a0RsE4KYMbM9LSb51jQcm8dOOBmqvHfRy63ELa0tOQm39o4OAQ2HubnZH9/0jYxQwjDesYewqh9cVqE2tcInRjCDH0nSBfr0FXyuHx9Z6p2VfueKg26iatXai3feaytrbnK8LD7ZO/eYF3CxtW2TC54tbFtYyeXEJbsdBsdJXa6+Ex23o22iXnnJYRhPWMOYdS+eC1C7WuETg5hQqePjkxeTO4X1fX715Iro+rCPPpeKKerF0u1l9pN7ad21K1GdM9HtW+nnSYcQv/8mTp2LFiXsHG1LT+4dau2deMmlxA2MzWVDBWGNh7mbzKMu9FGsUIIw3rGHMKofXEbe+1rhE4PYYZOUdO9AYeq4+50pZxcmEc1AIulLrilK9vqFjRziwsdeephPZJT1Ht6gnUJt65O858eHa1t1fjJPITxRcRiGPMXGlWwQ51vRKn9I0aofcWwCF/m3go7JYQBdAJ2sSZs3iKNnmYawrgkZ3FMLu250VYxXtpTf2Shzjei1P4RG9S+4hhz7WsEQhgAQNxkGsK4OV2xjPUmd4QwrGeMIYzaVyxjv8HnViCEAQDETWYhbGVlxY2dPevWd+0KHvQwPtVW4wMDSdvFBCEM6xlbCKP2Fc9Ya18jEMIAAOImsxBWrVTccldX8ICH8ao2q5bLtVaMA0IY1jO2EEbtK6Yx1r5GIIQBAMRNJiFsfnbWzRw5EjzQYfzOHDrk5ufna62ZP4QwrGdMIYzaV2xjq32NQAgDAIibtoew1dXVRzdN2707eJDD+FXbVQYHk7aMAUIY1jOWEEbtK76x1b5GIIQBAMRN20PY1Pi4W3ruueABDovjUnd30pYxQAjDesYSwqh9nWFMta8RCGEAAHHT1hC2ODfnpvv7gwc2LJ5X+vrcwsJCrXXzgxCG9YwhhFH7OstYal8jEMIAAOKmbSHMbjx3f8+e4EENi6faMmnTnG+ERwjDeuYdwqh9nWcsta8RCGEAAHHTthA2PTHhFnt7gwe03Hz/fedmZ8PTOlH9rvqdQ9O26WJPj5u+cKHWyvlACNu+5dtz7upHd4LTpPjbN18KTiuKeYewKGtflnZonY2h9jUCIQwAIG7aEsKWlpbc5FsbhT9wIMtV/Rez2VOEhL8O+67A/v1/PV8M6h43+nyhaU04ufH7q43zghC2fRdX77nXr08Gpz09cjLZvqFpRTLPEBZt7cvSVtRZraMNtatZ8659jUAIAwCIm5aHsLW1NVfZ6AR9sndv8CCWmwpJopmwZOsITYtR0WxnKKDaVm2sts4DQtj2FQpboWkKZwppoWlFMq8QFm3ty9JW1FnZinW0wbxrXyMQwgAA4qblIWxmasrdOnAgeACrq53CotEbww7CChJ6XfMIO9VFr/ukT4Hxz9/XND3X66Ewlf7Pq4/m1/I++jyaTz/9903P54cgew/DPk9I+4yGf1qh3sN+H2Hv4W87+xybrc//zMI+l/1ej1FtrLbOg6KEMAUaQ6cBCpv28Z8eJM+FvabTAI10GPLn96fZyJaPvW5Y6LL124iX8Nel0xT9UxXT690svMVmXiFs27UvS+vVWf1UTbHaYTWnnXXWX1bv49dHYeuKyDxrXyMQwgAA4qalIWx5edlVT2508AIHrsdqB2M/UFgnwDoF/sHfDtbWgbCOgj3X+mx56wzYcy2bPrgLW1bYe2m9Fky0vK3DFPaZ +Nc1fb6hDImy68Dskpv0utl5b1p5bB8qe22v2OaWw5+n12XP/sb/sFq2eOJG0edYUIYQp3PgBRyHKnvthR8HIHmseO1VQP+2xUIjTY3tugciw73EZtqze09Zvoco+hx/KbF5bLh0a9dz/fWI2jxDWVO3L0np11mqqX+PaWWfTy9q8qpvbqEdZmlftawRCGABA3LQshK2vr7uxctmt7NsXPGg9VuEHEh2c7UDsPzZ1wE4HGKFOgnUc/Gla3oKV1mcHf+mHknodAH8d0jod+uk/tun+etOdFyn0uj030+8j/d9Xj/3poXX7v2N6fXpsHZ7Qttqiamu1udo+S2IPYTbSZMFI+sFLYSYUaIQftmQ6/PjrTocoKfx1aFl7rp8KejZNCj/s+eHOX6/WY58/drMOYU3XviwVm9VZvy6Y7aqzWjb9XmZ6uQjNq/Y1AiEMACBuWhbCbly75m4ePBg8YD1W/+Bs6mBuB+J0RyAUOiwEaVroIG7T9DgUSqwjovfyp/n665B+RyLUgfE7Kf57SPu8/u/gv+6/jxRaX2i59Lqlv83S+J+zyQ6P2lxtnyWxh7BQ2PFHuaThByYLWMICkMJPGgt3Wp//PhbK/PCn6f66/PfzQ5y9t173P4dRlAAmsw5hTdW+LLW66b/m19l0XbT5/Vrj16dm6qz/vmn92hWxedS+RiCEAQDETUtC2MrGAXXs7Fm3vmtX8GD1WHXAtYOzKfwQ4XcEQp0JzWvhIn2A1zRh6xDWUZBazjoLm3UArPPhv6Zl7H38Dobpd1L00++Q+J/X195ns99Xj9PLad3+e9v8+hlan6+WC/2+W1RtPj4wsLGajfVkROwhTIElNHplYSj9uh+apB/i0uHNV/P54ehxocwPZDa/sMf2mdPrKZpZhrCma1+W6u88XaOE/f2rrvh10a87pl+3tC6rbzZNWK0R/vq0nNVALevXQ1+xWb2KyDxqXyMQwgAA4qYlIaxaqbjlrq7ggWpL6kAu/Od2oA91BCxY2AHenltnwg8ltrwfXIQtawdQvyPidyzssXUw7HXpdyTS09MdEq3X3kNqOf99fIU/r7D30U/73Uy9Zr+fbQvhP/c7Q771pm1RtX21XH60rgwo0kiYBSGh5wo6For8EOSHHj/E6XV/9Mo3PbKlx+nwl/4cfmgTtrxet2n+5yqiWYawpmtflqreCP95um5YvfJfa0ed1XO/jlkttPX4nyNis659jUAIAwCIm6ZD2K0bN9zMkSPBA9SWteBj+AfyUOiw1338IGGdBaF16cBvB3npv5emaR476FsnwPA7A4YFIuG/r3U0DHvdPo+/Ls1r60mrz+RjHRe52XI++kz+NktvK9u+9rvafE04c+iQm5+ff7S+BlFn4dKN92rPHk/sIUz6KAxZOPJDmUgHMuEHMhst87FlhD+yVS+U2UiXNPx59Z6ax5778wk/vMVuoyGs0f3PaEnty9J6ddbqoD+/bFed9ZcV/no1n/DXFbHN1L52QggDAIibpkLY6uqqq5RKbm337uDBacsKP6Bg4dQ+UBkcTPaJRvnuT19NOgvy6Zf6ks7DZw8e1qb+T4oQwjA/Gw1hje5/omW1L0sFdbblNlP72gkhDAAgbpoKYVPj427pueeCB6Ytq/+Ahv4Di4Vzqbs72Scaxe8E+6pDfOjtYffu7Tu1OR9BCMN6NhPCtrL/iZbUviylzrbV7da+dkIIAwCIm22HsMW5OTftn0KyXXW6S+h0QyykV/r6/kdnthV+7bs97sDR08lpY4QwrGdo/2lWf/9rWe3LUups21Xt+49fH032kxjUPxG07xLCAADiZFsh7MGDB0lH+O4Pfxg8GOHOVftEugPbCtUJtlPFTg2cCXa+EWVo/2lW2/+Ol6vJ/kftw7Ttqn3NqkAGAADxse2RsIWFBTd99GjwYIQ7V/03WCMFjbDZ6WBPdr/859PB/O/oMBKG9WzV6Yib7X/UPgyp2verN064NwfHo/LO3Y9rey4AAMRE898J6+4OHpBw55l8L2J0tLZ3bB3rBGu0QY83+x6OQQjDem43hG11/xPUPvTdbu0DAICdS1MhrJBXCMO2mFwhbGNf2M4VwtTp3coV6QxCGNaz0RDW6P4nqH1oNlP7AABg59JUCBPzs7Pu2uHDwYMTbkNRwMtIax/QvpAFhLD6+jdp3ok2GsK2C7XPU1de3MrFSuz+YKFpUvcGUx0JTYvULGsfAAB0Dk2HMFGtVNxyV1fwAFUYdeWwvK8eVtDLSKvtq+VybW9oP4Sw+uomzM3eXNm/0XPRzCqEiY6ofdvRQoceW7Dayj+PdBn3enVW9U/zhKZFaNa1DwAAOoeWhLCVjYPq+MCAW9+1K3igwi2qjk3BLiOtNlfbax/ICkJYfRWeFKJC07aqQlyz68jLLEMYtW/DRv55pJEuGZomRUHOBMij9gEAQOfQkhAmbly75m4ePBg8WEVv+j+5/qkl/n9l1dEw7DXN63cq1CHxp9u6Dc2fnldo3QU8FUdtrrbPkiKHMDtV8PXrk7Xfxv1V2FGA8qf5r/vY61LLGwpPWr/ex5bT+vx5/RGu9LJ6LY2tqyhmGcJE9LXPDwlW2+z1UD2y56pHhh6rRlmN9EestA6ty5bT64bVNZtX8+mxX0ttnen3lz5+nY3APGofAAB0Di0LYevr626sXHYr+/YFD1hRa50CPU53BKxzoQ6AdQLUabDH6Y6M1mXL2Lr0038emmadI3teANXWY6VS0vZZUuQQZqHHAo8FLptu2HOpUOWfXqgQZc9tff40/7nwQ5SW0zJ6HFpW8/7tmy8lr+unTSuSWYewqGufapHVI6k6F6pp6ef6aTVRahl7bv9YsvCkea0GWgCzaVbX7Llhz7Vee0+/dtp76DX/uS2Xs3nVPgAA6BxaFsLE8vKyq548GTxoRa3/n9x0J8LUdJvHV/jBye/IaH4/oOmxdWQ0zeaTkXUytmL1xImkzbOmyCFMIcgfiVLoEQo8Fn780KSQlr7IhsKTrUP4I13+/LZumyZtFE6Phf9eZmi5Ipl1CBNR1j77R49fU/z65Nc9KbSM1SK/rvnz2nptmmqahSU99mueP29ovfostl7/s/mPpdVle56zedU+AADoHFoawsTM9LSb7+0NHriiNR2WdPAX/n+CpWHzhoKT3yFJ469P+J0RLZN+v4i9deCAm6lWH/0eGVPkEOaHIKnHwh6nA5c/6mVakAuFJU2z+dPr80e4/PdN64e8IppHCBPR1T7VqXRN8euTX3P8kBUKPH6N9Of1a2AoZKXXm/48mmZhy/9sepzGXy5H86x9AADQObQ8hK2trbnK8LD7ZO/e4AEsSnXA9zsO/uvW8TDtP7vqcKQ7Ff40v3PiLy9DnRV1RqyzErlq2+QeSRttnQdFDmHCP83PHxlT+EkHLk2z0wdNC3KhICVsfj+QSb1uoSwU+Ewtk37PIplXCIuu9inc+DXF6pPVHatDeizsddU8v67ZfBaQtF6ri1rG5rX1+zVP0yxkaRl7bApbr7BlhX2eiMy79gEAQOfQ8hAmlpaW3GSEB9Cg1sHQT3UG/NAl9Jo6MtY50HNhj60DYusR/vPNtoOwzoc6JiId+CJVbfvBrVuPPnMOFDWE2ciVApD/3E4JDAUuP6TZcwtPtryFOr0ubH1+CLPAZuuy57asnttyWg8hbHtEVfv8MJWuT6bwg5L0a5zNI6wGan6rXXoPC3rpmqfXhc1rz/VY6j3t82kZf5qw5SIy79oHAACdQ1tCmJiemHCLPT3BA1lU6kBvHQFpHQVhocjvwAjrjEgfdSSsQyK1vI//Pv4068jE0nmr42Jvr5seHa198HwoaghTsFEIsrAkLPjI9HP/dcMPZFLPDQtlNs2eC82n9/fDlb+shTWpeQx7rUjmGcJEVLXPJ12fpGqSX5f81w0tZ/NYLbQaqPVZnZT2DyVhtdXmFX7d89/XaqA917JpbFpOxlD7AACgc2hbCLu/cYBVZ+j+nj3BAxoWT7Vl0qZ+By0HihrCFHSKPMJUFPMOYdS+zjOW2gcAAJ1D20KYWFhYcNNHjwYPalg8r/T1ucW5v4yS5EVRQ5hGwEIjXdha8w5hgtrXWcZS+wAAoHNoawgTU+Pjbqm7O3hgw+KoNpyK5FScIoYw/8qEoenYOmMIYYLa1xnGVPsAAKBzaHsIW11dfXQ1qd27gwc4jF+1ndpQbRkDRR0Jw2yMJYRR+4pvbLUPAAA6h7aHMDE/O+uuHT4cPMhh/Krt1IaxQAjDesYSwgS1r9jGVvsAAKBzyCSEiWql4pa7uoIHOoxXtVm1XK61YhwQwrCeMYUwQe0rpjHWPgAA6BwyC2ErKytufGDAre/aFTzgYXyqrdRmaruYIIRhPWMLYdS+4hlr7QMAgM4hsxAmbly75m4ePBg86GF8qq3UZrFBCMN6xhbCBLWvWMZa+wAAoHPINIStr6+7sXLZrezbFzzwYTyqjcZKpaTNYoMQhvWMMYRR+4pjzLUPAAA6h0xDmFheXnbVkyeDBz+Mx+qJE0lbxQghDOsZYwgT1L5iGHPtAwCAziHzECZmpqfdfG9v8ACI+XvrwAE3U63WWis+CGFYz1hDmKD2xW3stQ8AADqHXELY2tqaqwwPu0/27g0eCDE/1SbJvY022ihWCGFYz5hDGLUvXotQ+wAAoHPIJYSJpaUlN9nfHzwYYn5OHTvmPrh1q9ZKcUIIw3rGHMIEtS9Oi1D7AACgc8gthInpiQm32NMTPCBi9i729rrp0dFa68QLIQzrGXsIE9S+uCxK7QMAgM4h1xB2//79pMN0f8+e4IERs1NtkLTFRpvEjj7nlwKdb0TtF0UIYdS+eCxS7QMAgM4h1xAmFhYW3PTRo8GDI2bnlb4+tzg3V2uVuBkYHnJf/tlTwU447my1X5weLtX2lLih9sVhkWofAAB0DrmHMDE1Pu6WuruDB0hsv9r2UwU6FefsyDn3lRd/HOyE485W+8XpSrm2p8QPtS9fi1b7AACgc4gihK2urj66KtXu +3cEDJbZPbXNte7VBUZiavuy++sr+YCccd7baL0YminOJcWpffhax9gEAQOcQRQgT87Oz7trhw8GDJbZPbXNt+yJx584d13P8aLATjjvbfzt2JNk/igS1Lx+LWPsAAKBziCaEiWql4pa7uoIHTGy92tbVcnFO3TI+//xzd3ao5L7U851gRxx3ptoftF9o/yga1L5sLWrtAwCAziGqELaysuLGBwbc+q5dwQMntk5tY21rbfMicml62v39b18MdsZxZ6r9Yeji+doeUiyofdlZ9NoHAACdQVQhTNy4ds3dPHgwePDE1qltrG1dVHQ56YGhkvub5/852CHHnaX2g9OlwUJfZpzal41Fr30AANAZRBfC1tfX3Vi57Fb27QseQLF5tW3HSqVkWxeZq9dnXPfxvmCnHHeWXcdeT/aHIkPta7+dUvsAAKD4RBfCxPLysquePBk8iGLzVk+cSLZxJzB0fsw98dovgh1z3Bk+2fcrNzA2Utsjig21r712Uu0DAIBiE2UIEzPT026+tzd4IMXte+vAATdTLc4lvB+HLsIwNFIhiO1Qd28EsDPnhgt5MY7NoPa1x06rfQAAUGyiDWFra2uuMjzsPtm7N3hAxcbVtkzuSbSxbTsJdcAr1fPJKWl8R2xnqHZWe2sErJMCmKD2td5OrX0AAFBcog1hYmlpyU0dOxY8qGLjalt+cOtWbet2HvpOkC7Woavkcfn6zlTtqvY9VRp0E1ev1Fq+86D2tdZOr30AAFA8og5hYnpiwi329AQPrLh1F3t73fToaG2rdi66Ot7I5MXkflFdv3/NffWV/e4rL/7YfflnT2104MMde4xTtZfaTe2ndnzm2BF3plRK2rfIV0HcKtS+1rhTah8AABSL6EOYOltDQ0PYAndCx9XQKWp37txxQ9Vxd7pSdqeHS8FtgnE7MDzkTpwbciMTVTe3uNBxpx7Wg9rXOndS7QMAgGIQfQgDAAAAAADoJAhhAAAAAAAAGUIIAwAAAAAAyBBCGAAAAAAAQIYQwgAAAAAAADKEEAYAAAAAAJAhhDAAAAAAAIAMIYQBAAAAAABkCCEMAAAAAAAgQwhhAAAAAAAAGUIIAwAAAAAAyBBCGAAAAAAAQIYQwgAAAAAAADKEEAYAAAAAAJAhhDAAAAAAAIDMcO7/AyPAeqvrj91cAAAAAElFTkSuQmCC +", extent = {{-78.257, -39.233}, {78.257, 39.233}}), Line(visible = true, origin = {46.667, -25}, points = {{-186.667, 0}, {93.333, 0}, {93.333, 0}}, color = {76, 112, 136}, thickness = 1), Text(visible = true, origin = {101.715, -30.5}, textColor = {76, 112, 136}, extent = {{-38.285, -10.5}, {38.285, 10.5}}, textString = "Event-driven Process Chain", fontName = "Lato", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {-76.8, -75}, textColor = {76, 112, 136}, extent = {{-28.2, -2}, {28.2, 2}}, textString = "Cloud within producing", fontName = "Lato"), Text(visible = true, origin = {-17.6, -75}, textColor = {76, 112, 136}, extent = {{-11.4, -2}, {11.4, 2}}, textString = "inventory", fontName = "Lato"), Text(visible = true, origin = {50.58, -62}, textColor = {76, 112, 136}, extent = {{-12.58, -2}, {12.58, 2}}, textString = "installedBase", fontName = "Lato")})); +end SimpleProductionChain; diff --git a/BusinessSimulation/Examples/SimpleProductionChainII.mo b/BusinessSimulation/Examples/SimpleProductionChainII.mo new file mode 100644 index 0000000..7b81658 --- /dev/null +++ b/BusinessSimulation/Examples/SimpleProductionChainII.mo @@ -0,0 +1,63 @@ +within BusinessSimulation.Examples; + +model SimpleProductionChainII "Extending the first example to include replacement purchases" + extends Icons.Example; + ModelOutput modelOutput "Main output for the model" annotation(Placement(visible = true, transformation(origin = {130, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {90, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + inner ModelSettings modelSettings(modelDisplayTimeBase = BusinessSimulation.Types.TimeBases.months, dt(displayUnit = "mo") = 657000, modelTimeHorizon(displayUnit = "mo") = 157680000) annotation(Placement(visible = true, transformation(origin = {-135, -75}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + + expandable connector ModelOutput "Main output for the model" + import BusinessSimulation.Units.{Amount,Rate}; + extends Icons.DataOutPort; + Amount inventory "Finished goods inventory"; + Amount installedBase "Installed base for the product"; + Rate producing "Rate of production"; + Rate shipping "Rate of shipping to customers"; + Rate scrapping "Rate of scrapping at the end of useful life"; + end ModelOutput; +protected + Stocks.MaterialStock inventory(initialValue = 0, redeclare replaceable type OutputType = Units.Amount) "Finished goods inventory" annotation(Placement(visible = true, transformation(origin = {-50, -10}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Flows.Unidirectional.Transition shipping(hasConstantRate = false, rate(displayUnit = "1/mo") = 3.80517503805175e-06, redeclare replaceable type OutputType = Units.Rate) "Shippment to the customer at an exogenous rate" annotation(Placement(visible = true, transformation(origin = {-10, -10}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + SourcesOrSinks.Growth producing(hasConstantRate = false, rate(displayUnit = "1/mo") = 3.80517503805175e-05) "Production at a constant rate" annotation(Placement(visible = true, transformation(origin = {-90, -10}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Stocks.DelayN installedBase(hasConstantDelayTime = false, n = 4, delayTime(displayUnit = "yr") = 157680000, initialValue = 0, redeclare replaceable type OutputType = Units.Amount) "Product stays in use for around 5 years" annotation(Placement(visible = true, transformation(origin = {30, -10}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Flows.Unidirectional.OutflowDynamicStock scrapping "After its useful life has expired, products will be discarded" annotation(Placement(visible = true, transformation(origin = {70, -10}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + InformationSources.RampInput firstTimePurchases(redeclare replaceable type OutputType = Units.Rate, offset(displayUnit = "1/mo") = 3.80517503805175e-06, height(displayUnit = "1/mo") = 3.42465753424658e-05, startTime(displayUnit = "mo") = 15768000, duration(displayUnit = "mo") = 47304000) "Ramping up from 10 to 100 units per month starting at 6 mo for 18 mo" annotation(Placement(visible = true, transformation(origin = {-65, 45}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ConstantConverterTime usefulLife(value(displayUnit = "yr") = 157680000) "Average time a product remains in use" annotation(Placement(visible = true, transformation(origin = {10, 20}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Add_2 shippingRate(redeclare replaceable type OutputType = Units.Rate) "The total rate of material that is being shipped to customers" annotation(Placement(visible = true, transformation(origin = {-15, 22.729}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + MoleculesOfStructure.Policy.FirstOrderStockAdjustment productionRate(adjTime(displayUnit = "mo") = 2628000, hasConstantAdjTime = true) annotation(Placement(visible = true, transformation(origin = {-90, -50}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Converters.ConstantConverter desiredInventory(value = 100) "The constant level of inventory we wich to maintain" annotation(Placement(visible = true, transformation(origin = {-50, -50}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + SourcesOrSinks.Cloud cloud1 annotation(Placement(visible = true, transformation(origin = {110, -10}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); +equation + connect(inventory.outflow, shipping.portA) annotation(Line(visible = true, origin = {-30, -10}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(shipping.portB, installedBase.inflow) annotation(Line(visible = true, origin = {10, -10}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(producing.massPort, inventory.inflow) annotation(Line(visible = true, origin = {-70, -10}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(installedBase.outflow, scrapping.portA) annotation(Line(visible = true, origin = {50, -10}, points = {{-10, 0}, {10, 0}}, color = {255, 0, 0})); + connect(scrapping.portB, cloud1.massPort) annotation(Line(visible = true, origin = {90, -10}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(usefulLife.y, installedBase.u) annotation(Line(visible = true, origin = {22, 13.333}, points = {{-6, 6.667}, {3, 6.667}, {3, -13.333}}, color = {1, 37, 163})); + connect(firstTimePurchases.y, shippingRate.u2) annotation(Line(visible = true, origin = {-32.333, 40.243}, points = {{-24.667, 4.757}, {12.333, 4.757}, {12.333, -9.514}}, color = {1, 37, 163})); + connect(shippingRate.y, shipping.u) annotation(Line(visible = true, origin = {-15, 7.365}, points = {{0, 7.365}, {0, -7.365}}, color = {1, 37, 163})); + connect(scrapping.y, shippingRate.u1) annotation(Line(visible = true, origin = {32.5, 30.282}, points = {{42.5, -29.882}, {42.5, 14.718}, {-42.5, 14.718}, {-42.5, 0.447}}, color = {1, 37, 163})); + connect(desiredInventory.y, productionRate.u_reference) annotation(Line(visible = true, origin = {-67.5, -50}, points = {{11.5, 0}, {-11.5, 0}}, color = {1, 37, 163})); + connect(shipping.y2, productionRate.u_outflow) annotation(Line(visible = true, origin = {-54.1, -25.8}, points = {{33.6, 10.8}, {24.1, 10.8}, {24.1, -4.2}, {-40.9, -4.2}, {-40.9, -13.2}}, color = {1, 37, 163})); + connect(inventory.y2, productionRate.u_current) annotation(Line(visible = true, origin = {-74.1, -27.8}, points = {{13.6, 12.8}, {4.1, 12.8}, {4.1, -7.2}, {-10.9, -7.2}, {-10.9, -11.2}}, color = {1, 37, 163})); + connect(productionRate.y, producing.u) annotation(Line(visible = true, origin = {-106.2, -16}, points = {{5.2, -34}, {-13.8, -34}, {-13.8, 26}, {11.2, 26}, {11.2, 16}}, color = {1, 37, 163})); + connect(producing.y1, modelOutput.producing) annotation(Line(visible = true, origin = {-24.875, -27.5}, points = {{-54.625, 12.5}, {-50.125, 12.5}, {-50.125, -12.5}, {154.875, -12.5}}, color = {192, 192, 192})); + connect(shipping.y1, modelOutput.shipping) annotation(Line(visible = true, origin = {35.125, -27.5}, points = {{-34.625, 12.5}, {-30.125, 12.5}, {-30.125, -12.5}, {94.875, -12.5}}, color = {192, 192, 192})); + connect(inventory.y1, modelOutput.inventory) annotation(Line(visible = true, origin = {5.125, -27.5}, points = {{-44.625, 12.5}, {-40.125, 12.5}, {-40.125, -12.5}, {124.875, -12.5}}, color = {192, 192, 192})); + connect(scrapping.y1, modelOutput.scrapping) annotation(Line(visible = true, origin = {95.125, -27.5}, points = {{-14.625, 12.5}, {-10.125, 12.5}, {-10.125, -12.5}, {34.875, -12.5}}, color = {192, 192, 192})); + connect(installedBase.y1, modelOutput.installedBase) annotation(Line(visible = true, origin = {65.125, -27.5}, points = {{-24.625, 12.5}, {-20.125, 12.5}, {-20.125, -12.5}, {64.875, -12.5}}, color = {192, 192, 192})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

In this model we extend the introductory example →SimpleProductionChain by including the rate of scrapping in determining the rate of shipping. We simply assume, that whatever is scrapped will immediately be replaced by a new product.

+

Since this introduces some variation in the rate of shipping, we need to have an adequate policy to determine the production rate. In this case we make use of a policy component called →FirstOrderStockAdjustment that can be found in the package. It simply determines the rate of inflow needed to keep a stock at a desired level, given the current amount in the stock and the (perceived) rate of outflow from the stock.

+

Here we would like to keep the inventory at a desired level of 100 units. 

+
Model Output
+ +

See also

+

+Tutorial.StrategicBusinessSimulation, +SimpleProductionChainSimpleProductionChainIII

+"), experiment(StartTime = 0, StopTime = 157680000, __Wolfram_DisplayTimeUnit = "mo"), __Wolfram(PlotSet(plots = {Plot(name = "Stocks", identifier = "stocks", subPlots = {SubPlot(curves = {Curve(x = time, y = modelOutput.inventory), Curve(x = time, y = modelOutput.installedBase)})}), Plot(name = "Flows", identifier = "flows", preferred = true, caption = "The production rate quickly tracks the shipping rate once inventory is filled to 100 units. Two years into the simulation shipping is \"moulded\" by replacement purchases.", subPlots = {SubPlot(curves = {Curve(x = time, y = modelOutput.producing), Curve(x = time, y = modelOutput.scrapping), Curve(x = time, y = modelOutput.shipping)}, range = Range(yunit = "1/mo"))})})), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}), graphics = {Text(visible = true, origin = {0, 65}, textColor = {76, 112, 136}, extent = {{-140, -6}, {140, 6}}, textString = "Simple Production Chain II", fontName = "Lato Black", textStyle = {TextStyle.Bold})})); +end SimpleProductionChainII; diff --git a/BusinessSimulation/Examples/SimpleProductionChainIII.mo b/BusinessSimulation/Examples/SimpleProductionChainIII.mo new file mode 100644 index 0000000..cfd29d5 --- /dev/null +++ b/BusinessSimulation/Examples/SimpleProductionChainIII.mo @@ -0,0 +1,73 @@ +within BusinessSimulation.Examples; + +model SimpleProductionChainIII "Further extending the first example to explain new product diffusion" + import BusinessSimulation.Units.{Amount,Rate}; + extends Icons.Example; + ModelOutput modelOutput annotation(Placement(visible = true, transformation(origin = {135, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {90, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + inner ModelSettings modelSettings(modelDisplayTimeBase = BusinessSimulation.Types.TimeBases.months, dt(displayUnit = "mo") = 657000, modelTimeHorizon(displayUnit = "mo") = 315360000) annotation(Placement(visible = true, transformation(origin = {-135, -75}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + + expandable connector ModelOutput + extends Icons.DataOutPort; + // stocks + Amount customers "Customers"; + Amount potentialCustomers "Potential customers"; + Amount installedBase "Installed base"; + Amount inventory "Finished goods in stock"; + // rates + Rate producing(displayUnit = "1/mo") "Production rate"; + Rate shipping(displayUnit = "1/mo") "Shipping rate"; + Rate scrapping(displayUnit = "1/mo") "Scrapping rate"; + end ModelOutput; +protected + Stocks.MaterialStock inventory(initialValue = 100, hasStockInfoOutput = false) "Finished goods inventory" annotation(Placement(visible = true, transformation(origin = {-50, -30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Flows.Unidirectional.Transition shipping(hasConstantRate = false, rate = 0, redeclare replaceable type OutputType = Units.Rate) "Shipments to the customers" annotation(Placement(visible = true, transformation(origin = {-10, -30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + SourcesOrSinks.Growth producing(hasConstantRate = false, rate = 100, redeclare replaceable type OutputType = Units.Rate) "Production of a durable good" annotation(Placement(visible = true, transformation(origin = {-90, -30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Stocks.DelayN installedBase(hasConstantDelayTime = true, n = 4, delayTime(displayUnit = "mo") = 157680000) "Products in use" annotation(Placement(visible = true, transformation(origin = {30, -30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Flows.Unidirectional.OutflowDynamicStock scrapping(redeclare replaceable type OutputType = Units.Rate) "Discarding of products (which will be replaced by new ones)" annotation(Placement(visible = true, transformation(origin = {70, -30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + SourcesOrSinks.Cloud cloud1 annotation(Placement(visible = true, transformation(origin = {110, -30}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Converters.Add_2 totalOrders(redeclare replaceable type OutputType = Units.Rate) annotation(Placement(visible = true, transformation(origin = {10, 0}, extent = {{-10, -10}, {10, 10}}, rotation = -900))); + Stocks.MaterialStock potCustomers(initialValue(displayUnit = "each") = 250000) "Potential customers" annotation(Placement(visible = true, transformation(origin = {-90, 30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + MoleculesOfStructure.Actuators.Diffusion wordOfMouth(hasConstantOtherAdopters = true, hasConstantOtherPopulation = true, hasConstantContactRate = true, nextStageIsInfluencing = true, hasConstantAdoptionFraction = true, adoptionFraction = 0.02, contactRate(displayUnit = "1/mo") = 3.80517503805175e-06, hasConstantFractionalAdoptionRate = true, fractionalAdoptionRate(unit = "1/mo") = 0) "Bass diffusion model for a word-of-mouth process" annotation(Placement(visible = true, transformation(origin = {-50, 30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Stocks.MaterialStock customers(initialValue = 10) "Initial customers (early adopters)" annotation(Placement(visible = true, transformation(origin = {-10, 30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + MoleculesOfStructure.Policy.FirstOrderStockAdjustment productionPlanning(hasConstantAdjTime = true, adjTime(displayUnit = "mo") = 2628000) annotation(Placement(visible = true, transformation(origin = {-90, -70}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Converters.ConstantConverter desiredInventory(value = 100) annotation(Placement(visible = true, transformation(origin = {-55, -70}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Interfaces.Connectors.DataBus bus annotation(Placement(visible = true, transformation(origin = {110, 50}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {73.333, 77.778}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(inventory.outflow, shipping.portA) annotation(Line(visible = true, origin = {-30, -30}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(shipping.portB, installedBase.inflow) annotation(Line(visible = true, origin = {10, -30}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(producing.massPort, inventory.inflow) annotation(Line(visible = true, origin = {-70, -30}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(installedBase.outflow, scrapping.portA) annotation(Line(visible = true, origin = {50, -30}, points = {{-10, 0}, {10, 0}}, color = {255, 0, 0})); + connect(scrapping.portB, cloud1.massPort) annotation(Line(visible = true, origin = {90, -30}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(scrapping.y, totalOrders.u1) annotation(Line(visible = true, origin = {56, -9.867}, points = {{19, -9.733}, {19, 4.867}, {-38, 4.867}}, color = {1, 37, 163})); + connect(totalOrders.y, shipping.u) annotation(Line(visible = true, origin = {-9.333, -6.667}, points = {{11.333, 6.667}, {-5.667, 6.667}, {-5.667, -13.333}}, color = {1, 37, 163})); + connect(wordOfMouth.portB, customers.inflow) annotation(Line(visible = true, origin = {-30, 30}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(wordOfMouth.dataOut, bus) annotation(Line(visible = true, origin = {6.667, 46.8}, points = {{-51.667, -6.4}, {-51.667, 3.2}, {103.333, 3.2}}, color = {0, 0, 128})); + connect(bus.totalAdoptionRate, totalOrders.u2) annotation(Line(visible = true, origin = {42.5, 21.318}, points = {{67.5, 28.682}, {-12.5, 28.682}, {-12.5, -16.318}, {-24.5, -16.318}}, color = {0, 0, 128})); + connect(shipping.y2, productionPlanning.u_outflow) annotation(Line(visible = true, origin = {-54.1, -45.75}, points = {{33.6, 10.75}, {24.1, 10.75}, {24.1, -4.25}, {-40.9, -4.25}, {-40.9, -13.25}}, color = {1, 37, 163})); + connect(inventory.y2, productionPlanning.u_current) annotation(Line(visible = true, origin = {-72.1, -47.77}, points = {{11.6, 12.77}, {7.1, 12.77}, {7.1, -7.23}, {-12.9, -7.23}, {-12.9, -11.23}}, color = {1, 37, 163})); + connect(desiredInventory.y, productionPlanning.u_reference) annotation(Line(visible = true, origin = {-69.75, -70}, points = {{8.75, 0}, {-8.75, 0}}, color = {1, 37, 163})); + connect(customers.y1, modelOutput.customers) annotation(Line(visible = true, origin = {83.185, 12.5}, points = {{-82.685, 12.5}, {16.815, 12.5}, {16.815, -12.5}, {51.815, -12.5}}, color = {192, 192, 192})); + connect(potCustomers.y1, modelOutput.potentialCustomers) annotation(Line(visible = true, origin = {18.811, 12.772}, points = {{-98.311, 12.228}, {-88.811, 12.228}, {-88.811, 0.544}, {81.189, 0.544}, {81.189, -12.772}, {116.189, -12.772}}, color = {192, 192, 192})); + connect(inventory.y1, modelOutput.inventory) annotation(Line(visible = true, origin = {37.583, -15}, points = {{-77.083, -20}, {-72.583, -20}, {-72.583, 5}, {62.417, 5}, {62.417, 15}, {97.417, 15}}, color = {192, 192, 192})); + connect(installedBase.y, modelOutput.installedBase) annotation(Line(visible = true, origin = {81, -7.92}, points = {{-46, -11.68}, {-46, -2.08}, {19, -2.08}, {19, 7.92}, {54, 7.92}}, color = {192, 192, 192})); + connect(producing.y1, modelOutput.producing) annotation(Line(visible = true, origin = {24.25, -31.667}, points = {{-103.75, -3.333}, {-99.25, -3.333}, {-99.25, -28.333}, {95.75, -28.333}, {95.75, 31.667}, {110.75, 31.667}}, color = {192, 192, 192})); + connect(shipping.y1, modelOutput.shipping) annotation(Line(visible = true, origin = {64.25, -31.667}, points = {{-63.75, -3.333}, {-59.25, -3.333}, {-59.25, -28.333}, {55.75, -28.333}, {55.75, 31.667}, {70.75, 31.667}}, color = {192, 192, 192})); + connect(scrapping.y1, modelOutput.scrapping) annotation(Line(visible = true, origin = {104.25, -31.667}, points = {{-23.75, -3.333}, {-19.25, -3.333}, {-19.25, -28.333}, {15.75, -28.333}, {15.75, 31.667}, {30.75, 31.667}}, color = {192, 192, 192})); + connect(potCustomers.outflow, wordOfMouth.portA) annotation(Line(visible = true, origin = {-70, 30}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(productionPlanning.y, producing.u) annotation(Line(visible = true, origin = {-106.2, -36}, points = {{5.2, -34}, {-13.8, -34}, {-13.8, 26}, {11.2, 26}, {11.2, 16}}, color = {1, 37, 163})); + annotation(experiment(StartTime = 0, StopTime = 315360000, __Wolfram_DisplayTimeUnit = "mo", __Wolfram_NumberOfIntervals = -1), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

In this final extension of the introductory model SimpleProductionChain we now replace the Ramp component for the first-time purchases with a model of new product diffusion.

+

We are assuming that there are 10 initial customers and a stock of 250'000 potential customers that will be turned into customers by \"word-of-mouth\" only—for now we will assume that there is no growth or decline with regard to this potential. There is a constant contactRate of 10 people per month and the adoptionFraction is assumed to be 2%.

+
Model Output
+ +

See also

+

+Tutorial.StrategicBusinessSimulation, +SimpleProductionChainSimpleProductionChainIIDiffusion

+"), __Wolfram(PlotSet(plots = {Plot(name = "Stocks and Rates", identifier = "stocks-rates", preferred = true, subPlots = {SubPlot(curves = {Curve(x = time, y = modelOutput.potentialCustomers), Curve(x = time, y = modelOutput.customers)}, range = Range(xunit = "yr", yunit = "thousand")), SubPlot(curves = {Curve(x = time, y = modelOutput.producing), Curve(x = time, y = modelOutput.scrapping)}, range = Range(xunit = "yr"))})})), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}), graphics = {Text(visible = true, origin = {0, 65}, textColor = {76, 112, 136}, extent = {{-140, -6}, {140, 6}}, textString = "Simple Production Chain III", fontName = "Lato Black", textStyle = {TextStyle.Bold})})); +end SimpleProductionChainIII; diff --git a/BusinessSimulation/Examples/package.mo b/BusinessSimulation/Examples/package.mo new file mode 100644 index 0000000..f6f0b26 --- /dev/null +++ b/BusinessSimulation/Examples/package.mo @@ -0,0 +1,16 @@ +within BusinessSimulation; + +package Examples "Example models showing basic and advanced functionality" + extends Icons.ExamplesPackage; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This package contains examples for the use of library elements in simulation models.

+

See also

+

+Tutorial +

+
+
+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Examples; diff --git a/BusinessSimulation/Examples/package.order b/BusinessSimulation/Examples/package.order new file mode 100644 index 0000000..eb9c84b --- /dev/null +++ b/BusinessSimulation/Examples/package.order @@ -0,0 +1,10 @@ +SimpleProductionChain +SimpleProductionChainII +SimpleProductionChainIII +SIR +LoveHateDynamics +LotkaVolterraSystems +LotkaVolterraEquationsRevisited +ManagingEmployment +AssemblyLine +LookupFunctions diff --git a/BusinessSimulation/Flows/Bidirectional/ProportionalSwitching.mo b/BusinessSimulation/Flows/Bidirectional/ProportionalSwitching.mo new file mode 100644 index 0000000..b44a62d --- /dev/null +++ b/BusinessSimulation/Flows/Bidirectional/ProportionalSwitching.mo @@ -0,0 +1,49 @@ +within BusinessSimulation.Flows.Bidirectional; + +model ProportionalSwitching "Rate of exchange is proportional to amount in stocks" + extends Interfaces.PartialFlows.BidirectionalFlow; + Interfaces.Connectors.RealInput u "Fractional rate input" annotation(Placement(visible = true, transformation(origin = {-145, 60}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-50, 100}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + parameter Boolean useAbsoluteLevels = true "= true, if the stock levels are to be taken als absolute values otherweise a negative amount in a stock may reverse the direction of flow" annotation(Dialog(group = "Structural Parameters")); +protected + Real levelA = if not useAbsoluteLevels then portA.stock else abs(portA.stock) "Level-information for the stock A"; + Real levelB = if not useAbsoluteLevels then portB.stock else abs(portB.stock) "Level-information for the stock B"; +equation + A_rate = if u >= 0 then levelA * u else levelB * u; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

ProportionalSwitching models the exchange of \"mass\" (conserved matter or information) between two stocks as a bi-directional flow. The rate of flow will be proportional to the amount in the connected levels times the fractional rate of flow given by the input u:

+ + + + + + + + + + + + + + + + + + +
input udirection of flow (for positive levels) +

rate of flow

+
u ≥ 0flow from A to B +

stockA.y ⋅ u

+
u <= 0flow from B to A +

stockB.y ⋅ |u|

+
+

Notes

+ +

See also

+

Switching

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {59.583, 14.198}, rotation = 5.306, points = {{32.722, -10.515}, {16.1, 26.782}, {-20.02, 35.205}, {-43.929, 11.895}}, color = {0, 0, 128}, thickness = 2.5, arrowSize = 0, smooth = Smooth.Bezier), Text(visible = true, origin = {2.544, -76.372}, textColor = {0, 0, 128}, extent = {{-80.456, -12}, {80.456, 12}}, textString = "fractional rate", fontName = "Lato", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {0, 75}, textColor = {0, 128, 0}, extent = {{-100, -12}, {100, 12}}, textString = "PROP Switching", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Line(visible = true, origin = {-60.264, -14.352}, rotation = 5.306, points = {{-32.722, 10.515}, {-16.1, -26.782}, {20.02, -35.205}, {44.243, -12.981}}, color = {0, 0, 128}, thickness = 2.5, arrowSize = 0, smooth = Smooth.Bezier), Line(visible = true, origin = {-42.154, -19.63}, rotation = 5.306, points = {{36.522, -45.771}, {43.438, -34.535}, {45.906, -7.964}}, color = {0, 0, 128}, thickness = 2.5, arrowSize = 0, smooth = Smooth.Bezier), Polygon(visible = true, origin = {4, -26.505}, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, points = {{0, 9}, {5, -5}, {-5, -5}}), Polygon(visible = true, origin = {-15.474, -23.17}, rotation = -35, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, points = {{0, 9}, {-5, -5}, {5, -5}}), Polygon(visible = true, origin = {16.162, 24.036}, rotation = -35, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, points = {{0, -9}, {5, 5}, {-5, 5}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end ProportionalSwitching; diff --git a/BusinessSimulation/Flows/Bidirectional/Switching.mo b/BusinessSimulation/Flows/Bidirectional/Switching.mo new file mode 100644 index 0000000..9cab23c --- /dev/null +++ b/BusinessSimulation/Flows/Bidirectional/Switching.mo @@ -0,0 +1,20 @@ +within BusinessSimulation.Flows.Bidirectional; + +model Switching "An exchange of matter between two stocks at an exogenous rate" + import BusinessSimulation.Units.Rate; + extends Interfaces.PartialFlows.BidirectionalFlow; + Interfaces.Connectors.RealInput u "Rate input" annotation(Placement(visible = true, transformation(origin = {-145, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-50, 100}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); +equation + A_rate = u; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This is the classical example for an exchange of \"mass\" (conserved matter or information) between two stocks, where the flow may go in either direction.

+

Notes

+ +

See also

+

TransitionProportionalSwitching

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {-8.257, -76.886}, textColor = {0, 0, 128}, extent = {{-25.827, -12}, {25.827, 12}}, textString = "rate", fontName = "Lato", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {0, 75}, textColor = {0, 128, 0}, extent = {{-100, -12}, {100, 12}}, textString = "Switching", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Line(visible = true, origin = {-42.154, -19.63}, rotation = 5.306, points = {{36.522, -45.771}, {43.438, -34.535}, {45.906, -7.964}}, color = {0, 0, 128}, thickness = 2.5, arrowSize = 0, smooth = Smooth.Bezier), Polygon(visible = true, origin = {4, -26.925}, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, points = {{0, 9}, {5, -5}, {-5, -5}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Switching; diff --git a/BusinessSimulation/Flows/Bidirectional/package.mo b/BusinessSimulation/Flows/Bidirectional/package.mo new file mode 100644 index 0000000..fb85a51 --- /dev/null +++ b/BusinessSimulation/Flows/Bidirectional/package.mo @@ -0,0 +1,12 @@ +within BusinessSimulation.Flows; + +package Bidirectional "Entities may move from stock A to stock B or from B to A" + extends Icons.Package; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This package contains bidirectional flows of the System Dynamics method. Bidirectional flows represent the most general type of flows.

+
+
+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {128, 128, 128}, fillColor = {76, 112, 136}, fillPattern = FillPattern.Solid, extent = {{-100, -100}, {100, 100}}, radius = 25), Line(visible = true, origin = {-2.596, -11.973}, points = {{-72.3, 0}, {72.3, 0}}, color = {255, 255, 255}, thickness = 5), Line(visible = true, origin = {-1.216, 11.777}, points = {{-73.637, 0}, {73.637, 0}}, color = {255, 255, 255}, thickness = 5), Polygon(visible = true, origin = {72.114, -0.25}, rotation = -450, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-22.295, -7.943}, {22.191, -7.943}, {0.104, 15.886}}), Ellipse(visible = true, origin = {1.899, 0}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-15.107, -15.107}, {15.107, 15.107}}), Polygon(visible = true, origin = {-74.886, -0.25}, rotation = 450, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{22.295, -7.943}, {-22.191, -7.943}, {-0.104, 15.886}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Bidirectional; diff --git a/BusinessSimulation/Flows/Bidirectional/package.order b/BusinessSimulation/Flows/Bidirectional/package.order new file mode 100644 index 0000000..2d9321f --- /dev/null +++ b/BusinessSimulation/Flows/Bidirectional/package.order @@ -0,0 +1,2 @@ +ProportionalSwitching +Switching diff --git a/BusinessSimulation/Flows/Interaction/BrokenTransition.mo b/BusinessSimulation/Flows/Interaction/BrokenTransition.mo new file mode 100644 index 0000000..eeee367 --- /dev/null +++ b/BusinessSimulation/Flows/Interaction/BrokenTransition.mo @@ -0,0 +1,56 @@ +within BusinessSimulation.Flows.Interaction; + +model BrokenTransition "The inflow to B is proportional to the outflow from A" + import BusinessSimulation.Units.{Rate,Amount}; + extends Interfaces.Basics.GenericFlow; + extends Interfaces.Basics.Interaction4SO; + extends Icons.Interaction; + Interfaces.Connectors.RealInput u_rate if not hasConstantRate "Rate of outflow from A" annotation(Placement(visible = true, transformation(origin = {-70, 90}, extent = {{-10, -10}, {10, 10}}, rotation = -90), iconTransformation(origin = {0, 100}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Interfaces.Connectors.RealInput u_factor if not hasConstantFactor "Factor of proportionality (units B / units A)" annotation(Placement(visible = true, transformation(origin = {-20, 90}, extent = {{-10, -10}, {10, 10}}, rotation = -450), iconTransformation(origin = {100, 50}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + parameter Rate rate(min = 0) = 0 "Constant rate of outflow for the stock A" annotation(Dialog(enable = hasConstantRate)); + parameter Amount factor(min = 0) = 1 "Constant factor of proportionality to be multiplied with the outflow from A (default = 1 each [per 1 each])" annotation(Dialog(enable = hasConstantFactor)); + parameter Boolean hasConstantFactor = false "= true, if the factor is to be given by the constant parameter" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean hasConstantRate = false "= true, if the outflow rate for A is to be given by the constant parameter" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); +protected + SourcesOrSinks.Decline flowingOut "Outflow for stock A" annotation(Placement(visible = true, transformation(origin = {-110, -0}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Converters.PassThrough u_OutflowRate_A if not hasConstantRate "Input of outflow rate" annotation(Placement(visible = true, transformation(origin = {-70, 60}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.ConstantConverterRate parOutflowRate_A(final value = rate) if hasConstantRate "Constant rate of outflow for A" annotation(Placement(visible = true, transformation(origin = {-95, 60}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.Product_2 inflowRate_B "Rate of inflow to stock B" annotation(Placement(visible = true, transformation(origin = {30, 30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + SourcesOrSinks.Growth flowingIn "Inflow to stock B" annotation(Placement(visible = true, transformation(origin = {90, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.PassThrough u_FactorOfProportionality if not hasConstantFactor "Continuous input" annotation(Placement(visible = true, transformation(origin = {-20, 60}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.ConstantConverter parFactorOfProportionality(final value = factor) if hasConstantFactor "Constant input" annotation(Placement(visible = true, transformation(origin = {0, 60}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); +equation + connect(portA, flowingOut.massPort) annotation(Line(visible = true, origin = {-140, -0}, points = {{-20, 0}, {20, -0}}, color = {128, 0, 128})); + connect(u_OutflowRate_A.y, flowingOut.u) annotation(Line(visible = true, origin = {-87.5, 37.716}, points = {{17.5, 14.921}, {17.5, -17.716}, {-17.5, -17.716}, {-17.5, -27.716}}, color = {1, 37, 163})); + connect(parOutflowRate_A.y, flowingOut.u) annotation(Line(visible = true, origin = {-102.5, 38.104}, points = {{7.5, 16.896}, {7.5, -18.104}, {-2.5, -18.104}, {-2.5, -28.104}}, color = {1, 37, 163})); + connect(flowingIn.massPort, portB) annotation(Line(visible = true, origin = {130, -0}, points = {{-30, -0}, {30, 0}}, color = {128, 0, 128})); + connect(inflowRate_B.y, flowingIn.u) annotation(Line(visible = true, origin = {69.121, 23.333}, points = {{-31.758, 6.667}, {15.879, 6.667}, {15.879, -13.333}}, color = {1, 37, 163})); + connect(flowingOut.y2, inflowRate_B.u2) annotation(Line(visible = true, origin = {-29.375, 10}, points = {{-70.125, -15}, {9.375, -15}, {9.375, 15}, {51.375, 15}}, color = {1, 37, 163})); + connect(flowingOut.y, y1_A) annotation(Line(visible = true, origin = {-23.333, 30.133}, points = {{-91.667, -19.733}, {-91.667, 9.867}, {183.333, 9.867}}, color = {1, 37, 163})); + connect(flowingOut.y, y_A) annotation(Line(visible = true, origin = {-23.333, 56.8}, points = {{-91.667, -46.4}, {-91.667, 23.2}, {183.333, 23.2}}, color = {1, 37, 163})); + connect(u_FactorOfProportionality.y, inflowRate_B.u1) annotation(Line(visible = true, origin = {-6, 40.879}, points = {{-14, 11.758}, {-14, -5.879}, {28, -5.879}}, color = {1, 37, 163})); + connect(flowingIn.y1, y_B) annotation(Line(visible = true, origin = {125.125, -22.5}, points = {{-24.625, 17.5}, {-5.125, 17.5}, {-5.125, -17.5}, {34.875, -17.5}}, color = {1, 37, 163})); + connect(flowingIn.y1, y1_B) annotation(Line(visible = true, origin = {125.125, -42.5}, points = {{-24.625, 37.5}, {-5.125, 37.5}, {-5.125, -37.5}, {34.875, -37.5}}, color = {1, 37, 163})); + connect(parFactorOfProportionality.y, inflowRate_B.u1) annotation(Line(visible = true, origin = {7.333, 41.667}, points = {{-7.333, 13.333}, {-7.333, -6.667}, {14.667, -6.667}}, color = {1, 37, 163})); + connect(u_factor, u_FactorOfProportionality.u) annotation(Line(visible = true, origin = {-20, 79}, points = {{-0, 11}, {0, -11}}, color = {1, 37, 163})); + connect(u_rate, u_OutflowRate_A.u) annotation(Line(visible = true, origin = {-70, 79}, points = {{0, 11}, {0, -11}}, color = {1, 37, 163})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This is the classical structure for a broken flow from stock A to stock B, where the rate of outflow is given for stock A. A's outflow will flow into a →Cloud and accordingly, there will be an inflow to stock B which is given by:

+

rate of inflow to B = rate of outflow from A × factor of proportionality

+

Here the factor of proportionality will be given as amount of B per amount of A, so that the resulting inflow to B will have proper units [amount of B per second].

+

Implementation

+
+ + + + + + +
Diagram for BrokenTransition
\"Diagram.png\"
+

Notes

+

Jim Hines [6, p. 16] notes, that \"in an aggregated model of a supply chain there will be a change of units and a conceptual break in the transition from raw materials inventory to work in progress.\"

+

See also

+

BrokenTransitionPullTransition

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {-15.783, -54.866}, textColor = {0, 0, 128}, extent = {{-34.217, -12}, {34.217, 12}}, textString = "factor", fontName = "Lato", textStyle = {TextStyle.Bold}), Line(visible = true, origin = {33.142, 17.162}, rotation = 5.35, points = {{-56.426, 30.508}, {-66.107, 22.749}, {-75.3, 9.902}}, color = {0, 0, 128}, thickness = 2.5, arrowSize = 0, smooth = Smooth.Bezier), Text(visible = true, origin = {-2.331, 50}, textColor = {0, 0, 128}, extent = {{-20, -12}, {20, 12}}, textString = "rate", fontName = "Lato", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {0, 75}, textColor = {0, 128, 0}, extent = {{-100, -12}, {100, 12}}, textString = "Broken Transition", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Polygon(visible = true, origin = {-41.165, 23.17}, rotation = -30, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, points = {{0, -9}, {-5, 5}, {5, 5}}), Line(visible = true, origin = {-45.895, -19.209}, rotation = 5.35, points = {{56.426, -30.508}, {66.107, -22.749}, {75.3, -9.902}}, color = {0, 0, 128}, thickness = 2.5, arrowSize = 0, smooth = Smooth.Bezier), Polygon(visible = true, origin = {28.979, -23.17}, rotation = -30, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, points = {{0, 9}, {5, -5}, {-5, -5}})}), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end BrokenTransition; diff --git a/BusinessSimulation/Flows/Interaction/BrokenTransitionPull.mo b/BusinessSimulation/Flows/Interaction/BrokenTransitionPull.mo new file mode 100644 index 0000000..f967006 --- /dev/null +++ b/BusinessSimulation/Flows/Interaction/BrokenTransitionPull.mo @@ -0,0 +1,58 @@ +within BusinessSimulation.Flows.Interaction; + +model BrokenTransitionPull "The outflow from A is proportional to the inflow to B" + import BusinessSimulation.Units.{Amount,Rate}; + extends Interfaces.Basics.GenericFlow; + extends Interfaces.Basics.Interaction4SO; + extends Icons.Interaction; + Interfaces.Connectors.RealInput u_rate if not hasConstantRate "Rate of inflow to B" annotation(Placement(visible = true, transformation(origin = {-70, 90}, extent = {{-10, -10}, {10, 10}}, rotation = -90), iconTransformation(origin = {0, 100}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Interfaces.Connectors.RealInput u_factor if not hasConstantFactor "Factor of proportionality (amount of A per amount of B)" annotation(Placement(visible = true, transformation(origin = {-20, 90}, extent = {{-10, -10}, {10, 10}}, rotation = -450), iconTransformation(origin = {-100, 50}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + parameter Rate rate(min = 0) = 0 "Constant rate of inflow to the stock B" annotation(Dialog(enable = hasConstantRate)); + parameter Amount factor = 1 "Constant factor of proportionality to be multiplied with the outflow from A (default = 1 each [per 1 each])" annotation(Dialog(enable = hasConstantFactor)); + parameter Boolean hasConstantFactor = false "= true, if the factor is to be given by the constant parameter" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean hasConstantRate = false "= true, if the outflow rate for A is to be given by the constant parameter" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); +protected + SourcesOrSinks.Decline flowingOut "Outflow for stock A" annotation(Placement(visible = true, transformation(origin = {-110, -0}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Converters.PassThrough u_InflowRate_B if not hasConstantRate "Input of inflow rate for B" annotation(Placement(visible = true, transformation(origin = {-70, 60}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.ConstantConverterRate parInflowRate_B(final value = rate) if hasConstantRate "Constant rate of inflow to B" annotation(Placement(visible = true, transformation(origin = {-95, 60}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.Product_2 outflowRate_A "Rate of outflow from stock A" annotation(Placement(visible = true, transformation(origin = {-50, 20}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + SourcesOrSinks.Growth flowingIn "Inflow to stock B" annotation(Placement(visible = true, transformation(origin = {90, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.PassThrough u_Factor if not hasConstantFactor "Input for factor of proportionality" annotation(Placement(visible = true, transformation(origin = {-20, 60}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.ConstantConverter parFactor(final value = factor) if hasConstantFactor "Constant factor of proportionality" annotation(Placement(visible = true, transformation(origin = {0, 60}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); +equation + connect(portA, flowingOut.massPort) annotation(Line(visible = true, origin = {-140, -0}, points = {{-20, 0}, {20, -0}}, color = {128, 0, 128})); + connect(flowingIn.massPort, portB) annotation(Line(visible = true, origin = {130, -0}, points = {{-30, -0}, {30, 0}}, color = {128, 0, 128})); + connect(flowingOut.y, y1_A) annotation(Line(visible = true, origin = {-23.333, 30.133}, points = {{-91.667, -19.733}, {-91.667, 9.867}, {183.333, 9.867}}, color = {1, 37, 163})); + connect(flowingOut.y, y_A) annotation(Line(visible = true, origin = {-23.333, 56.8}, points = {{-91.667, -46.4}, {-91.667, 23.2}, {183.333, 23.2}}, color = {1, 37, 163})); + connect(u_Factor.y, outflowRate_A.u1) annotation(Line(visible = true, origin = {-27.333, 34}, points = {{7.333, 18}, {7.333, -9}, {-14.667, -9}}, color = {1, 37, 163})); + connect(flowingIn.y1, y_B) annotation(Line(visible = true, origin = {125.125, -22.5}, points = {{-24.625, 17.5}, {-5.125, 17.5}, {-5.125, -17.5}, {34.875, -17.5}}, color = {1, 37, 163})); + connect(flowingIn.y1, y1_B) annotation(Line(visible = true, origin = {125.125, -42.5}, points = {{-24.625, 37.5}, {-5.125, 37.5}, {-5.125, -37.5}, {34.875, -37.5}}, color = {1, 37, 163})); + connect(parFactor.y, outflowRate_A.u1) annotation(Line(visible = true, origin = {-14, 34.667}, points = {{14, 19.333}, {14, -9.667}, {-28, -9.667}}, color = {1, 37, 163})); + connect(u_factor, u_Factor.u) annotation(Line(visible = true, origin = {-20, 79}, points = {{0, 11}, {0, -11}}, color = {1, 37, 163})); + connect(u_rate, u_InflowRate_B.u) annotation(Line(visible = true, origin = {-70, 79}, points = {{0, 11}, {0, -11}}, color = {1, 37, 163})); + connect(parInflowRate_B.y, flowingIn.u) annotation(Line(visible = true, origin = {-5, 31.25}, points = {{-90, 23.75}, {-90, -1.25}, {90, -1.25}, {90, -21.25}}, color = {1, 37, 163})); + connect(u_InflowRate_B.y, flowingIn.u) annotation(Line(visible = true, origin = {7.5, 30.5}, points = {{-77.5, 21.5}, {-77.5, -0.5}, {77.5, -0.5}, {77.5, -20.5}}, color = {1, 37, 163})); + connect(flowingIn.y2, outflowRate_A.u2) annotation(Line(visible = true, origin = {9.375, 5}, points = {{70.125, -10}, {-9.375, -10}, {-9.375, 10}, {-51.375, 10}}, color = {1, 37, 163})); + connect(outflowRate_A.y, flowingOut.u) annotation(Line(visible = true, origin = {-89.333, 16.667}, points = {{31.333, 3.333}, {-15.667, 3.333}, {-15.667, -6.667}}, color = {1, 37, 163})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This is a variant of the classical broken flow (→BrokenTransition) structure that allows for a different parameterization:  In this component the given value for the rate (rate or u_rate) relates to the rate of inflow to stock B, while the factor of proportionality (factor or u_factor) determines the outflow from stock A that is necessary for this process.

+

A typical application would be to have a given rate of production (here the stock B would be the stock of finished goods) which needs and outflow from the stock of materials that is proprotional to the rate of production according to a factor determined by the bill of materials.

+

Hence:

+

rate of outflow from A = rate of inflow to B × factor of proportionality

+

The factor of proportionality will be given as amount of A per amount of B, so that the resulting outflow from A will have proper units[amnount of B per second]. 

+

Implementation

+
+ + + + + + +
Diagram for BrokenTransitionPull
\"Diagram.png\"
+

Notes

+

Unlike the classical broken flow structure, setting the rate for the stock B might not take into account the availability of material in the stock A; so this has to be taken care of by the modeler explicitly.

+

See also

+

BrokenTransitionTransition

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {-2.924, -54.714}, textColor = {0, 0, 128}, extent = {{-19.048, -12}, {19.048, 12}}, textString = "rate", fontName = "Lato", textStyle = {TextStyle.Bold}, horizontalAlignment = TextAlignment.Left), Text(visible = true, origin = {42.118, 50}, textColor = {0, 0, 128}, extent = {{-65, -12}, {65, 12}}, textString = "factor", fontName = "Lato", textStyle = {TextStyle.Bold}, horizontalAlignment = TextAlignment.Left), Text(visible = true, origin = {0, 75}, textColor = {0, 128, 0}, extent = {{-100, -12}, {100, 12}}, textString = "Broken Transition", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Line(visible = true, origin = {33.142, 17.162}, rotation = 5.35, points = {{-56.426, 30.508}, {-66.107, 22.749}, {-75.3, 9.902}}, color = {0, 0, 128}, thickness = 2.5, arrowSize = 0, smooth = Smooth.Bezier), Line(visible = true, origin = {-45.895, -19.209}, rotation = 5.35, points = {{56.426, -30.508}, {66.107, -22.749}, {75.3, -9.902}}, color = {0, 0, 128}, thickness = 2.5, arrowSize = 0, smooth = Smooth.Bezier), Polygon(visible = true, origin = {-41.165, 23.17}, rotation = -30, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, points = {{0, -9}, {-5, 5}, {5, 5}}), Polygon(visible = true, origin = {28.979, -23.17}, rotation = -30, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, points = {{0, 9}, {5, -5}, {-5, -5}})}), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end BrokenTransitionPull; diff --git a/BusinessSimulation/Flows/Interaction/ComplexInteraction.mo b/BusinessSimulation/Flows/Interaction/ComplexInteraction.mo new file mode 100644 index 0000000..acd8447 --- /dev/null +++ b/BusinessSimulation/Flows/Interaction/ComplexInteraction.mo @@ -0,0 +1,172 @@ +within BusinessSimulation.Flows.Interaction; + +model ComplexInteraction "Combined linear and nonlinear interaction" + extends Icons.Interaction; + extends Interfaces.Basics.GenericFlow; + extends Interfaces.Basics.Interaction4SO; + InputConnector dataIn "Expandable connector for continuous input" annotation(Placement(visible = true, transformation(origin = {-150, 40}, extent = {{-10, -10}, {10, 10}}, rotation = -360), iconTransformation(origin = {0, 100}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + + expandable connector InputConnector "Data bus for inputs" + extends Icons.DataInPort; + // coefficients for net flow equations A + Real a_0 "Growth rate for A (independent)"; + Real a_A "Fractional rate of growth for A (self-coupling A)"; + Real a_B "Rate of growth for A per unit of B (coupling of B to A)"; + Real a_AB "Fractional rate of growth for A per unit of B (nonlinear coupling)"; + // coefficients for net flow equation B + Real b_0 "Growth rate for B (independent)"; + Real b_B "Fractional growth rate for B (self-coupling)"; + Real b_A "Rate of growth for B per unit of A (coupling of A to B)"; + Real b_AB "Fractional growth rate for B per unit of A (nonlinear coupling)"; + end InputConnector; +protected + LinearInteraction linearInteraction "Linear interaction between A and B" annotation(Placement(visible = true, transformation(origin = {0, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + NonlinearInteraction nonlinearInteraction "Nonlinear interaction between A and B" annotation(Placement(visible = true, transformation(origin = {0, -40}, extent = {{-10, 10}, {10, -10}}, rotation = 0))); + Converters.Add_2 netRate_B annotation(Placement(visible = true, transformation(origin = {80, -60}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Add_2 netRate_A annotation(Placement(visible = true, transformation(origin = {80, 60}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealOutput a_0 "Growth rate for A (independent)" annotation(Placement(visible = true, transformation(origin = {-120, 90}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80.808, 87.354}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealOutput a_A "Fractional rate of growth for A (self-coupling A)" annotation(Placement(visible = true, transformation(origin = {-120, 70}, extent = {{-10, -10}, {10, 10}}, rotation = -360), iconTransformation(origin = {-80.808, 87.354}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealOutput a_B "Rate of growth for A per unit of B (coupling of B to A)" annotation(Placement(visible = true, transformation(origin = {-120, 50}, extent = {{-10, -10}, {10, 10}}, rotation = -360), iconTransformation(origin = {-80.808, 87.354}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealOutput a_AB "Fractional rate of growth for A per unit of B (nonlinear coupling)" annotation(Placement(visible = true, transformation(origin = {-120, 30}, extent = {{-10, -10}, {10, 10}}, rotation = -360), iconTransformation(origin = {-80.808, 87.354}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealOutput b_0 "Growth rate for B (independent)" annotation(Placement(visible = true, transformation(origin = {-120, 10}, extent = {{-10, -10}, {10, 10}}, rotation = -360), iconTransformation(origin = {-80.808, 87.354}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealOutput b_B "Fractional growth rate for B (self-coupling)" annotation(Placement(visible = true, transformation(origin = {-120, -10}, extent = {{-10, -10}, {10, 10}}, rotation = -360), iconTransformation(origin = {-80.808, 87.354}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealOutput b_A "Rate of growth for B per unit of A (coupling of A to B)" annotation(Placement(visible = true, transformation(origin = {-120, -30}, extent = {{-10, -10}, {10, 10}}, rotation = -360), iconTransformation(origin = {-80.808, 87.354}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealOutput b_AB "Fractional growth rate for B per unit of A (nonlinear coupling)" annotation(Placement(visible = true, transformation(origin = {-120, -50}, extent = {{-10, -10}, {10, 10}}, rotation = -360), iconTransformation(origin = {-80.808, 87.354}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.DataBus dataBus annotation(Placement(visible = true, transformation(origin = {-90, 70}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-60.606, 49.959}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(portA, linearInteraction.portA) annotation(Line(visible = true, origin = {-62.5, 20}, points = {{-97.5, -20}, {22.5, -20}, {22.5, 20}, {52.5, 20}}, color = {128, 0, 128})); + connect(linearInteraction.portB, portB) annotation(Line(visible = true, origin = {62.5, 20}, points = {{-52.5, 20}, {-22.5, 20}, {-22.5, -20}, {97.5, -20}}, color = {128, 0, 128})); + connect(portA, nonlinearInteraction.portA) annotation(Line(visible = true, origin = {-62.5, -20}, points = {{-97.5, 20}, {22.5, 20}, {22.5, -20}, {52.5, -20}}, color = {128, 0, 128})); + connect(nonlinearInteraction.portB, portB) annotation(Line(visible = true, origin = {62.5, -20}, points = {{-52.5, -20}, {-22.5, -20}, {-22.5, 20}, {97.5, 20}}, color = {128, 0, 128})); + // inputConnector to connectors + connect(dataIn.a_0, a_0) annotation(Line(visible = true, origin = {-142.078, 65}, points = {{-7.922, -25}, {2.078, -25}, {2.078, 25}, {22.078, 25}}, color = {0, 0, 128})); + connect(dataIn.a_A, a_A) annotation(Line(visible = true, origin = {-142.078, 55}, points = {{-7.922, -15}, {2.078, -15}, {2.078, 15}, {22.078, 15}}, color = {0, 0, 128})); + connect(dataIn.a_B, a_B) annotation(Line(visible = true, origin = {-142.078, 45}, points = {{-7.922, -5}, {2.078, -5}, {2.078, 5}, {22.078, 5}}, color = {0, 0, 128})); + connect(dataIn.a_AB, a_AB) annotation(Line(visible = true, origin = {-142.078, 35}, points = {{-7.922, 5}, {2.078, 5}, {2.078, -5}, {22.078, -5}}, color = {0, 0, 128})); + connect(dataIn.b_0, b_0) annotation(Line(visible = true, origin = {-142.078, 25}, points = {{-7.922, 15}, {2.078, 15}, {2.078, -15}, {22.078, -15}}, color = {0, 0, 128})); + connect(dataIn.b_B, b_B) annotation(Line(visible = true, origin = {-142.078, 15}, points = {{-7.922, 25}, {2.078, 25}, {2.078, -25}, {22.078, -25}}, color = {0, 0, 128})); + connect(dataIn.b_A, b_A) annotation(Line(visible = true, origin = {-142.078, 5}, points = {{-7.922, 35}, {2.078, 35}, {2.078, -35}, {22.078, -35}}, color = {0, 0, 128})); + connect(dataIn.b_AB, b_AB) annotation(Line(visible = true, origin = {-142.078, -5}, points = {{-7.922, 45}, {2.078, 45}, {2.078, -45}, {22.078, -45}}, color = {0, 0, 128})); + // connectors to interior inputConnectors + connect(a_0, dataBus.a_0) annotation(Line(visible = true, origin = {-110, 80}, points = {{-10, 10}, {0, 10}, {0, -10}, {20, -10}}, color = {1, 37, 163})); + connect(a_A, dataBus.a_A) annotation(Line(visible = true, origin = {-105, 70}, points = {{-15, 0}, {15, 0}}, color = {1, 37, 163})); + connect(a_B, dataBus.a_B) annotation(Line(visible = true, origin = {-110, 60}, points = {{-10, -10}, {0, -10}, {0, 10}, {20, 10}}, color = {1, 37, 163})); + connect(a_AB, dataBus.a_AB) annotation(Line(visible = true, origin = {-110, 50}, points = {{-10, -20}, {0, -20}, {0, 20}, {20, 20}}, color = {1, 37, 163})); + connect(b_0, dataBus.b_0) annotation(Line(visible = true, origin = {-110, 40}, points = {{-10, -30}, {0, -30}, {0, 30}, {20, 30}}, color = {1, 37, 163})); + connect(b_B, dataBus.b_B) annotation(Line(visible = true, origin = {-110, 30}, points = {{-10, -40}, {0, -40}, {0, 40}, {20, 40}}, color = {1, 37, 163})); + connect(b_A, dataBus.b_A) annotation(Line(visible = true, origin = {-110, 20}, points = {{-10, -50}, {0, -50}, {0, 50}, {20, 50}}, color = {1, 37, 163})); + connect(b_AB, dataBus.b_AB) annotation(Line(visible = true, origin = {-110, 10}, points = {{-10, -60}, {0, -60}, {0, 60}, {20, 60}}, color = {1, 37, 163})); + // other connections + connect(linearInteraction.y_A, netRate_A.u1) annotation(Line(visible = true, origin = {20.667, 60.133}, points = {{-25.667, -9.733}, {-25.667, 4.867}, {51.333, 4.867}}, color = {1, 37, 163})); + connect(nonlinearInteraction.y1_A, netRate_A.u2) annotation(Line(visible = true, origin = {1.408, 10}, points = {{-11.908, -45}, {-29.342, -45}, {-29.342, 45}, {70.592, 45}}, color = {1, 37, 163})); + connect(netRate_A.y, y_A) annotation(Line(visible = true, origin = {121.841, 70}, points = {{-34.478, -10}, {-1.841, -10}, {-1.841, 10}, {38.159, 10}}, color = {1, 37, 163})); + connect(netRate_A.y, y1_A) annotation(Line(visible = true, origin = {121.841, 50}, points = {{-34.478, 10}, {-1.841, 10}, {-1.841, -10}, {38.159, -10}}, color = {1, 37, 163})); + connect(nonlinearInteraction.y_B, netRate_B.u2) annotation(Line(visible = true, origin = {27.333, -60.133}, points = {{-22.333, 9.733}, {-22.333, -4.867}, {44.667, -4.867}}, color = {1, 37, 163})); + connect(linearInteraction.y1_B, netRate_B.u1) annotation(Line(visible = true, origin = {30.625, -10}, points = {{-20.125, 45}, {-10.625, 45}, {-10.625, -45}, {41.375, -45}}, color = {1, 37, 163})); + connect(netRate_B.y, y_B) annotation(Line(visible = true, origin = {121.841, -50}, points = {{-34.478, -10}, {-1.841, -10}, {-1.841, 10}, {38.159, 10}}, color = {1, 37, 163})); + connect(netRate_B.y, y1_B) annotation(Line(visible = true, origin = {121.841, -70}, points = {{-34.478, 10}, {-1.841, 10}, {-1.841, -10}, {38.159, -10}}, color = {1, 37, 163})); + connect(linearInteraction.dataIn, dataBus) annotation(Line(visible = true, origin = {-30, 63.333}, points = {{30, -13.333}, {30, 6.667}, {-60, 6.667}}, color = {0, 0, 128})); + connect(nonlinearInteraction.dataIn, dataBus) annotation(Line(visible = true, origin = {-45, -25}, points = {{45, -25}, {45, -35}, {-45, -35}, {-45, 95}}, color = {0, 0, 128})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The ComplexInteraction component combines linear and nonlinear interaction between two stocks A (portA) and B (portB):

+

\"Formula.svg\"

+

Note: Capital letters were chosen to represent the stocks (state variables) connected at portA and portB in the formula above. Also dot notation is used for a stock's rate of flow—its first derivative with respect to time.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Coefficient +Unit +Description +
a_0 +

amount of A per second

+
+

Rate of growth for stock A

+
+

b_0

+
+

amount of B per second

+
+

Rate of growth for stock B

+
+

a_A

+
+

1/s

+
+

Fractional rate of growth for stock A
(e.g. the self-coupling coefficient for A)

+
+

b_B

+
+

1/s

+
+

Fractional rate of growth for stock B
(e.g.the self-coupling coefficient for B)

+
+

a_B

+
+

amount of A per amount of B per second

+
+

Rate of growth for stock A per stock B
(e.g. the coupling-cofficient for B towards A)

+
+

b_A

+
+

amount of B per amount of A per second

+
+

Rate of growth for stock B per stock A
(e.g. the coupling-coefficient for A towards B)

+
a_AB1 per second per amount of B +

Factor used to determine the net flow to A
(e.g. nonlinear coupling factor for A)

+
b_AB1 per second per amount of A +

Factor used to determine the net flow to B
(e.g. nonlinear coupling factor for B)

+
+

The coefficients can be given as parameters or as variables via the expandable connector dataIn.

+

Examples

+

The classical Lotka-Volterra-Model of predator-prey-dynamics can be derived from this model using the following parameterization:

+

a_0 = 0, a_A = α, a_B = 0, a_AB = -β, b_0 = 0, b_B = -γ, b_A = 0, b_AB = δ

+

See also

+

LinearInteraction, ComplexInteractionLotkaVolterra

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, 75}, textColor = {0, 128, 0}, extent = {{-100, -12}, {100, 12}}, textString = "Linear & Nonlinear", fontName = "Lato Black", textStyle = {TextStyle.Bold})})); +end ComplexInteraction; diff --git a/BusinessSimulation/Flows/Interaction/LinearInteraction.mo b/BusinessSimulation/Flows/Interaction/LinearInteraction.mo new file mode 100644 index 0000000..7424b59 --- /dev/null +++ b/BusinessSimulation/Flows/Interaction/LinearInteraction.mo @@ -0,0 +1,179 @@ +within BusinessSimulation.Flows.Interaction; + +model LinearInteraction "Linear model of interaction between two stocks" + import BusinessSimulation.Units.Rate; + extends Interfaces.Basics.GenericFlow; + extends Interfaces.Basics.Interaction4SO; + extends Icons.Interaction; + Input_Connector dataIn if not (hasConstantGrowthRates and hasConstantFractionalGrowthRates and hasConstantCouplingCoefficients) "Continuous inputs for the component" annotation(Placement(visible = true, transformation(origin = {-145, 85}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {0, 100}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + parameter Boolean hasConstantGrowthRates = false "= true, if the linear growth rates are given by constant parameters" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean hasConstantFractionalGrowthRates = false "= true, if the fractional growth rates are given by constant parameters" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean hasConstantCouplingCoefficients = false "= true, if the induced growth rates are given by constant parameters" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Rate a_0 = 0 "Constant rate of growth for stock A" annotation(Dialog(enable = hasConstantGrowthRates)); + parameter Rate b_0 = 0 "Constant rate of growth for stock B" annotation(Dialog(enable = hasConstantGrowthRates)); + parameter Rate a_A = 0 "Constant fractional rate of growth for stock A (self-coupling)" annotation(Dialog(enable = hasConstantFractionalGrowthRates)); + parameter Rate b_B = 0 "Constant fractional rate of growth for stock B (self-coupling)" annotation(Dialog(enable = hasConstantFractionalGrowthRates)); + parameter Rate a_B = 0 "Constant Rate of growth for stock A per unit of B (coupling B to A)" annotation(Dialog(enable = hasConstantCouplingCoefficients)); + parameter Rate b_A = 0 "Constant cross-fractional rate of growth for stock B per stock A (coupling A to B)" annotation(Dialog(enable = hasConstantCouplingCoefficients)); + + expandable connector Input_Connector "Data bus for inputs" + extends Interfaces.Connectors.DataInPort; + Real a_0 "Rate of growth for stock A (independent growth)"; + Real b_0 "Rate of growth for stock B (independent growth)"; + Real a_A "Fractional rate of growth for stock A (self-coupling)"; + Real b_B "Fractional rate of growth for stock B (sefl-coupling)"; + Real a_B "Rate of growth for stock A per unit of B (coupling of B to A)"; + Real b_A "Rate of growth for stock B per unit of A (coupling of A to B)"; + end Input_Connector; +protected + Converters.ConstantConverterRate parGrowthRateA(value = a_0) if hasConstantGrowthRates "Constant growth rate for A (optional)" annotation(Placement(visible = true, transformation(origin = {-130, 70}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.ConstantConverterRate parFractionalRateA(value = a_A) if hasConstantFractionalGrowthRates "Constant fractional growth rate for A (optional)" annotation(Placement(visible = true, transformation(origin = {-80, 70}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.ConstantConverterRate parCrossFractionalRateA(value = a_B) if hasConstantCouplingCoefficients "Constant cross-fractional growth rate for A (optional)" annotation(Placement(visible = true, transformation(origin = {-40, 70}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.ConstantConverterRate parGrowthRateB(value = b_0) if hasConstantGrowthRates "Constant growth rate for B (optional)" annotation(Placement(visible = true, transformation(origin = {120, 70}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.ConstantConverterRate parFractionalRateB(value = b_B) if hasConstantFractionalGrowthRates "Constant fractional growth rate for B (optional)" annotation(Placement(visible = true, transformation(origin = {80, 70}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.ConstantConverterRate parCrossFractionalRateB(value = b_A) if hasConstantCouplingCoefficients "Constant cross-fractional growth rate for B (optional)" annotation(Placement(visible = true, transformation(origin = {40, 70}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Interfaces.Connectors.RealOutput u_growthRate_A if not hasConstantGrowthRates annotation(Placement(visible = true, transformation(origin = {-105, 65}, extent = {{-10, -10}, {10, 10}}, rotation = -90), iconTransformation(origin = {-66.667, 77.778}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealOutput u_fractionalGrowthRate_A if not hasConstantFractionalGrowthRates annotation(Placement(visible = true, transformation(origin = {-65, 65}, extent = {{-10, -10}, {10, 10}}, rotation = -90), iconTransformation(origin = {-66.667, 77.778}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealOutput u_growthRate_A_per_B if not hasConstantCouplingCoefficients annotation(Placement(visible = true, transformation(origin = {-25, 65}, extent = {{-10, -10}, {10, 10}}, rotation = -90), iconTransformation(origin = {-66.667, 77.778}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealOutput u_growthRate_B_per_A if not hasConstantCouplingCoefficients annotation(Placement(visible = true, transformation(origin = {20, 65}, extent = {{10, -10}, {-10, 10}}, rotation = 90), iconTransformation(origin = {-66.667, 77.778}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealOutput u_fractionalGrowthRate_B if not hasConstantFractionalGrowthRates annotation(Placement(visible = true, transformation(origin = {60, 65}, extent = {{10, -10}, {-10, 10}}, rotation = 90), iconTransformation(origin = {-66.667, 77.778}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealOutput u_growthRate_B if not hasConstantGrowthRates annotation(Placement(visible = true, transformation(origin = {105, 65}, extent = {{10, -10}, {-10, 10}}, rotation = 90), iconTransformation(origin = {-66.667, 77.778}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + SourcesOrSinks.ExogenousChange growingA1 "Linear growth" annotation(Placement(visible = true, transformation(origin = {-110, 30}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + SourcesOrSinks.ExponentialChange growingA2 "Exponential growth for A" annotation(Placement(visible = true, transformation(origin = {-110, -10}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + SourcesOrSinks.ExogenousChange growingA3 "Cross-fractional growth rate for A per B" annotation(Placement(visible = true, transformation(origin = {-110, -50}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Sensors.FlowPortSensor stockB "Amount in stock B" annotation(Placement(visible = true, transformation(origin = {136.619, 0}, extent = {{-10, 10}, {10, -10}}, rotation = 0))); + Sensors.FlowPortSensor stockA "Amount in stock A" annotation(Placement(visible = true, transformation(origin = {-137.295, 0}, extent = {{-10, 10}, {10, -10}}, rotation = 0))); + Converters.Product_2 inducedGrowthA "Rate of growth induced by stock B" annotation(Placement(visible = true, transformation(origin = {-70, -30}, extent = {{-10, -10}, {10, 10}}, rotation = -540))); + Converters.Add_3 totalRateA annotation(Placement(visible = true, transformation(origin = {0, 20}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + SourcesOrSinks.ExogenousChange growingB1 "Linear growth" annotation(Placement(visible = true, transformation(origin = {110, 25}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + SourcesOrSinks.ExponentialChange growingB2 "Exponential growth for B" annotation(Placement(visible = true, transformation(origin = {110, -5}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + SourcesOrSinks.ExogenousChange growingB3 "Cross-fractional growth rate for B per A" annotation(Placement(visible = true, transformation(origin = {110, -55}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Product_2 inducedGrowthB "Rate of growth induced by stock A" annotation(Placement(visible = true, transformation(origin = {70, -25}, extent = {{10, -10}, {-10, 10}}, rotation = 540))); + Converters.Add_3 totalRateB annotation(Placement(visible = true, transformation(origin = {40, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(growingA1.massPort, portA) annotation(Line(visible = true, origin = {-135, 15}, points = {{15, 15}, {5, 15}, {5, -15}, {-25, -15}}, color = {128, 0, 128})); + connect(parGrowthRateA.y, growingA1.u) annotation(Line(visible = true, origin = {-117.5, 51.25}, points = {{-12.5, 13.75}, {-12.5, -1.25}, {12.5, -1.25}, {12.5, -11.25}}, color = {1, 37, 163})); + connect(growingA2.massPort, portA) annotation(Line(visible = true, origin = {-135, -5}, points = {{15, -5}, {5, -5}, {5, 5}, {-25, 5}}, color = {128, 0, 128})); + connect(parFractionalRateA.y, growingA2.u) annotation(Line(visible = true, origin = {-92.5, 21.25}, points = {{12.5, 43.75}, {12.5, -11.25}, {-12.5, -11.25}, {-12.5, -21.25}}, color = {1, 37, 163})); + connect(growingA3.massPort, portA) annotation(Line(visible = true, origin = {-135, -25}, points = {{15, -25}, {5, -25}, {5, 25}, {-25, 25}}, color = {128, 0, 128})); + connect(stockB.flowPort, portB) annotation(Line(visible = true, origin = {142.542, 0}, points = {{-5.922, 0}, {5.922, -0}}, color = {128, 0, 128})); + connect(stockA.flowPort, portA) annotation(Line(visible = true, origin = {-142.815, 0}, points = {{5.519, 0}, {-5.519, -0}}, color = {128, 0, 128})); + connect(inducedGrowthA.y, growingA3.u) annotation(Line(visible = true, origin = {-95.787, -33.333}, points = {{18.425, 3.333}, {-9.213, 3.333}, {-9.213, -6.667}}, color = {1, 37, 163})); + connect(inducedGrowthA.u1, stockB.stock) annotation(Line(visible = true, origin = {70.445, -27}, points = {{-132.445, -8}, {66.223, -8}, {66.223, 16}}, color = {1, 37, 163})); + connect(parCrossFractionalRateA.y, inducedGrowthA.u2) annotation(Line(visible = true, origin = {-47.333, 5}, points = {{7.333, 60}, {7.333, -30}, {-14.667, -30}}, color = {1, 37, 163})); + connect(growingA1.y2, totalRateA.u1) annotation(Line(visible = true, origin = {-39.833, 25.87}, points = {{-59.667, -0.87}, {29.833, -0.87}, {31.833, -0.87}}, color = {1, 37, 163})); + connect(growingA2.y2, totalRateA.u2) annotation(Line(visible = true, origin = {-34.375, 2.5}, points = {{-65.125, -17.5}, {19.375, -17.5}, {19.375, 17.5}, {26.375, 17.5}}, color = {1, 37, 163})); + connect(growingA3.y2, totalRateA.u3) annotation(Line(visible = true, origin = {-39.375, -20}, points = {{-60.125, -35}, {14.375, -35}, {14.375, 35}, {31.375, 35}}, color = {1, 37, 163})); + connect(totalRateA.y, y_A) annotation(Line(visible = true, origin = {49.341, 50}, points = {{-41.979, -30}, {-34.341, -30}, {-34.341, 30}, {110.659, 30}}, color = {1, 37, 163})); + connect(totalRateA.y, y1_A) annotation(Line(visible = true, origin = {49.341, 30}, points = {{-41.978, -10}, {-34.341, -10}, {-34.341, 10}, {110.659, 10}}, color = {1, 37, 163})); + connect(growingB1.massPort, portB) annotation(Line(visible = true, origin = {135, 15}, points = {{-15, 10}, {-5, 10}, {-5, -15}, {13.464, -15}}, color = {128, 0, 128})); + connect(parGrowthRateB.y, growingB1.u) annotation(Line(visible = true, origin = {112.5, 51.25}, points = {{7.5, 12.75}, {7.5, -1.25}, {-7.5, -1.25}, {-7.5, -16.25}}, color = {1, 37, 163})); + connect(parFractionalRateB.y, growingB2.u) annotation(Line(visible = true, origin = {92.5, 21.25}, points = {{-12.5, 43.75}, {-12.5, -11.25}, {12.5, -11.25}, {12.5, -16.25}}, color = {1, 37, 163})); + connect(growingB2.massPort, portB) annotation(Line(visible = true, origin = {135, -5}, points = {{-15, 0}, {-5, 0}, {-5, 5}, {25, 5}}, color = {128, 0, 128})); + connect(growingB3.massPort, portB) annotation(Line(visible = true, origin = {135, -25}, points = {{-15, -30}, {-5, -30}, {-5, 25}, {25, 25}}, color = {128, 0, 128})); + connect(inducedGrowthB.y, growingB3.u) annotation(Line(visible = true, origin = {95.787, -31.667}, points = {{-18.425, 6.667}, {9.213, 6.667}, {9.213, -13.333}}, color = {1, 37, 163})); + connect(stockA.stock, inducedGrowthB.u1) annotation(Line(visible = true, origin = {-27.58, -40.2}, points = {{-109.667, 29.2}, {-109.667, -29.8}, {67.58, -29.8}, {67.58, 10.2}, {89.58, 10.2}}, color = {1, 37, 163})); + connect(totalRateB.y, y1_B) annotation(Line(visible = true, origin = {79.341, -40}, points = {{-31.978, 40}, {-24.341, 40}, {-24.341, -40}, {80.659, -40}}, color = {1, 37, 163})); + connect(totalRateB.y, y_B) annotation(Line(visible = true, origin = {79.341, -20}, points = {{-31.979, 20}, {-24.341, 20}, {-24.341, -20}, {80.659, -20}}, color = {1, 37, 163})); + connect(growingB3.y2, totalRateB.u3) annotation(Line(visible = true, origin = {45.375, -32.5}, points = {{54.125, -27.5}, {-20.375, -27.5}, {-20.375, 27.5}, {-13.375, 27.5}}, color = {1, 37, 163})); + connect(growingB2.y2, totalRateB.u2) annotation(Line(visible = true, origin = {55.25, -21.667}, points = {{44.25, 11.667}, {34.75, 11.667}, {34.75, -28.333}, {-45.25, -28.333}, {-45.25, 21.667}, {-23.25, 21.667}}, color = {1, 37, 163})); + connect(growingB1.y2, totalRateB.u1) annotation(Line(visible = true, origin = {45.375, 12.5}, points = {{54.125, 7.5}, {-20.375, 7.5}, {-20.375, -7.5}, {-13.375, -7.5}}, color = {1, 37, 163})); + connect(parCrossFractionalRateB.y, inducedGrowthB.u2) annotation(Line(visible = true, origin = {37, 21.7}, points = {{3, 43.3}, {3, 23.3}, {-17, 23.3}, {-17, -41.7}, {25, -41.7}}, color = {1, 37, 163})); + connect(dataIn.a_0, u_growthRate_A) annotation(Line(visible = true, origin = {-123.333, 78.333}, points = {{-21.667, 6.667}, {18.333, 6.667}, {18.333, -13.333}}, color = {0, 0, 128})); + connect(u_growthRate_A, growingA1.u) annotation(Line(visible = true, origin = {-105, 52.5}, points = {{0, 12.5}, {0, -12.5}}, color = {1, 37, 163})); + connect(dataIn.a_A, u_fractionalGrowthRate_A) annotation(Line(visible = true, origin = {-96.667, 78.333}, points = {{-48.333, 6.667}, {31.667, 6.667}, {31.667, -13.333}}, color = {0, 0, 128})); + connect(u_fractionalGrowthRate_A, growingA2.u) annotation(Line(visible = true, origin = {-85.646, 21.921}, points = {{20.646, 43.079}, {20.323, 18.079}, {5.646, 18.079}, {5.646, -11.921}, {-19.354, -11.921}, {-19.354, -21.921}}, color = {1, 37, 163})); + connect(dataIn.a_B, u_growthRate_A_per_B) annotation(Line(visible = true, origin = {-70, 78.333}, points = {{-75, 6.667}, {45, 6.667}, {45, -13.333}}, color = {0, 0, 128})); + connect(u_growthRate_A_per_B, inducedGrowthA.u2) annotation(Line(visible = true, origin = {-38.4, 19}, points = {{13.4, 46}, {13.4, 21}, {-1.6, 21}, {-1.6, -44}, {-23.6, -44}}, color = {1, 37, 163})); + connect(u_growthRate_B_per_A, inducedGrowthB.u2) annotation(Line(visible = true, origin = {34, 8.333}, points = {{-14, 56.667}, {-14, -28.333}, {28, -28.333}}, color = {1, 37, 163})); + connect(dataIn.b_A, u_growthRate_B_per_A) annotation(Line(visible = true, origin = {-40, 78.333}, points = {{-105, 6.667}, {60, 6.667}, {60, -13.333}}, color = {0, 0, 128})); + connect(u_fractionalGrowthRate_B, growingB2.u) annotation(Line(visible = true, origin = {81.667, 30}, points = {{-21.667, 35}, {-21.667, 15}, {-1.667, 15}, {-1.667, -20}, {23.333, -20}, {23.333, -25}}, color = {1, 37, 163})); + connect(dataIn.b_B, u_fractionalGrowthRate_B) annotation(Line(visible = true, origin = {-13.333, 78.333}, points = {{-131.667, 6.667}, {73.333, 6.667}, {73.333, -13.333}}, color = {0, 0, 128})); + connect(u_growthRate_B, growingB1.u) annotation(Line(visible = true, origin = {105, 50}, points = {{0, 15}, {0, -15}}, color = {1, 37, 163})); + connect(dataIn.b_0, u_growthRate_B) annotation(Line(visible = true, origin = {16.667, 78.333}, points = {{-161.667, 6.667}, {88.333, 6.667}, {88.333, -13.333}}, color = {0, 0, 128})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The LinearInteraction component allows to model the interaction between two stocks A (portA) and A (portB) as linear equations:

+

\"Formula.svg\"

+

Note: Capital letters were chosen to represent the stocks (state variables) connected at portA and portB in the formula above. Also dot notation is used for a stock's rate of flow—its first derivative with respect to time.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CoefficientUnitDescription
a_0 +

amount of A per second

+
+

Rate of growth for stock A

+
+

b_0

+
+

amount of B per second

+
+

Rate of growth for stock B

+
+

a_A

+
+

1/s

+
+

Fractional rate of growth for stock A
(e.g. the self-coupling coefficient for A)

+
+

b_B

+
+

1/s

+
+

Fractional rate of growth for stock B
(e.g.the self-coupling coefficient for B)

+
+

a_B

+
+

amount of A per amount of B per second

+
+

Rate of growth for stock A per stock B
(e.g. the coupling-cofficient for B towards A)

+
+

b_A

+
+

amount of B per amount of A per second

+
+

Rate of growth for stock B per stock A
(e.g. the coupling-coefficient for A towards B)

+
+

The coefficients can be given as parameters or as variables via the expandable connector dataIn.

+


Examples

+

A linear harmonic oscillator can be modeled as a special case of linear interactions where the rates for the mutual influences (e.g. fractionalGrowthRate_B_per_A and fractionalGrowthRate_A_per_B) are negative. In that case, positive stock A will decrease stock B and vice versa.

+

The Linear Interaction can be used to model Strogatz' famous model for the dynamics of a love affair (conspicuously between \"Romeo\" and \"Juliet\") as shown in →LoveHateDynamics [16].

+

See also

+

NonlinearInteractionComplexInteraction

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, 75}, textColor = {0, 128, 0}, extent = {{-100, -12}, {100, 12}}, textString = "Linear", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end LinearInteraction; diff --git a/BusinessSimulation/Flows/Interaction/LotkaVolterra.mo b/BusinessSimulation/Flows/Interaction/LotkaVolterra.mo new file mode 100644 index 0000000..2cc5a1b --- /dev/null +++ b/BusinessSimulation/Flows/Interaction/LotkaVolterra.mo @@ -0,0 +1,115 @@ +within BusinessSimulation.Flows.Interaction; + +model LotkaVolterra "The Lotka-Volterra equations to model predator-prey-dynamics" + import BusinessSimulation.Units.Rate; + extends Interfaces.Basics.GenericFlow; + extends Interfaces.Basics.Interaction4SO; + extends Icons.Interaction; + InputConnector dataIn if not (hasConstantAlpha and hasConstantBeta and hasConstantGamma and hasConstantDelta) "Inputs for predator-prey model" annotation(Placement(visible = true, transformation(origin = {-145, 70}, extent = {{-10, -10}, {10, 10}}, rotation = -360), iconTransformation(origin = {0, 100}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + parameter Rate alpha = 0 "Fractional growth rate of prey population (A)" annotation(Dialog(enable = hasConstantAlpha)); + parameter Rate beta = 0 "Fractional rate of decline for prey population (A) per predator" annotation(Dialog(enable = hasConstantBeta)); + parameter Rate gamma = 0 "Fractional rate of decline for predator population (B)" annotation(Dialog(enable = hasConstantGamma)); + parameter Rate delta = 0 "Fractional rate of growth for predator population (B) per prey" annotation(Dialog(enable = hasConstantDelta)); + parameter Boolean hasConstantAlpha = false "= true, if the constant parameter value is to be used instead of the input connector" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean hasConstantBeta = false "= true, if the constant parameter value is to be used instead of the input connector" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean hasConstantGamma = false "= true, if the constant parameter value is to be used instead of the input connector" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean hasConstantDelta = false "= true, if the constant parameter value is to be used instead of the input connector" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + + expandable connector InputConnector "DataBus for inputs" + extends Icons.DataInPort; + Rate alpha "Fractional growth rate of prey population (A)"; + Rate beta "Fractional rate of decline for prey population (A) per predator"; + Rate delta "Fractional rate of growth for predator population (B) per prey"; + Rate gamma "Fractional rate of decline for predator population (B)"; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

alpha, beta, gamma, delta

")); + end InputConnector; +protected + ComplexInteraction complexInteraction annotation(Placement(visible = true, transformation(origin = {0, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ConstantConverterRate zeroRate(value = 0) "Zero rate input" annotation(Placement(visible = true, transformation(origin = {-110, -20}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Gain fractionalGrowthRatePredator(c = -1) "Convert rate of delince to growth rate" annotation(Placement(visible = true, transformation(origin = {21.803, 30}, extent = {{-10, 10}, {10, -10}}, rotation = -540))); + Converters.Gain couplingFactorForPrey(c = -1) "Convert rate of delince to growth rate" annotation(Placement(visible = true, transformation(origin = {-45, 30}, extent = {{-10, 10}, {10, -10}}, rotation = -180))); + Converters.ConstantConverterRate parAlpha(value = alpha) if hasConstantAlpha "Constant alpha (optional)" annotation(Placement(visible = true, transformation(origin = {-110, 50}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.ConstantConverterRate parBeta(value = beta) if hasConstantBeta "Constant beta (optional)" annotation(Placement(visible = true, transformation(origin = {-50, 50}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.ConstantConverterRate parGamma(value = gamma) if hasConstantGamma "Constant gamma (optional)" annotation(Placement(visible = true, transformation(origin = {10, 50}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.ConstantConverterRate parDelta(value = delta) if hasConstantDelta "Constant delta (optional)" annotation(Placement(visible = true, transformation(origin = {70, 50}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Interfaces.Connectors.RealOutput u_alpha if not hasConstantAlpha annotation(Placement(visible = true, transformation(origin = {-95, 55}, extent = {{-10, -10}, {10, 10}}, rotation = -90), iconTransformation(origin = {-50, 66.667}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealOutput u_beta if not hasConstantBeta annotation(Placement(visible = true, transformation(origin = {-30, 55}, extent = {{-10, -10}, {10, 10}}, rotation = -90), iconTransformation(origin = {-50, 66.667}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealOutput u_gamma if not hasConstantGamma annotation(Placement(visible = true, transformation(origin = {30, 55}, extent = {{-10, -10}, {10, 10}}, rotation = -90), iconTransformation(origin = {-50, 66.667}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealOutput u_delta if not hasConstantDelta annotation(Placement(visible = true, transformation(origin = {90, 55}, extent = {{-10, -10}, {10, 10}}, rotation = -90), iconTransformation(origin = {-50, 66.667}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.DataBus dataBus annotation(Placement(visible = true, transformation(origin = {-80, 15}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-43.333, 16.667}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(dataIn.alpha, u_alpha) annotation(Line(visible = true, origin = {-116.667, 63.333}, points = {{-28.333, 6.667}, {21.667, 6.667}, {21.667, -8.333}}, color = {0, 0, 128})); + connect(dataIn.beta, u_beta) annotation(Line(visible = true, origin = {-73.333, 65}, points = {{-71.667, 5}, {43.333, 5}, {43.333, -10}}, color = {0, 0, 128})); + connect(dataIn.gamma, u_gamma) annotation(Line(visible = true, origin = {-33.333, 65}, points = {{-111.667, 5}, {63.333, 5}, {63.333, -10}}, color = {0, 0, 128})); + connect(dataIn.delta, u_delta) annotation(Line(visible = true, origin = {6.667, 65}, points = {{-151.667, 5}, {83.333, 5}, {83.333, -10}}, color = {0, 0, 128})); + connect(portA, complexInteraction.portA) annotation(Line(visible = true, origin = {-37.698, -23.214}, points = {{-110.636, 23.214}, {27.698, 23.214}}, color = {128, 0, 128})); + connect(complexInteraction.portB, portB) annotation(Line(visible = true, origin = {79.232, 0}, points = {{-69.232, 0}, {69.232, 0}}, color = {128, 0, 128})); + connect(complexInteraction.y1_B, y1_B) annotation(Line(visible = true, origin = {82.625, -42.5}, points = {{-72.125, 37.5}, {-2.625, 37.5}, {-2.625, -37.5}, {77.375, -37.5}}, color = {1, 37, 163})); + connect(complexInteraction.y1_B, y_B) annotation(Line(visible = true, origin = {82.625, -22.5}, points = {{-72.125, 17.5}, {-2.625, 17.5}, {-2.625, -17.5}, {77.375, -17.5}}, color = {1, 37, 163})); + connect(complexInteraction.y_A, y_A) annotation(Line(visible = true, origin = {50, 56.8}, points = {{-55, -46.4}, {-55, 23.2}, {110, 23.2}}, color = {1, 37, 163})); + connect(complexInteraction.y_A, y1_A) annotation(Line(visible = true, origin = {78, 50.08}, points = {{-83, -39.68}, {-83, 29.92}, {42, 29.92}, {42, -10.08}, {82, -10.08}}, color = {1, 37, 163})); + connect(complexInteraction.dataIn, dataBus) annotation(Line(visible = true, origin = {-26.667, 13.333}, points = {{26.667, -3.333}, {26.667, 1.667}, {-53.333, 1.667}}, color = {0, 0, 128})); + connect(u_beta, couplingFactorForPrey.u) annotation(Line(visible = true, origin = {-32.333, 38.333}, points = {{2.333, 16.667}, {2.333, -8.333}, {-4.667, -8.333}}, color = {1, 37, 163})); + connect(parBeta.y, couplingFactorForPrey.u) annotation(Line(visible = true, origin = {-39.4, 35}, points = {{-10.6, 9}, {-10.6, 5}, {9.4, 5}, {9.4, -5}, {2.4, -5}}, color = {1, 37, 163})); + connect(parGamma.y, fractionalGrowthRatePredator.u) annotation(Line(visible = true, origin = {25.961, 37}, points = {{-15.961, 7}, {-15.961, 3}, {14.039, 3}, {14.039, -7}, {3.842, -7}}, color = {1, 37, 163})); + connect(u_gamma, fractionalGrowthRatePredator.u) annotation(Line(visible = true, origin = {33.961, 39}, points = {{-3.961, 16}, {-3.961, 1}, {6.039, 1}, {6.039, -9}, {-4.158, -9}}, color = {1, 37, 163})); + // feeding the dataBus + connect(u_alpha, dataBus.a_A) annotation(Line(visible = true, origin = {-90, 28.333}, points = {{-5, 26.667}, {-5, -13.333}, {10, -13.333}}, color = {1, 37, 163})); + connect(parAlpha.y, dataBus.a_A) annotation(Line(visible = true, origin = {-100, 25}, points = {{-10, 20}, {-10, -10}, {20, -10}}, color = {1, 37, 163})); + connect(couplingFactorForPrey.y, dataBus.a_AB) annotation(Line(visible = true, origin = {-68.25, 22.5}, points = {{15.25, 7.5}, {-1.75, 7.5}, {-1.75, -7.5}, {-11.75, -7.5}}, color = {1, 37, 163})); + connect(fractionalGrowthRatePredator.y, dataBus.b_B) annotation(Line(visible = true, origin = {-26.549, 22.5}, points = {{40.352, 7.5}, {6.549, 7.5}, {6.549, -7.5}, {-53.451, -7.5}}, color = {1, 37, 163})); + connect(parDelta.y, dataBus.b_AB) annotation(Line(visible = true, origin = {20, 25}, points = {{50, 20}, {50, -10}, {-100, -10}}, color = {1, 37, 163})); + connect(u_delta, dataBus.b_AB) annotation(Line(visible = true, origin = {33.333, 28.333}, points = {{56.667, 26.667}, {56.667, -13.333}, {-113.333, -13.333}}, color = {1, 37, 163})); + // setting parameters a_0,b_0,a_B,b_A to zero + connect(zeroRate.y, dataBus.a_0) annotation(Line(visible = true, origin = {-88.333, -8.333}, points = {{-16.667, -11.667}, {8.333, -11.667}, {8.333, 23.333}}, color = {1, 37, 163})); + connect(zeroRate.y, dataBus.a_B) annotation(Line(visible = true, origin = {-88.333, -8.333}, points = {{-16.667, -11.667}, {8.333, -11.667}, {8.333, 23.333}}, color = {1, 37, 163})); + connect(zeroRate.y, dataBus.b_0) annotation(Line(visible = true, origin = {-88.333, -8.333}, points = {{-16.667, -11.667}, {8.333, -11.667}, {8.333, 23.333}}, color = {1, 37, 163})); + connect(zeroRate.y, dataBus.b_A) annotation(Line(visible = true, origin = {-88.333, -8.333}, points = {{-16.667, -11.667}, {8.333, -11.667}, {8.333, 23.333}}, color = {1, 37, 163})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

These are the classical Lotka-Volterra equations describing predator-prey-dynamics in an idealized way [17]. The dynamics for the prey population (portA) and the predator population (portB) are given by the following equations:

+

\"Formula.svg\"

+

Note: Capital letters were chosen to represent the stocks (state variables) connected at portA and portB in the formula above. Also dot notation is used for a stock's rate of flow—its first derivative with respect to time.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CoefficientUnitDescription
alpha1 per second +

fractional growth rate for prey population

+
beta1 per second per amount of B +

fractional rate of decline for prey population per predator

+
gamma1 per second +

fractional rate of decline for predator population

+
+

delta

+
1 per second per amount of Afractional rate of groth for predator population per prey
+

See also

+

ComplexInteraction

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {-35.498, 33.689}, textColor = {128, 128, 128}, extent = {{-34.502, -12}, {34.502, 12}}, textString = "Prey", fontName = "Lato", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {17.887, -46.189}, textColor = {128, 128, 128}, extent = {{-44.005, -12}, {44.005, 12}}, textString = "Predator", fontName = "Lato", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {0, 75}, textColor = {0, 128, 0}, extent = {{-100, -12}, {100, 12}}, textString = "Lotka-Volterra", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}), graphics = {Text(visible = true, origin = {-123.379, 7.594}, textColor = {192, 192, 192}, extent = {{-16.621, -9.24}, {16.621, 9.24}}, textString = "PREY", fontSize = 18, horizontalAlignment = TextAlignment.Left), Text(visible = true, origin = {119.167, 7.28}, textColor = {192, 192, 192}, extent = {{-20.833, -9.24}, {20.833, 9.24}}, textString = "PREDATOR", fontSize = 18, horizontalAlignment = TextAlignment.Right), Text(visible = true, origin = {-90, -34.24}, textColor = {192, 192, 192}, extent = {{-40, -9.24}, {40, 9.24}}, textString = "a_0 = b_0 = a_B = b_A = 0", fontSize = 18, horizontalAlignment = TextAlignment.Left), Text(visible = true, origin = {-90.879, 75}, textColor = {192, 192, 192}, extent = {{-24.121, -9.24}, {24.121, 9.24}}, textString = "a_A = alpha", fontSize = 18, horizontalAlignment = TextAlignment.Left), Text(visible = true, origin = {-29.121, 75}, textColor = {192, 192, 192}, extent = {{-24.121, -9.24}, {24.121, 9.24}}, textString = "a_AB = - beta", fontSize = 18, horizontalAlignment = TextAlignment.Left), Text(visible = true, origin = {29.121, 75}, textColor = {192, 192, 192}, extent = {{-24.121, -9.24}, {24.121, 9.24}}, textString = "b_B = - gamma", fontSize = 18, horizontalAlignment = TextAlignment.Left), Text(visible = true, origin = {89.121, 75}, textColor = {192, 192, 192}, extent = {{-24.121, -9.24}, {24.121, 9.24}}, textString = "b_AB = delta", fontSize = 18, horizontalAlignment = TextAlignment.Left)})); +end LotkaVolterra; diff --git a/BusinessSimulation/Flows/Interaction/NonlinearInteraction.mo b/BusinessSimulation/Flows/Interaction/NonlinearInteraction.mo new file mode 100644 index 0000000..898c15b --- /dev/null +++ b/BusinessSimulation/Flows/Interaction/NonlinearInteraction.mo @@ -0,0 +1,87 @@ +within BusinessSimulation.Flows.Interaction; + +model NonlinearInteraction "Outflows depend upon the product of the stocks and a factor" + import BusinessSimulation.Units.Rate; + extends Interfaces.Basics.GenericFlow; + extends Interfaces.Basics.Interaction4SO; + extends Icons.Interaction; + InputConnector dataIn if not (hasConstantFactorA and hasConstantFactorB) annotation(Placement(visible = true, transformation(origin = {-145, 70}, extent = {{-10, -10}, {10, 10}}, rotation = -360), iconTransformation(origin = {0, 100}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + parameter Rate a_AB = 0 "Constant fractional rate for the netflow to A per unit of B (nonlinear coupling factor)" annotation(Dialog(enable = hasConstantFactorA)); + parameter Rate b_AB = 0 "Constant fractional rate for the netflow to B per unit of A (nonlinear coupling factor)" annotation(Dialog(enable = hasConstantFactorB)); + parameter Boolean hasConstantFactorA = false "= true, if the coupling factor for A is given by the constant parameter" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean hasConstantFactorB = false "= true, if the coupling factor for B is given by the constant parameter" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + + expandable connector InputConnector "Data bus for inputs" + extends Icons.DataInPort; + Real a_AB "Fractional rate for the netflow to stock A per amount of B"; + Real b_AB "Fractional rate for the netflow to stock B per amount of B"; + annotation(Diagram(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}))); + end InputConnector; +protected + SourcesOrSinks.ExogenousChange netFlowA "Net flow to A" annotation(Placement(visible = true, transformation(origin = {-100, -0}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + SourcesOrSinks.ExogenousChange netFlowB "Net flow to B" annotation(Placement(visible = true, transformation(origin = {100, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Sensors.FlowPortSensor levelA "Amount in stock A" annotation(Placement(visible = true, transformation(origin = {-130, 0}, extent = {{-10, 10}, {10, -10}}, rotation = 0))); + Sensors.FlowPortSensor levelB "Amount in stock B" annotation(Placement(visible = true, transformation(origin = {130, 0}, extent = {{-10, 10}, {10, -10}}, rotation = 0))); + Converters.Product_2 product_A_B "Product of A and B" annotation(Placement(visible = true, transformation(origin = {0, 0}, extent = {{-10, -10}, {10, 10}}, rotation = -270))); + Converters.Product_2 netRateA "Rate of netflow A (positive = inflow)" annotation(Placement(visible = true, transformation(origin = {-70, 20}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Converters.Product_2 netRateB "Rate of netflow B (positive = inflow)" annotation(Placement(visible = true, transformation(origin = {70, 20}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ConstantConverterRate parFactorA(value = a_AB) if hasConstantFactorA "Constant fractional rate A" annotation(Placement(visible = true, transformation(origin = {-30, 50}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.ConstantConverterRate parFactorB(value = b_AB) if hasConstantFactorB "Constant fractional rate B" annotation(Placement(visible = true, transformation(origin = {30, 50}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Interfaces.Connectors.RealOutput u_a_AB if not hasConstantFactorA "Nonlinear coupling factor for A" annotation(Placement(visible = true, transformation(origin = {-55, 50}, extent = {{-10, -10}, {10, 10}}, rotation = -90), iconTransformation(origin = {-60, 72.222}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealOutput u_b_AB if not hasConstantFactorB "Nonlinear coupling factor for B" annotation(Placement(visible = true, transformation(origin = {50, 50}, extent = {{-10, -10}, {10, 10}}, rotation = -90), iconTransformation(origin = {-60, 72.222}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(portA, netFlowA.massPort) annotation(Line(visible = true, origin = {-135, -0}, points = {{-25, 0}, {25, -0}}, color = {128, 0, 128})); + connect(netFlowB.massPort, portB) annotation(Line(visible = true, origin = {135, 0}, points = {{-25, 0}, {25, -0}}, color = {128, 0, 128})); + connect(levelA.flowPort, portA) annotation(Line(visible = true, origin = {-145, 0}, points = {{15, 0}, {-15, 0}}, color = {128, 0, 128})); + connect(levelB.flowPort, portB) annotation(Line(visible = true, origin = {145, 0}, points = {{-15, 0}, {15, 0}}, color = {128, 0, 128})); + connect(levelA.stock, product_A_B.u1) annotation(Line(visible = true, origin = {-67.476, -14.75}, points = {{-62.475, 3.75}, {-62.475, -5.25}, {62.476, -5.25}, {62.476, 6.75}}, color = {1, 37, 163})); + connect(levelB.stock, product_A_B.u2) annotation(Line(visible = true, origin = {67.524, -14.75}, points = {{62.525, 3.75}, {62.525, -5.25}, {-62.524, -5.25}, {-62.524, 6.75}}, color = {1, 37, 163})); + connect(product_A_B.y, netRateA.u2) annotation(Line(visible = true, origin = {-20.667, 12.454}, points = {{20.667, -5.092}, {20.667, 2.546}, {-41.333, 2.546}}, color = {1, 37, 163})); + connect(netRateA.y, netFlowA.u) annotation(Line(visible = true, origin = {-89.121, 16.667}, points = {{11.758, 3.333}, {-5.879, 3.333}, {-5.879, -6.667}}, color = {1, 37, 163})); + connect(parFactorA.y, netRateA.u1) annotation(Line(visible = true, origin = {-40.667, 31.667}, points = {{10.667, 13.333}, {10.667, -6.667}, {-21.333, -6.667}}, color = {1, 37, 163})); + connect(parFactorB.y, netRateB.u1) annotation(Line(visible = true, origin = {40.667, 31.667}, points = {{-10.667, 13.333}, {-10.667, -6.667}, {21.333, -6.667}}, color = {1, 37, 163})); + connect(product_A_B.y, netRateB.u2) annotation(Line(visible = true, origin = {20.667, 12.454}, points = {{-20.667, -4.454}, {-20.667, 2.546}, {41.333, 2.546}}, color = {1, 37, 163})); + connect(netRateB.y, netFlowB.u) annotation(Line(visible = true, origin = {89.121, 16.667}, points = {{-11.758, 3.333}, {5.879, 3.333}, {5.879, -6.667}}, color = {1, 37, 163})); + connect(netFlowB.y2, y_B) annotation(Line(visible = true, origin = {102.375, -22.5}, points = {{-12.875, 17.5}, {-22.375, 17.5}, {-22.375, -17.5}, {57.625, -17.5}}, color = {1, 37, 163})); + connect(netFlowB.y2, y1_B) annotation(Line(visible = true, origin = {102.375, -42.5}, points = {{-12.875, 37.5}, {-22.375, 37.5}, {-22.375, -37.5}, {57.625, -37.5}}, color = {1, 37, 163})); + connect(netFlowA.y, y_A) annotation(Line(visible = true, origin = {-16.667, 56.8}, points = {{-88.333, -46.4}, {-88.333, 23.2}, {176.667, 23.2}}, color = {1, 37, 163})); + connect(netFlowA.y, y1_A) annotation(Line(visible = true, origin = {-16.667, 30.133}, points = {{-88.333, -19.733}, {-88.333, 9.867}, {176.667, 9.867}}, color = {1, 37, 163})); + connect(dataIn.a_AB, u_a_AB) annotation(Line(visible = true, origin = {-92.366, 66.667}, points = {{-52.634, 3.333}, {37.366, 3.333}, {37.366, -16.667}}, color = {0, 0, 128})); + connect(u_a_AB, netRateA.u1) annotation(Line(visible = true, origin = {-57.333, 33.333}, points = {{2.333, 16.667}, {2.333, -8.333}, {-4.667, -8.333}}, color = {1, 37, 163})); + connect(dataIn.b_AB, u_b_AB) annotation(Line(visible = true, origin = {-20, 66.667}, points = {{-125, 3.333}, {70, 3.333}, {70, -16.667}}, color = {0, 0, 128})); + connect(u_b_AB, netRateB.u1) annotation(Line(visible = true, origin = {54, 33.333}, points = {{-4, 16.667}, {-4, -8.333}, {8, -8.333}}, color = {1, 37, 163})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The NonlinearInteraction can be used by itself or in combination with the →LinearInteraction flow to model more complex interactions. The netflows to the connected stocks A (portA) and B (portB) are given by the following equations:

+

\"Formula.svg\"

+

Note: Capital letters were chosen to represent the stocks (state variables) connected at portA and portB in the formula above. Also dot notation is used for a stock's rate of flow—its first derivative with respect to time.

+ + + + + + + + + + + + + + + + + + +
CoefficientUnitDescription
a_AB1 per second per amount of B +

Factor used to determine the net flow to A (positive rate = inflow)

+
b_AB1 per second per amount of A +

Factor used to determine the net flow to B (positive rate = inflow)

+
+

The coefficients can be given as parameters or as variables via the expandable connector dataIn.

+

Examples

+

A nonlinear component is typically found in predator-prey models or models of infectious diseases, where the exponential growth rate for a population depends upon the size of another population (e.g. prey or susceptible population).

+

See also

+

LinearInteractionComplexInteraction

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, 75}, textColor = {0, 128, 0}, extent = {{-100, -12}, {100, 12}}, textString = "Nonlinear", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end NonlinearInteraction; diff --git a/BusinessSimulation/Flows/Interaction/package.mo b/BusinessSimulation/Flows/Interaction/package.mo new file mode 100644 index 0000000..5a3d388 --- /dev/null +++ b/BusinessSimulation/Flows/Interaction/package.mo @@ -0,0 +1,14 @@ +within BusinessSimulation.Flows; + +package Interaction "Broken flows modeling the interaction of two stocks" + extends Icons.Package; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Interactions model two stocks with a bidirectional flow at each stock and their interdependencies. Such components already allow to represent more complicated structures like the Lotka-Volterra model of predator-prey-dynamics [17]; there is thus a thin boundary between the classes contained in this package and more complex Actuator subsystems contained in the Molecules of Structure package. 

+

See also

+

Actuators

+
+
+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {-2.596, -11.973}, points = {{-72.3, 0}, {72.3, 0}}, color = {255, 255, 255}, thickness = 5), Line(visible = true, origin = {-1.216, 11.777}, points = {{-73.637, 0}, {73.637, 0}}, color = {255, 255, 255}, thickness = 5), Polygon(visible = true, origin = {72.114, -0.25}, rotation = -450, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-22.295, -7.943}, {22.191, -7.943}, {0.104, 15.886}}), Ellipse(visible = true, origin = {1.899, 0}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-15.107, -15.107}, {15.107, 15.107}}), Polygon(visible = true, origin = {-74.886, -0.25}, rotation = 450, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{22.295, -7.943}, {-22.191, -7.943}, {-0.104, 15.886}}), Rectangle(visible = true, origin = {40, 0}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-24.394, -11.346}, {24.394, 11.346}}), Ellipse(visible = true, origin = {1.691, 0}, lineColor = {76, 112, 136}, fillColor = {76, 112, 136}, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-10.924, -10.924}, {10.924, 10.924}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Interaction; diff --git a/BusinessSimulation/Flows/Interaction/package.order b/BusinessSimulation/Flows/Interaction/package.order new file mode 100644 index 0000000..d886d9c --- /dev/null +++ b/BusinessSimulation/Flows/Interaction/package.order @@ -0,0 +1,6 @@ +BrokenTransition +BrokenTransitionPull +ComplexInteraction +LinearInteraction +LotkaVolterra +NonlinearInteraction diff --git a/BusinessSimulation/Flows/Unidirectional/CheckValveInflow.mo b/BusinessSimulation/Flows/Unidirectional/CheckValveInflow.mo new file mode 100644 index 0000000..0b833d3 --- /dev/null +++ b/BusinessSimulation/Flows/Unidirectional/CheckValveInflow.mo @@ -0,0 +1,33 @@ +within BusinessSimulation.Flows.Unidirectional; + +model CheckValveInflow "Flow is only passed on if it fills the connected stock" + extends Icons.Outflow; + extends Interfaces.Basics.ThreeSO_rate; + Interfaces.Connectors.StockPort portA "Stock port to be connected to an inflow that is passed on" annotation(Placement(visible = true, transformation(origin = {-148.052, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-100, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.FlowPort portB "Flow port to pass on the inflow to a connected stock" annotation(Placement(visible = true, transformation(origin = {148.5, -2.69}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {100, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + // portA receives the rate information and passes it on to portB observing restrictions + // portB receives the level information and passes it on to portA + portA.stock = portB.stock; + portB.rate = if portA.rate > 0 and not portB.stopInflow then -portA.rate else 0; + // set the boolean flags for the stock port + portA.stopOutflow = true; + portA.stopInflow = portB.stopInflow "pass on the inflow-restrictions"; + // report a positive rate + y = -portB.rate; + y1 = y; + y2 = y; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The CheckValveInflow is actually a transceiver that simply passes on a connected flow if that flow fills the connected stock (portB). This will most often be relevant for more complex subsystems where the flows being connected may not be clear in advance and where this element allows to avoid unwanted draining.

+

Implementation

+ + +

See also

+

CheckValveOutflow

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {7.939, 4.004}, points = {{-11.1, 5.996}, {11.1, -5.996}}, color = {255, 0, 0}, thickness = 2.5, arrowSize = 0), Ellipse(visible = true, origin = {-5.759, 11.642}, lineColor = {0, 128, 0}, fillColor = {255, 0, 0}, fillPattern = FillPattern.Solid, extent = {{-4.241, -4.241}, {4.241, 4.241}}), Line(visible = true, origin = {-5.977, -9}, points = {{0, 4.985}, {0, -4.985}}, color = {255, 0, 0}, thickness = 2.5, arrowSize = 0), Text(visible = true, origin = {0, 75}, textColor = {0, 128, 0}, extent = {{-100, -12}, {100, 12}}, textString = "Check Valve In", fontName = "Lato Black", textStyle = {TextStyle.Bold})})); +end CheckValveInflow; diff --git a/BusinessSimulation/Flows/Unidirectional/CheckValveOutflow.mo b/BusinessSimulation/Flows/Unidirectional/CheckValveOutflow.mo new file mode 100644 index 0000000..9d3836f --- /dev/null +++ b/BusinessSimulation/Flows/Unidirectional/CheckValveOutflow.mo @@ -0,0 +1,33 @@ +within BusinessSimulation.Flows.Unidirectional; + +model CheckValveOutflow "Flow is only passed on if it drains the connected stock" + extends Icons.Outflow; + extends Interfaces.Basics.ThreeSO_rate; + Interfaces.Connectors.StockPort portB "Stock port to be connected to an outflow that is passed on" annotation(Placement(visible = true, transformation(origin = {148.5, -2.69}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {100, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.FlowPort portA "Flow port to pass on the outflow to a connected stock" annotation(Placement(visible = true, transformation(origin = {-148.182, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-100, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + // FlowPort (A) receives level information and passes it on to port B + // StockPort (B) receives rate information and passes it on observing restrictions + portB.stock = portA.stock; + portA.rate = if portB.rate < 0 and not portA.stopOutflow then -portB.rate else 0; + // set the boolean flags for the stock port + portB.stopInflow = true; + portB.stopOutflow = portA.stopOutflow "connected stock may also not allow an outflow"; + // report a positive rate + y = portA.rate; + y1 = y; + y2 = y; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The CheckValveOutflow is actually a transceiver that simply passes on a connected flow if that flow drains the connected stock (portA). This will most often be relevant for more complex subsystems where the flows being connected may not be clear in advance and where this element allows to avoid unwanted filling.

+

Implementation

+ + +

See also

+

CheckValveInflow

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {7.939, 4.004}, points = {{-11.1, 5.996}, {11.1, -5.996}}, color = {255, 0, 0}, thickness = 2.5, arrowSize = 0), Ellipse(visible = true, origin = {-5.759, 11.642}, lineColor = {0, 128, 0}, fillColor = {255, 0, 0}, fillPattern = FillPattern.Solid, extent = {{-4.241, -4.241}, {4.241, 4.241}}), Line(visible = true, origin = {-5.977, -9}, points = {{0, 4.985}, {0, -4.985}}, color = {255, 0, 0}, thickness = 2.5, arrowSize = 0), Text(visible = true, origin = {0, 75}, textColor = {0, 128, 0}, extent = {{-100, -12}, {100, 12}}, textString = "Check Valve Out", fontName = "Lato Black", textStyle = {TextStyle.Bold})})); +end CheckValveOutflow; diff --git a/BusinessSimulation/Flows/Unidirectional/Decay.mo b/BusinessSimulation/Flows/Unidirectional/Decay.mo new file mode 100644 index 0000000..76c0074 --- /dev/null +++ b/BusinessSimulation/Flows/Unidirectional/Decay.mo @@ -0,0 +1,87 @@ +within BusinessSimulation.Flows.Unidirectional; + +model Decay "Draining a stock with a given average residence time" + import BusinessSimulation.Units.Time; + extends Icons.UnidirectionalFlow; + extends Interfaces.Basics.GenericFlow; + extends Interfaces.Basics.ThreeSO_rate; + Interfaces.Connectors.RealInput u if not hasConstantResidenceTime "Residence time input" annotation(Placement(visible = true, transformation(origin = {-107.149, 43.598}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-50, 100}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + parameter Time residenceTime(min = 0) = 1 "Constant time of average residence (optional)" annotation(Dialog(enable = hasConstantResidenceTime)); + parameter Boolean hasConstantResidenceTime = false " = true, if the parameter residenceTime will be used instead of the continuous input u" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); +protected + Sensors.FlowPortSensor levelA "Report the amount in the connected stock (Port A)" annotation(Placement(visible = true, transformation(origin = {-125, 13.459}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ConstantConverterTime parDelayTime(value = residenceTime) if hasConstantResidenceTime "Constant delay time (optional)" annotation(Placement(visible = true, transformation(origin = {-102.149, 26.402}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ClipProcessTime clippedResidenceTime "Residence time may not be smaller than dt" annotation(Placement(visible = true, transformation(origin = {-57.149, 43.598}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Division indicatedRate(redeclare replaceable type OutputType = Units.Rate) annotation(Placement(visible = true, transformation(origin = {-20, 65}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Transition draining "Flow from stock A to stock B" annotation(Placement(visible = true, transformation(origin = {-0, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(portA, levelA.flowPort) annotation(Line(visible = true, origin = {-133.215, 6.557}, points = {{-26.785, -6.557}, {8.215, -6.557}, {8.215, 6.902}, {8.215, 6.902}}, color = {128, 0, 128})); + connect(u, clippedResidenceTime.u) annotation(Line(visible = true, origin = {-86.149, 43.598}, points = {{-21, 0}, {21, 0}}, color = {1, 37, 163})); + connect(parDelayTime.y, clippedResidenceTime.u) annotation(Line(visible = true, origin = {-83.899, 35}, points = {{-12.25, -8.598}, {-3.25, -8.598}, {-3.25, 8.598}, {18.75, 8.598}}, color = {1, 37, 163})); + connect(clippedResidenceTime.y, indicatedRate.u2) annotation(Line(visible = true, origin = {-40.362, 51.799}, points = {{-8.787, -8.201}, {-1.787, -8.201}, {-1.787, 8.201}, {12.362, 8.201}}, color = {1, 37, 163})); + connect(levelA.stock, indicatedRate.u1) annotation(Line(visible = true, origin = {-92.634, 54.82}, points = {{-32.317, -30.361}, {-32.317, 15.18}, {64.634, 15.18}}, color = {1, 37, 163})); + connect(indicatedRate.y, draining.u) annotation(Line(visible = true, origin = {-7.333, 46.667}, points = {{-4.667, 18.333}, {2.333, 18.333}, {2.333, -36.667}}, color = {1, 37, 163})); + connect(portA, draining.portA) annotation(Line(visible = true, origin = {-93.97, 18.598}, points = {{-54.364, -18.598}, {83.97, -18.598}}, color = {128, 0, 128})); + connect(draining.portB, portB) annotation(Line(visible = true, origin = {79.232, 0}, points = {{-69.232, -0}, {69.232, 0}}, color = {128, 0, 128})); + connect(draining.y, y1) annotation(Line(visible = true, origin = {56.667, 50.133}, points = {{-51.667, -39.733}, {-51.667, 19.867}, {103.333, 19.867}}, color = {1, 37, 163})); + connect(draining.y, y) annotation(Line(visible = true, origin = {56.667, 23.467}, points = {{-51.667, -13.067}, {-51.667, 6.533}, {103.333, 6.533}}, color = {1, 37, 163})); + connect(draining.y1, y2) annotation(Line(visible = true, origin = {52.625, -27.5}, points = {{-42.125, 22.5}, {-32.625, 22.5}, {-32.625, -22.5}, {107.375, -22.5}}, color = {1, 37, 163})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The stock connected to port A (stockA) will be gradually drained at a rate determined by the average time of residence (residenceTime) in the stock. The rate which drains the stock (draining) is given by:

+

draining = stockA.y / residenceTime

+

Implementation

+

The residence time is clipped to never be smaller than the global parameter dt.

+

Notes

+

The process of decay is essentially exponential decline, since the outflow is a fraction of the stock. The rate of decay thus also exponentially declines towards zero if there is no inflow to the stock, that is connected to port A.

+

If there is no inflow to the stock the level of the stock will be less than α x InitialLevel (0 < α <1) after a time span of - ln(α) × residenceTime.

+

So we can note the following multiples for the residenceTime to calculate the time it takes to drain the stock A to α [%] of its initial level:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
α [%]Time to drain as multiple of the residenceTime
50 +

0.69 ⋅ residenceTime

+
1/e ≈ 37 +

1.0 ⋅ residenceTime

+
10 +

2.3 ⋅ residenceTime

+
5 +

3.0 ⋅ residenceTime

+
1 +

4.6 ⋅ residenceTime

+
0.1 = 1 ‰ +

6.9 ⋅ residenceTime

+
+

The time span it takes to drain the stock by half is called its half life. As can be seen from the equation and table above it is about ln(2) residenceTime ≈ 69% of the (average) residence time.

+

See also

+

ProportionalTransitionExponentialDecay

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {-1.392, -78.316}, textColor = {0, 0, 128}, extent = {{-81.392, -12}, {81.392, 12}}, textString = "residence time", fontName = "Lato", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {0, 75}, textColor = {0, 128, 0}, extent = {{-100, -12}, {100, 12}}, textString = "Decay", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Line(visible = true, origin = {-60.264, -14.352}, rotation = 5.306, points = {{-32.722, 10.515}, {-16.1, -26.782}, {20.02, -35.205}, {44.243, -12.981}}, color = {0, 0, 128}, thickness = 2.5, arrowSize = 0, smooth = Smooth.Bezier), Line(visible = true, origin = {-42.154, -19.63}, rotation = 5.306, points = {{36.522, -45.771}, {43.438, -34.535}, {45.906, -7.964}}, color = {0, 0, 128}, thickness = 2.5, arrowSize = 0, smooth = Smooth.Bezier), Polygon(visible = true, origin = {4, -26.505}, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, points = {{0, 9}, {5, -5}, {-5, -5}}), Polygon(visible = true, origin = {-15.474, -23.17}, rotation = -35, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, points = {{0, 9}, {-5, -5}, {5, -5}})}), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Decay; diff --git a/BusinessSimulation/Flows/Unidirectional/OutflowDynamicStock.mo b/BusinessSimulation/Flows/Unidirectional/OutflowDynamicStock.mo new file mode 100644 index 0000000..f3aebce --- /dev/null +++ b/BusinessSimulation/Flows/Unidirectional/OutflowDynamicStock.mo @@ -0,0 +1,36 @@ +within BusinessSimulation.Flows.Unidirectional; + +model OutflowDynamicStock "Outflow from a dynamic stock—the rate is set by the stock" + import BusinessSimulation.Units.Rate; + extends Interfaces.Basics.GenericFlow_Special; + extends Icons.Outflow; + extends Interfaces.Basics.ThreeSO_rate; +equation + portA.rate = portA.data; + portB.rate = -portA.rate; + // report the rate of flow at Port A + y = portA.rate; + y1 = portA.rate; + y2 = portA.rate; + // outflow must never be negative and the stopInflow flag must not be true at portB + assert(portA.rate >= 0, "Rate of outflow must never be negative", AssertionLevel.warning); + assert(not portB.stopInflow, "There must not be capacity restrictions (stopInflow) for the stock at portB"); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

OutflowDynamicStock can be used to model the outflow from a stock with inherent dynamic behavior (e.g. a conveyor or a higher-order delay). In these cases, the stock will set the flow and \"signal\" it via its →StockPort_Special. + 

+

Implementation

+

Since neither negative outflows (after all, this is a unidirectional flow) nor preventing an outflow by \"stock control\" (e.g. the receiving stock at portB has stopInflow = true) are compatible with this flow element, the following assert conditions will have breaches of these conditions cause errors that will stop the simulation:

+
assert(portA.rate >= 0, \"Rate of outflow must never be negative\");
assert(not portB.stopInflow, \"There must not be capacity restrictions (stopInflow) for the stock at portB\");
+

Notes

+ + +

See also

+

SplitOutflowDynamicStock

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, 75}, textColor = {0, 128, 0}, extent = {{-100, -12}, {100, 12}}, textString = "Outflow", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end OutflowDynamicStock; diff --git a/BusinessSimulation/Flows/Unidirectional/ProportionalTransition.mo b/BusinessSimulation/Flows/Unidirectional/ProportionalTransition.mo new file mode 100644 index 0000000..ba6374e --- /dev/null +++ b/BusinessSimulation/Flows/Unidirectional/ProportionalTransition.mo @@ -0,0 +1,33 @@ +within BusinessSimulation.Flows.Unidirectional; + +model ProportionalTransition "Rate of transition is proportional to the amount in stock A" + import BusinessSimulation.Units.Rate; + extends Icons.UnidirectionalFlow; + extends Interfaces.Basics.GenericFlow; + extends Interfaces.Basics.ThreeSO_rate; + Interfaces.Connectors.RealInput u if not hasConstantRate "Fractional rate input" annotation(Placement(visible = true, transformation(origin = {-145, 60}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-50, 100}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + parameter OutputType fractionalRate(min = 0) = 0 "Constant fractional rate of transition (optional)" annotation(Dialog(enable = hasConstantRate)); + parameter Boolean hasConstantRate = false "= true, if the parameter fractionalRate is to be used instead of the continuous input u" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); +protected + Transition flowing "Flow from A to B" annotation(Placement(visible = true, transformation(origin = {0, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Sensors.FlowPortSensor stockLevelA "Report the amount in the connected stock (Port A)" annotation(Placement(visible = true, transformation(origin = {-125, 13.459}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Product_2 netRate "Rate of flow" annotation(Placement(visible = true, transformation(origin = {-60, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ConstantConverterRate parConstantRate(value = fractionalRate) if hasConstantRate "Constant fractional rate of flow (optional)" annotation(Placement(visible = true, transformation(origin = {-140, 45}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(portA, flowing.portA) annotation(Line(visible = true, origin = {-85, 0}, points = {{-75, 0}, {75, 0}}, color = {128, 0, 128})); + connect(flowing.portB, portB) annotation(Line(visible = true, origin = {79.232, 0}, points = {{-69.232, -0}, {69.232, 0}}, color = {128, 0, 128})); + connect(flowing.y, y) annotation(Line(visible = true, origin = {56.667, 23.467}, points = {{-51.667, -13.067}, {-51.667, 6.533}, {103.333, 6.533}}, color = {1, 37, 163})); + connect(flowing.y, y1) annotation(Line(visible = true, origin = {56.667, 50.133}, points = {{-51.667, -39.733}, {-51.667, 19.867}, {103.333, 19.867}}, color = {1, 37, 163})); + connect(flowing.y1, y2) annotation(Line(visible = true, origin = {52.625, -27.5}, points = {{-42.125, 22.5}, {-32.625, 22.5}, {-32.625, -22.5}, {107.375, -22.5}}, color = {1, 37, 163})); + connect(portA, stockLevelA.flowPort) annotation(Line(visible = true, origin = {-133.215, 6.557}, points = {{-15.119, -6.557}, {8.215, -6.557}, {8.215, 6.902}, {8.215, 6.902}}, color = {128, 0, 128})); + connect(stockLevelA.stock, netRate.u2) annotation(Line(visible = true, origin = {-105.967, 31.486}, points = {{-18.984, -7.027}, {-18.984, 3.514}, {37.967, 3.514}}, color = {1, 37, 163})); + connect(parConstantRate.y, netRate.u1) annotation(Line(visible = true, origin = {-101.5, 45}, points = {{-33.5, 0}, {33.5, 0}}, color = {1, 37, 163})); + connect(u, netRate.u1) annotation(Line(visible = true, origin = {-92, 52.5}, points = {{-53, 7.5}, {12, 7.5}, {12, -7.5}, {24, -7.5}}, color = {1, 37, 163})); + connect(netRate.y, flowing.u) annotation(Line(visible = true, origin = {-20.667, 30}, points = {{-31.333, 10}, {15.667, 10}, {15.667, -20}}, color = {1, 37, 163})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The rate of transition from stock A to stock B will be propotional to the amount in stock A:

rate = fractionalRate ⋅ stockA.y

Notes

Since this is a unidirectional flow, the rate of flow will automatically be set to zero (causing an event), if the given rate of transition is a negative value.

+

See also

+

DecayProportionalSwitching

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {-60.264, -14.352}, rotation = 5.306, points = {{-32.722, 10.515}, {-16.1, -26.782}, {20.02, -35.205}, {44.243, -12.981}}, color = {0, 0, 128}, thickness = 2.5, arrowSize = 0, smooth = Smooth.Bezier), Line(visible = true, origin = {-42.154, -19.63}, rotation = 5.306, points = {{36.522, -45.771}, {43.438, -34.535}, {45.906, -7.964}}, color = {0, 0, 128}, thickness = 2.5, arrowSize = 0, smooth = Smooth.Bezier), Text(visible = true, origin = {0, -76.311}, textColor = {0, 0, 128}, extent = {{-71.477, -12}, {71.477, 12}}, textString = "fractional rate", fontSize = 60, fontName = "Lato", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {0, 75}, textColor = {0, 128, 0}, extent = {{-100, -12}, {100, 12}}, textString = "Proportional Flow", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Polygon(visible = true, origin = {4, -26.505}, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, points = {{0, 9}, {5, -5}, {-5, -5}}), Polygon(visible = true, origin = {-15.474, -23.17}, rotation = -35, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, points = {{0, 9}, {-5, -5}, {5, -5}})}), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end ProportionalTransition; diff --git a/BusinessSimulation/Flows/Unidirectional/SplitOutflowDynamicStock.mo b/BusinessSimulation/Flows/Unidirectional/SplitOutflowDynamicStock.mo new file mode 100644 index 0000000..4b2cd31 --- /dev/null +++ b/BusinessSimulation/Flows/Unidirectional/SplitOutflowDynamicStock.mo @@ -0,0 +1,38 @@ +within BusinessSimulation.Flows.Unidirectional; + +model SplitOutflowDynamicStock "The outflow from a dynamic stock is split into n outflows proportional to the weights given" + extends Interfaces.Basics.OutputTypeChoice_Rate; + extends Icons.Outflow; + Interfaces.Connectors.FlowPort_Special portA "Special port (stock sets rate of flow)" annotation(Placement(visible = true, transformation(origin = {-148.5, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-100, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.FlowMultiPort portB[n] "Flow port" annotation(Placement(visible = true, transformation(origin = {148.5, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {100, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealMultiInput[n] u if not hasConstantWeights "Split fractions (or weights) for the outflow" annotation(Placement(visible = true, transformation(origin = {-145, 80}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-50, 100}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + RealMultiOutput[n] y "Rate information" annotation(Placement(visible = true, transformation(origin = {150, 30}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {50, 104}, extent = {{-10, -10}, {10, 10}}, rotation = -1350))); + RealMultiOutput[n] y1 "Rate information" annotation(Placement(visible = true, transformation(origin = {150, 60}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {105, -50}, extent = {{-10, -10}, {10, 10}}, rotation = -1440))); + RealMultiOutput[n] y2 "Rate information" annotation(Placement(visible = true, transformation(origin = {150, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-105, -50}, extent = {{10, -10}, {-10, 10}}, rotation = 1440))); + parameter Real weights[n] = ones(n) "Vector of weights according to which the total outflow is split proportionally" annotation(Dialog(enable = hasConstantWeights)); + parameter Integer n(min = 2) = 2 "Number of flows to split the outflow into" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean hasConstantWeights = false "If true then the weights are given by the continuous input u" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean shiftInputs = false "= true, if all weights are to be shifted to prevent negative values, otherwise negative values are simply set to zero (fractions.shiftInputs)"; +protected + MoleculesOfStructure.Transceivers.SplitFlow splitFlow(final nout = n, final shiftInputs = shiftInputs, final isSplit = true) annotation(Placement(visible = true, transformation(origin = {-50, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + OutflowDynamicStock flowingOut "Outflow from a dynamic stock" annotation(Placement(visible = true, transformation(origin = {-90, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ConstantConverter parWeights[n](final value = weights) if hasConstantWeights "Constant weights (optional)" annotation(Placement(visible = true, transformation(origin = {-110, 50}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(portA, flowingOut.portA) annotation(Line(visible = true, origin = {-124.25, 0}, points = {{-24.25, 0}, {24.25, 0}}, color = {255, 0, 0})); + connect(flowingOut.portB, splitFlow.stockPort) annotation(Line(visible = true, origin = {-70, 0}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(splitFlow.flowPort, portB) annotation(Line(visible = true, origin = {54.25, 0}, points = {{-94.25, 0}, {94.25, 0}}, color = {128, 0, 128})); + connect(parWeights.y, splitFlow.u) annotation(Line(visible = true, origin = {-71.333, 36.667}, points = {{-32.667, 13.333}, {16.333, 13.333}, {16.333, -26.667}}, color = {1, 37, 163})); + connect(splitFlow.y, y) annotation(Line(visible = true, origin = {19.333, 23.467}, points = {{-64.333, -13.067}, {-64.333, 6.533}, {130.667, 6.533}}, color = {1, 37, 163})); + connect(u, splitFlow.u) annotation(Line(visible = true, origin = {-85, 56.667}, points = {{-60, 23.333}, {30, 23.333}, {30, -46.667}}, color = {1, 37, 163})); + connect(splitFlow.y, y1) annotation(Line(visible = true, origin = {19.333, 43.467}, points = {{-64.333, -33.067}, {-64.333, 16.533}, {130.667, 16.533}}, color = {1, 37, 163})); + connect(splitFlow.y, y2) annotation(Line(visible = true, origin = {3.6, -5.92}, points = {{-48.6, 16.32}, {-48.6, 25.92}, {-23.6, 25.92}, {-23.6, -34.08}, {146.4, -34.08}}, color = {1, 37, 163})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The SplitOutflowDynamicStock is used to model the outflow from a stock with inherent dynamic behavior(e.g. a conveyor or a higher-order delay). In these cases, the stock will set the rate of flow and \"signal\" it via its →StockPort_Special.

+

The total outflow is split proportionally according to given weights either given as a vector of parameters or as a vector of inputs u.

+

Notes

+

The proportional split is done using fractions derived from the weights as described for the converter →ProportionalSplitFactors.

+

See also

+

OutflowDynamicStock

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, -80}, extent = {{-93.103, -12}, {93.103, 12}}, textString = "n = %n", fontName = "Lato", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {88.18, -57.325}, textColor = {0, 128, 0}, extent = {{-13.452, -10}, {13.452, 10}}, textString = "i"), Text(visible = true, origin = {-13.511, -24.505}, textColor = {128, 128, 128}, extent = {{-60.234, -10}, {60.234, 10}}, textString = "outflow to B weight", fontName = "Lato"), Text(visible = true, origin = {1.563, -23.731}, textColor = {128, 128, 128}, extent = {{-7.437, -10}, {7.437, 10}}, textString = "µ", fontName = "Symbol"), Text(visible = true, origin = {0, 75}, textColor = {0, 128, 0}, extent = {{-100, -12}, {100, 12}}, textString = "Split Outfllow", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {-6.548, -30}, textColor = {128, 128, 128}, extent = {{-13.452, -5}, {13.452, 5}}, textString = "i", fontName = "Lato"), Text(visible = true, origin = {50, -30}, textColor = {128, 128, 128}, extent = {{-13.452, -5}, {13.452, 5}}, textString = "i", fontName = "Lato")}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end SplitOutflowDynamicStock; diff --git a/BusinessSimulation/Flows/Unidirectional/Transition.mo b/BusinessSimulation/Flows/Unidirectional/Transition.mo new file mode 100644 index 0000000..fc34483 --- /dev/null +++ b/BusinessSimulation/Flows/Unidirectional/Transition.mo @@ -0,0 +1,24 @@ +within BusinessSimulation.Flows.Unidirectional; + +model Transition "Flow from stock A to stock B at a given rate" + import BusinessSimulation.Units.Rate; + extends Interfaces.PartialFlows.UnidirectionalFlow; + parameter OutputType rate(min = 0) = 0 "Constant rate of transition (optional)" annotation(Dialog(enable = hasConstantRate)); + parameter Boolean hasConstantRate = false "= true, if the parameter rate is to be used instead of the variable input u" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + Interfaces.Connectors.RealInput u if not hasConstantRate "Rate input" annotation(Placement(visible = true, transformation(origin = {-145, 60}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-50, 100}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); +protected + Interfaces.Connectors.RealInput constantRate = rate if hasConstantRate "Conditional connector for constant rate input"; + Interfaces.Connectors.RealInput actualRate "Actual rate to use within the component"; +equation + connect(constantRate, actualRate); + connect(u, actualRate); + A_rate = actualRate; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This is the prototypical unidirectional flow of mass from stock A to stock B at a given rate. The rate can be either constant (rate) or given by the continuous input u.

+

Notes

+

Since this is a unidirectional flow the rate of flow will always be set to zero (causing an event) if the given rate of transition is a negative value.

+

See also

+

SwitchingBrokenTransition

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {-42.154, -19.63}, rotation = 5.306, points = {{36.522, -45.771}, {43.438, -34.535}, {45.906, -7.964}}, color = {0, 0, 128}, thickness = 2.5, arrowSize = 0, smooth = Smooth.Bezier), Polygon(visible = true, origin = {4, -26.925}, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, points = {{0, 9}, {5, -5}, {-5, -5}}), Text(visible = true, origin = {-5.905, -73.77}, textColor = {0, 0, 128}, extent = {{-34.095, -12}, {34.095, 12}}, textString = "rate", fontName = "Lato", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {0, 75}, textColor = {0, 128, 0}, extent = {{-100, -12}, {100, 12}}, textString = "Transition", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Transition; diff --git a/BusinessSimulation/Flows/Unidirectional/package.mo b/BusinessSimulation/Flows/Unidirectional/package.mo new file mode 100644 index 0000000..c94c6b6 --- /dev/null +++ b/BusinessSimulation/Flows/Unidirectional/package.mo @@ -0,0 +1,12 @@ +within BusinessSimulation.Flows; + +package Unidirectional "Transition from one stock to another" + extends Icons.Package annotation(Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This package contains unidirectional flows of the System Dynamics method that can be used to model a transition from one stock to another. A transition can be understood as the continuous movement of some form of mass from one state to another at a specific rate.

+
+
+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {-2.596, -11.973}, points = {{-72.3, 0}, {72.3, 0}}, color = {255, 255, 255}, thickness = 5), Line(visible = true, origin = {-1.216, 11.777}, points = {{-73.637, 0}, {73.637, 0}}, color = {255, 255, 255}, thickness = 5), Polygon(visible = true, origin = {72.114, -0.25}, rotation = -450, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-22.295, -7.943}, {22.191, -7.943}, {0.104, 15.886}}), Ellipse(visible = true, origin = {1.899, 0}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-15.107, -15.107}, {15.107, 15.107}})})); +end Unidirectional; diff --git a/BusinessSimulation/Flows/Unidirectional/package.order b/BusinessSimulation/Flows/Unidirectional/package.order new file mode 100644 index 0000000..b6b7615 --- /dev/null +++ b/BusinessSimulation/Flows/Unidirectional/package.order @@ -0,0 +1,7 @@ +CheckValveInflow +CheckValveOutflow +Decay +OutflowDynamicStock +ProportionalTransition +SplitOutflowDynamicStock +Transition diff --git a/BusinessSimulation/Flows/package.mo b/BusinessSimulation/Flows/package.mo new file mode 100644 index 0000000..152b3e6 --- /dev/null +++ b/BusinessSimulation/Flows/package.mo @@ -0,0 +1,16 @@ +within BusinessSimulation; + +package Flows "Processes that move entities from one stock to another at a specific rate" + extends Icons.Package; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This package contains flow elements of the System Dynamics method.

+

See also

+

+Tutorial.ElementaryBuildingBlocks +

+
+
+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {-2.596, -11.973}, points = {{-72.3, 0}, {72.3, 0}}, color = {255, 255, 255}, thickness = 5), Line(visible = true, origin = {-1.216, 11.777}, points = {{-73.637, 0}, {73.637, 0}}, color = {255, 255, 255}, thickness = 5), Polygon(visible = true, origin = {72.114, -0.25}, rotation = -450, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-22.295, -7.943}, {22.191, -7.943}, {0.104, 15.886}}), Ellipse(visible = true, origin = {1.899, 0}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-15.107, -15.107}, {15.107, 15.107}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Flows; diff --git a/BusinessSimulation/Flows/package.order b/BusinessSimulation/Flows/package.order new file mode 100644 index 0000000..59b4489 --- /dev/null +++ b/BusinessSimulation/Flows/package.order @@ -0,0 +1,3 @@ +Unidirectional +Bidirectional +Interaction diff --git a/BusinessSimulation/Functions/allTrueQ.mo b/BusinessSimulation/Functions/allTrueQ.mo new file mode 100644 index 0000000..255bdfc --- /dev/null +++ b/BusinessSimulation/Functions/allTrueQ.mo @@ -0,0 +1,29 @@ +within BusinessSimulation.Functions; + +function allTrueQ "Gives true, if all elements in a vector of Booleans are true" + extends BusinessSimulation.Icons.Function; + input Boolean x[:] "Vector of booleans"; + output Boolean y "True, if all elements of the input vector are true"; +protected + Integer n = size(x, 1) "Length of the input vector x"; +algorithm + y := true; + for i in 1:n loop + y := y and x[i]; + end for; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The function takes a vector of Booleans and will return true, if all of the elements in the input vector is true, and false otherwise.

+

Syntax

+
+
Function.allTrueQ(vec);
+
+

Examples

+
+
Function.allTrueQ({false, false, false}); // false
Function.allTrueQ({true, true, true}); // true
+
Function.allTrueQ({false, false, true}); // false
+
+

See also

+

Functions.noneTrueQ

+")); +end allTrueQ; diff --git a/BusinessSimulation/Functions/arithmeticMean.mo b/BusinessSimulation/Functions/arithmeticMean.mo new file mode 100644 index 0000000..91e5757 --- /dev/null +++ b/BusinessSimulation/Functions/arithmeticMean.mo @@ -0,0 +1,44 @@ +within BusinessSimulation.Functions; + +function arithmeticMean "(Weighted) arithmetic mean" + import BusinessSimulation.Constants.inf; + extends BusinessSimulation.Icons.Function; + input Real[:] x "Vector input"; + input Real[size(x, 1)] weights = ones(size(x, 1)) "Vector of weights"; + output Real y; +protected + Real[n] w "Normalized and clipped weights"; + constant Integer n = size(x, 1) "Length of the input vector"; +algorithm + // clip weights to eliminate negative values + w := BusinessSimulation.Functions.clip(weights, {0, inf}); + y := sum(x[i] * w[i] for i in 1:n) / sum(w); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output y is the arithmetic mean of the components of the input vector x. As a second argument a vector of positive weights (default = 1 for each weight) can be given to calculate the weighted arithmetic mean.

+

Syntax

+

Functions.arithmeticMean(x);
+Functions.arithmeticMean(x, weights);

+

Implementation


+
  w := BusinessSimulation.Functions.clip(weights, {0, inf});
+  y := sum(x[i] * w[i] for i in 1:n) / sum(w);

+

Notes

+ +

Examples

+
+
+Functions.arithmeticMean({ 10, 20});        // 15.0
+Functions.arithmeticMean({-20, 20});        //  0.0
+Functions.arithmeticMean({ 10, 20},{1,10}); // 19.09..
+Functions.arithmeticMean({ 10, 20},{1,-1}); // 10.
+
+
+

See also

+

+ArithmeticMean, +geometricMean +

+"), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end arithmeticMean; diff --git a/BusinessSimulation/Functions/boole.mo b/BusinessSimulation/Functions/boole.mo new file mode 100644 index 0000000..3bbaa38 --- /dev/null +++ b/BusinessSimulation/Functions/boole.mo @@ -0,0 +1,17 @@ +within BusinessSimulation.Functions; + +function boole "Returns 1.0 if input is true, and 0.0 otherwise" + extends BusinessSimulation.Icons.Function; + input Boolean u "Boolean input"; + output Real y "Real output"; +algorithm + y := if noEvent(u == true) then 1. else 0.; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The function returns 1.0 if the Boolean input u is true and 0.0 in all other cases.

+

Syntax

+

Functions.boole(u)

+

Examples

+
Functions.boole(true);   // 1.0
Functions.notZeroQ(false); // 0.0

+ "), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end boole; diff --git a/BusinessSimulation/Functions/clip.mo b/BusinessSimulation/Functions/clip.mo new file mode 100644 index 0000000..cc60c41 --- /dev/null +++ b/BusinessSimulation/Functions/clip.mo @@ -0,0 +1,25 @@ +within BusinessSimulation.Functions; + +function clip "Clip values so they do not extend beyond a given interval" + extends BusinessSimulation.Icons.Function; + input Real x[:] "List of values to be clipped"; + input Real[2] interval = {-1, 1} "Interval [min,max] given as a list (default = {-1,1})"; + output Real y[size(x, 1)] "Clipped values"; +protected + Integer n = size(x, 1) "Length of the input vector x"; +algorithm + for i in 1:n loop + y[i] := if x[i] < interval[1] then interval[1] elseif x[i] > interval[2] then interval[2] else x[i]; + end for; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The function will clip a list of input values x so that any component x_i of x will be x_i for min ≤ x_i ≤ max, min for x_i < min, and max for x_i > max

+

Syntax

+
+
Function.clip(x);               // {min, max} = {-1,1}
Function.clip(x, {min, max}); 
+

Examples

+
+
Function.clip({-3,-2,-1,0,1,2,3});        // {-1,-1,-1,0,1,1,1} 
Function.clip({-3,-2,-1,0,1,2,3},{-2,2}); // {-2,-2,-1,0,1,2,2}
+

Notes

+

This function is closely modeled to Clip in the Wolfram Language.

", revisions = "")); +end clip; diff --git a/BusinessSimulation/Functions/constrainedRate.mo b/BusinessSimulation/Functions/constrainedRate.mo new file mode 100644 index 0000000..4017e60 --- /dev/null +++ b/BusinessSimulation/Functions/constrainedRate.mo @@ -0,0 +1,30 @@ +within BusinessSimulation.Functions; + +function constrainedRate "Set rate for a port according to signals from stock" + extends BusinessSimulation.Icons.Function; + input Real indicatedRate "Proposed rate for port of flow element"; + input Boolean stopInflow "Signal from connected stock"; + input Boolean stopOutflow "Signal from connected stock"; + output Real actualRate "The rate to use"; +protected + // neagtive rate is inflow to stock + Boolean indRateIsInflow = indicatedRate < 0; +algorithm + // set rate to zero if stopSignal matches character of flow + actualRate := if stopInflow and indRateIsInflow then 0 elseif stopOutflow and not indRateIsInflow then 0 else indicatedRate; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The real output actualRate is determined by checking whether the real input indicatedRate is complying with the restrictions signaled by a connected stock in form of the boolean flags stopInflow and stopOutflow. If the rate is found to violate either flag 0 is returned, in all other cases the indicated rate is returned unchanged.

+

Syntax

+

Functions.constrainedRate(indicatedRate, stopInflow, stopOutflow)

+

Examples

+
+
Functions.constrainedRate(-5.0, stopInflow = true, stopOutflow = false); //  0.0
Functions.constrainedRate( 5.0, stopInflow = true, stopOutflow = false); // 5.0
Functions.constrainedRate(-5.0, stopInflow = false, stopOutflow = true); // -5.0
Functions.constrainedRate( 5.0, stopInflow = false, stopOutflow = true); // 0.0
+
+

Notes

+

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.

+

Thus, in the first example above the indicated negative rate for a →FlowPort would mean an outflow from the flow component and an inflow with regard to the connected →StockPort. Observing the flow restriction signaled by the stock the acutal rate is set to zero.

+

See also

+

constrainedRateBoolean

+"), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end constrainedRate; diff --git a/BusinessSimulation/Functions/constrainedRateBoolean.mo b/BusinessSimulation/Functions/constrainedRateBoolean.mo new file mode 100644 index 0000000..22f58a8 --- /dev/null +++ b/BusinessSimulation/Functions/constrainedRateBoolean.mo @@ -0,0 +1,28 @@ +within BusinessSimulation.Functions; + +function constrainedRateBoolean "Return true, if the indicated rate meets restrictions" + extends BusinessSimulation.Icons.Function; + input Real indicatedRate "Proposed rate for port of flow element"; + 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"; +protected + // neagtive rate is inflow to stock + Boolean indRateIsInflow = indicatedRate < 0; +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 = " +

This information is part of the Business Simulation Library (BSL).

+

The real output actualRate is determined by checking whether the real input indicatedRate is complying with the restrictions signaled by a connected stock in form of the boolean flags stopInflow and stopOutflow. If the rate is found to violate either flag false is returned, in all other cases true is returned.

+

Syntax

+

Functions.constrainedRateBoolean(indicatedRate, stopInflow, stopOutflow)

+

Examples

+
+
Functions.constrainedRateBoolean(-5.0, stopInflow = true, stopOutflow = false); //  false
Functions.constrainedRateBoolean( 5.0, stopInflow = true, stopOutflow = false); // true
Functions.constrainedRateBoolean(-5.0, stopInflow = false, stopOutflow = true); // true
Functions.constrainedRateBoolean( 5.0, stopInflow = false, stopOutflow = true); // false
+
+

Notes

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.

+

Thus, in the first example above the indicated negative rate for a →FlowPort would mean an outflow from the flow component and an inflow with regard to the connected →StockPort. Observing the flow restriction signaled by the stock false is returned.

+

See also

constrainedRate

+"), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end constrainedRateBoolean; diff --git a/BusinessSimulation/Functions/evalmf.mo b/BusinessSimulation/Functions/evalmf.mo new file mode 100644 index 0000000..1864c6f --- /dev/null +++ b/BusinessSimulation/Functions/evalmf.mo @@ -0,0 +1,43 @@ +within BusinessSimulation.Functions; + +function evalmf "Evaluate a fuzzy membership function" + import BusinessSimulation.Types.MembershipFunctionTypes; + import BusinessSimulation.Functions.{rampmf,trimf,smf,sigmf,pimf,gaussmf,gbellmf,trapmf}; + extends BusinessSimulation.Icons.Function; + input Real x "Input value for which the degree of membership is to be computed"; + input MembershipFunctionTypes mft = MembershipFunctionTypes.trapezoidal "Type of membership function to be used"; + input Real a "Parameter of membership function"; + input Real b "Parameter of membership function"; + input Real c "Parameter of membership function"; + input Real d "Parameter of membership function"; + output Real y "Degree of membership"; +algorithm + y := if mft == MembershipFunctionTypes.ramp then rampmf(x, a, b) elseif mft == MembershipFunctionTypes.triangular then trimf(x, a, b, c) + elseif mft == MembershipFunctionTypes.sshaped then smf(x, a, b) + elseif mft == MembershipFunctionTypes.sigmoidal then sigmf(x, a, c) + elseif mft == MembershipFunctionTypes.pishaped then pimf(x, a, b, c, d) + elseif mft == MembershipFunctionTypes.psigmoidal then psigmf(x, a, b, c, d) + elseif mft == MembershipFunctionTypes.gaussian then gaussmf(x, a, c) + elseif mft == MembershipFunctionTypes.bell then gbellmf(x, a, b, c) else trapmf(x, a, b, c, d); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The function returns the degree of membership using the membership function specified.

+

Syntax

+

Functions.evalmf(x, mft, a, b, c, d);

+

Examples

+

+Functions.evalmf( 5, mft = MembershipFunctionTypes.trapezoid, a=2, b=4, c=6, d=8); // 1.0 +
+
+

See also

+

rampmf, +trapmf, +trimf, +smf, +sigmf, +pimf, +psigmf, +gaussmf, +gbellmf +

")); +end evalmf; diff --git a/BusinessSimulation/Functions/gaussmf.mo b/BusinessSimulation/Functions/gaussmf.mo new file mode 100644 index 0000000..2d8efec --- /dev/null +++ b/BusinessSimulation/Functions/gaussmf.mo @@ -0,0 +1,41 @@ +within BusinessSimulation.Functions; + +function gaussmf "Gaussian membership function" + extends BusinessSimulation.Icons.Function; + input Real x "Input value for which the degree of membership is to be computed"; + input Real a "Half width at half maximum (HWHM)"; + input Real c "Mean value"; + output Real y "Degree of membership"; +protected + // sigma = a/ sqrt(log(4)) + Real sigma = a / 1.177410022515474691; +algorithm + y := exp(-(x - c) ^ 2 / (2 * sigma ^ 2)); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The function returns the degree of membership using a Gaussian function given the real input x and the parameters half width at half maximum a and mean c.

+

Implementation

+
+
sigma = a / 1.177410022515474691;
+y := exp(-(x - c) ^ 2 / (2 * sigma ^ 2));
+
+

Syntax

+

Functions.gaussmf(x, a, c);

+

Examples

+

Functions.gaussmf( 5, a=2, c=5); // 1.0 +Functions.gaussmf( 3, a=2, c=5); // 0.5 +Functions.gaussmf( 7, a=2, c=5); // 0.5
+
+

See also

+

+evalmf, +rampmf, +trimf, +trapmf, +smf, +sigmf, +pimf, +psigmf, +gbellmf +

")); +end gaussmf; diff --git a/BusinessSimulation/Functions/gbellmf.mo b/BusinessSimulation/Functions/gbellmf.mo new file mode 100644 index 0000000..761212f --- /dev/null +++ b/BusinessSimulation/Functions/gbellmf.mo @@ -0,0 +1,38 @@ +within BusinessSimulation.Functions; + +function gbellmf "Generalized bell-shaped membership function" + extends BusinessSimulation.Icons.Function; + input Real x "Input value for which the degree of membership is to be computed"; + input Real a "Width of core (i.e. the interval for which the function gives 1)"; + input Real b "Shape parameter (larger values → steeper transition"; + input Real c "Center of membership function"; + output Real y "Degree of membership"; +algorithm + y := 1 / (1 + abs((x - c) / a) ^ (2 * b)); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The function returns the degree of membership using a generalized bell-shaped function given the real input x and the parameters width of core a, shape parameter b, and the center value c.

+

Implementation

+
+
y := 1 / (1 + abs((x - c) / a) ^ (2 * b));
+
+

Syntax

+

Functions.gbellmf(x, a, b, c);

+

Examples

+

Functions.gbellmf( 6, a=2, b=4, c=6); // 1.0 +Functions.gbellmf( 4, a=2, b=4, c=6); // 0.5 +Functions.gbellmf( 8, a=2, b=4, c=6); // 0.5
+
+

See also

+

+evalmf, +rampmf, +trimf +trapmf, +smf, +sigmf, +pimf, +psigmf, +gaussmf, +

")); +end gbellmf; diff --git a/BusinessSimulation/Functions/geometricMean.mo b/BusinessSimulation/Functions/geometricMean.mo new file mode 100644 index 0000000..f094db0 --- /dev/null +++ b/BusinessSimulation/Functions/geometricMean.mo @@ -0,0 +1,45 @@ +within BusinessSimulation.Functions; + +function geometricMean "(Weighted) geometric mean" + import BusinessSimulation.Constants.{inf,small}; + extends BusinessSimulation.Icons.Function; + input Real[:] x "Vector input"; + input Real[size(x, 1)] weights = ones(size(x, 1)) "Vector of weights"; + output Real y; +protected + Real[n] w "Normalized and clipped weights"; + constant Integer n = size(x, 1) "Length of the input vector"; +algorithm + // clip weights to eliminate negative values + w := BusinessSimulation.Functions.clip(weights, {0, inf}); + y := if min(x) < small then 0 else exp(sum(log(x[i]) * w[i] for i in 1:n) / sum(w)); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output y is the geometric mean of the components of the input vector x. As a second argument a vector of positive weights (default = 1 for each weight) can be given to calculate the weighted geometric mean.

+

Syntax

+

Functions.geometricMean(x);
+Functions.geometricMean(x, weights);

+

Implementation


+
  w := BusinessSimulation.Functions.clip(weights, {0, inf});
+  y := if min(x) < small then 0 else exp( sum( log(x[i]) * w[i] for i in 1:n ) / sum(w) );

+

Notes

+ +

Examples

+
+
+Functions.geometricMean({10, 20});        // 14.1421..
+Functions.geometricMean({ 0, 20});        //  0.0
+Functions.geometricMean({10, 20},{1,10}); // 18.7786..
+Functions.geometricMean({10, 20},{1,-1}); // 10.
+
+
+

See also

+

+GeometricMean, +arithmeticMean +

+"), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end geometricMean; diff --git a/BusinessSimulation/Functions/janoschek.mo b/BusinessSimulation/Functions/janoschek.mo new file mode 100644 index 0000000..284e65a --- /dev/null +++ b/BusinessSimulation/Functions/janoschek.mo @@ -0,0 +1,26 @@ +within BusinessSimulation.Functions; + +function janoschek "Janoschek's Growth Curve" + extends BusinessSimulation.Icons.Function; + input Real x "x-Value"; + input Real b "Lower asymptote"; + input Real l "Upper asymptote"; + input Real k "Growth rate"; + input Real d "Control of abscissa for the point of inflection"; + output Real y; +algorithm + y := l - (l - b) * exp(-k * x ^ d); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This function models Janoschek's growth curve [19] given the real input x and the specifying real inputs b, l, k, d. The formula for the real output y is:

+

y := 1 - (l - b) * exp(-k * x ^ d);

+

Syntax

+

Functions.janoschek(x, b, l, k, d);

+

Examples

+
+
BusinessSimulation.Functions.janoschek(2, b = 0, l = 2, k = 2, d = 1); // 1.963369
+
+

See also

+

JanoschekPositiveJanoschekNegative

+"), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end janoschek; diff --git a/BusinessSimulation/Functions/noneTrueQ.mo b/BusinessSimulation/Functions/noneTrueQ.mo new file mode 100644 index 0000000..bcd887f --- /dev/null +++ b/BusinessSimulation/Functions/noneTrueQ.mo @@ -0,0 +1,29 @@ +within BusinessSimulation.Functions; + +function noneTrueQ "Gives true, if no element in a vector of Booleans is true" + extends BusinessSimulation.Icons.Function; + input Boolean x[:] "Vector of booleans"; + output Boolean y "True, if no element of the input vector is true"; +protected + Integer n = size(x, 1) "Length of the input vector x"; +algorithm + y := true; + for i in 1:n loop + y := y and not x[i]; + end for; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The function takes a vector of Booleans and will return true, if none of the elements in the input vector is true, and false otherwise.

+

Syntax

+
+
Function.noneTrueQ(vec);
+
+

Examples

+
+
Function.noneTrueQ({false, false, false}); // true
Function.noneTrueQ({true, false, false}); // false
+
Function.noneTrueQ({false, false, true}); // false
+
+

See also

+

Functions.allTrueQ

+")); +end noneTrueQ; diff --git a/BusinessSimulation/Functions/notZeroQ.mo b/BusinessSimulation/Functions/notZeroQ.mo new file mode 100644 index 0000000..b1555da --- /dev/null +++ b/BusinessSimulation/Functions/notZeroQ.mo @@ -0,0 +1,22 @@ +within BusinessSimulation.Functions; + +function notZeroQ "Yields true if input is different from zero" + extends BusinessSimulation.Icons.Function; + input Real x "Real input"; + output Boolean y "Boolean output"; +algorithm + y := x <> 0; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The function returns false if the real input x is zero and true in all other cases.

+

Syntax

+

Functions.notZeroQ(x)

+

Examples

+
+
import BusinessSimulation.Constants.small;
Functions.notZeroQ(0.0); // false
Functions.notZeroQ(1.2); // true
Functions.notZeroQ(-5); // true
Functions.notZeroQ(small); // true
+
+

Notes

+

This functions is somewhat like an \"inverse\" Boole.

+

See also

+

Boole

"), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end notZeroQ; diff --git a/BusinessSimulation/Functions/package.mo b/BusinessSimulation/Functions/package.mo new file mode 100644 index 0000000..07b8850 --- /dev/null +++ b/BusinessSimulation/Functions/package.mo @@ -0,0 +1,12 @@ +within BusinessSimulation; + +package Functions "Functions used within the library" + extends Icons.FunctionsPackage; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This pacakge contains functions used in the library.

+
+
+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Functions; diff --git a/BusinessSimulation/Functions/package.order b/BusinessSimulation/Functions/package.order new file mode 100644 index 0000000..db1fba4 --- /dev/null +++ b/BusinessSimulation/Functions/package.order @@ -0,0 +1,25 @@ +allTrueQ +arithmeticMean +boole +clip +constrainedRate +constrainedRateBoolean +evalmf +gaussmf +gbellmf +geometricMean +janoschek +noneTrueQ +notZeroQ +pimf +polynomialFunction +psigmf +rampmf +rescale +rescaleVector +shiftList +sigmf +smf +stringToTimeBase +trapmf +trimf diff --git a/BusinessSimulation/Functions/pimf.mo b/BusinessSimulation/Functions/pimf.mo new file mode 100644 index 0000000..de095d3 --- /dev/null +++ b/BusinessSimulation/Functions/pimf.mo @@ -0,0 +1,55 @@ +within BusinessSimulation.Functions; + +function pimf "Pi-shaped membership function" + extends BusinessSimulation.Icons.Function; + input Real x "Input value for which the degree of membership is to be computed"; + input Real a "Foot of the s-shaped part(lower bound of the support)"; + input Real b "Shoulder of the s-haped part (lower bound of the core)"; + input Real c "Shoulder of the z-shaped part (upper bound of the core)"; + input Real d "Foot of the z-shaped part (upper bound of the support)"; + output Real y "Degree of membership"; +protected + Real midpointS = (a + b) / 2; + Real midpointZ = (c + d) / 2; +algorithm + y := if x <= a then 0 elseif a < x and x <= midpointS then 2 * ((x - a) / (b - a)) ^ 2 + elseif midpointS < x and x <= b then 1 - 2 * ((x - b) / (b - a)) ^ 2 + elseif b < x and x <= c then 1 + elseif c < x and x <= midpointZ then 1 - 2 * ((x - c) / (d - c)) ^ 2 + elseif midpointZ < x and x <= d then 2 * ((x - d) / (d - c)) ^ 2 else 1; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The function returns the degree of membership using a Pi-shaped function given the real input x and the parameters foot of the s-shaped part a, shoulder of the s-shaped part b, shoulder of the z-shaped part c, and foot of the z-shaped part d of the function.

+

Implementation

+
+
  y := if x <= a then 0 
+    elseif a < x and x <= midpointS then 2 * ((x - a) / (b - a)) ^ 2
+    elseif midpointS < x and x <= b then 1 - 2 * ((x - b) / (b - a)) ^ 2
+    elseif b < x and x <= c then 1
+    elseif c < x and x <= midpointZ then 1 - 2 * ((x - c) / (d - c)) ^ 2
+    elseif midpointZ < x and x <= d then 2 * ((x - d) / (d - c)) ^ 2
+    else 1;
+
+

Syntax

+

Functions.pimf(x, a, b, c, d);

+

Examples

+

Functions.pimf( 5, a=1, b=4, c=5, d=10); // 1.0 +Functions.pimf( 2.5, a=1, b=4, c=5, d=10); // 0.5 +Functions.pimf( 1, a=1, b=4, c=5, d=10); // 0.0 +Functions.pimf( 7.5, a=1, b=4, c=5, d=10); // 0.5 +Functions.pimf( 10, a=1, b=4, c=5, d=10); // 0.0 +
+
+

See also

+

+evalmf, +rampmf, +trimf, +trapmf, +smf, +sigmf, +psigmf, +gaussmf, +gbellmf +

")); +end pimf; diff --git a/BusinessSimulation/Functions/polynomialFunction.mo b/BusinessSimulation/Functions/polynomialFunction.mo new file mode 100644 index 0000000..1160e4b --- /dev/null +++ b/BusinessSimulation/Functions/polynomialFunction.mo @@ -0,0 +1,25 @@ +within BusinessSimulation.Functions; + +function polynomialFunction "Polynomial function of degree n" + extends BusinessSimulation.Icons.Function; + input Real x "Independent variable"; + input Real a[:] "Vector of coefficients"; + output Real y "Value of the polynomial equation"; +protected + Integer i; + constant Integer n = size(a, 1); +algorithm + y := 0; + for i in 1:n loop + y := y + a[i] * x ^ (i - 1); + end for; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The function returns the value of the n-th degree polynomial given the real input x and the real vector of coefficients a[:] = {a_0, a_1, ..., a_n} where the degree of the polynomial is n = size(a,1) - 1.

+

Syntax

+

Functions.polynomialFunction(x,a);

+

Examples

+

Functions.polynomialFunction( 2, { 0,0,1}); // 4.0
Functions.polynomialFunction( 2, {-6,1,1}); // 0.0

+

See also

+

PolynomialFunction

", revisions = "")); +end polynomialFunction; diff --git a/BusinessSimulation/Functions/psigmf.mo b/BusinessSimulation/Functions/psigmf.mo new file mode 100644 index 0000000..ca84b45 --- /dev/null +++ b/BusinessSimulation/Functions/psigmf.mo @@ -0,0 +1,42 @@ +within BusinessSimulation.Functions; + +function psigmf "Product of two sigmoidal membership functions" + import BusinessSimulation.Functions.sigmf; + extends BusinessSimulation.Icons.Function; + input Real x "Input value for which the degree of membership is to be computed"; + input Real a "Shape parameter controlling the width of s-shaped transition area (higher values → steeper transition)"; + input Real b "Center of s-shaped transition area"; + input Real c "Shape parameter controlling the width of z-shaped transition area (higher values → steeper transition)"; + input Real d "Center of z-shaped transition area"; + output Real y "Degree of membership"; +algorithm + y := sigmf(x, a = a, c = b) * sigmf(x, a = -c, c = d); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The function returns the degree of membership using the product of two sigmoidal functions given the real input x and the parameters shape parameter for the s-shaped transition area a, center of the s-shaped transition area b, shape parameter of the z-shaped transition area c, and center of the z-shaped transition area d of the function.

+

Implementation

+
+
 y := sigmf(x, a = a, c = b) * sigmf(x, a = -c, c = d);
+
+

Syntax

+

Functions.psigmf(x, a, b, c, d);

+

Examples

+

+Functions.psigmf( 8, a=2, b=3, c=5, d=8); // 0.4999773.. +Functions.psigmf( 6.9, a=2, b=3, c=5, d=8); // 0.9955219.. +Functions.psigmf( 3, a=2, b=3, c=5, d=8); // 0.4999999.. +Functions.psigmf( 10, a=2, b=3, c=5, d=8); // 4.53978e-05 +
+
+

See also

+

+evalmf, +rampmf, +trimf, +trapmf, +smf, +sigmf, +gaussmf, +gbellmf +

")); +end psigmf; diff --git a/BusinessSimulation/Functions/rampmf.mo b/BusinessSimulation/Functions/rampmf.mo new file mode 100644 index 0000000..c1c3ea5 --- /dev/null +++ b/BusinessSimulation/Functions/rampmf.mo @@ -0,0 +1,38 @@ +within BusinessSimulation.Functions; + +function rampmf "Bounded ramp membership function" + extends BusinessSimulation.Icons.Function; + input Real x "Input value for which the degree of membership is to be computed"; + input Real a "Lower bound"; + input Real b "Upper bound"; + output Real y "Degree of membership"; +algorithm + y := max(min((x - a) / (b - a), 1), 0); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The function returns the degree of membership using a bounded ramp function given the real input x and the parameters lower bound a and upper bound b.

+

The ramp will usually ramp up from 0 to 1, but if lower bound and upper bound are switched (i.e. a > b), then the ramp will be ramp downwards from 1 to 0.

+

Implementation

+
+
y := max(min((x - a) / (b - a), 1), 0);
+
+

Syntax

+

Functions.rampmf(x, a, b);

+

Examples

+

Functions.rampmf( 5, a=2, b=8); // 0.5 +Functions.rampmf( 1, a=2, b=8); // 0.0 +Functions.rampmf( 9, a=2, b=8); // 1.0
+
+

See also

+

+evalmf, +trimf, +trapmf, +smf, +sigmf, +pimf, +psigmf, +gaussmf, +gbellmf +

")); +end rampmf; diff --git a/BusinessSimulation/Functions/rescale.mo b/BusinessSimulation/Functions/rescale.mo new file mode 100644 index 0000000..d23490f --- /dev/null +++ b/BusinessSimulation/Functions/rescale.mo @@ -0,0 +1,29 @@ +within BusinessSimulation.Functions; + +function rescale "Rescale values from one range to another" + extends BusinessSimulation.Icons.Function; + input Real x "Value to be transformed"; + input Real x_range[2] "Original range [min,max] given as a list"; + input Real y_range[2] = {0, 1} "Rescaled range [y_min, y_max] given as a list (default = {0,1})"; + output Real y "Rescaled value to run from y_min to y_max over the range min to max"; +protected + Real x_min = x_range[1]; + Real x_max = x_range[2]; + Real y_min = y_range[1]; + Real y_max = y_range[2]; +algorithm + y := y_min + (x - x_min) * (y_max - y_min) / (x_max - x_min) annotation(Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The function will rescale the input to run from range y_min to y_max over the range min to max.

+

Syntax

+
+
Function.rescale(x, {x_min, x_max});                 // {y_min, y_max} by default assumed to be {0,1}
Function.rescale(x, {min, max}, {y_min, y_max}); 
+

Examples

+
+
Function.rescale(5, {0, 10});                 // 0.5
Function.rescale(5, {0, 10}, {10, 20}); // 15.
+

Notes

+

This function is closely modeled to Rescale in the Wolfram Language.

+

See also

+

Functions.rescaleVector

", revisions = "")); +end rescale; diff --git a/BusinessSimulation/Functions/rescaleVector.mo b/BusinessSimulation/Functions/rescaleVector.mo new file mode 100644 index 0000000..86bfc72 --- /dev/null +++ b/BusinessSimulation/Functions/rescaleVector.mo @@ -0,0 +1,26 @@ +within BusinessSimulation.Functions; + +function rescaleVector "Rescale a list of values from one range to another" + extends BusinessSimulation.Icons.Function; + input Real x[:] "List of values (vector) to be rescaled"; + input Real x_range[2] = {min(x), max(x)} "Original range [min,max] given as a list (default = {min(x), max(x)})"; + input Real y_range[2] = {0, 1} "Rescaled range [y_min, y_max] given as a list (default = {0,1})"; + output Real y[size(x, 1)] "Rescaled value to run from y_min to y_max over the range min to max"; +protected + Integer n = size(x, 1) "Length of the input vector x"; +algorithm + y := array(BusinessSimulation.Functions.rescale(x[i], x_range, y_range) for i in 1:n); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The function will rescale the input vector to a vector whose elements run from range y_min to y_max over the range min to max.

+

Syntax

+
+
Function.rescale(vec);                             // {min, max} = {min(vec), max(vec)};{y_min, y_max} = {0,1}
Function.rescale(vec, {min, max});  // {y_min,y_max} = {0,1}
Function.rescale(vec, {min, max}, {y_min, y_max});
+

Examples

+
+
Function.rescale({0,1,2,3,4,5,6,7,8,9,10});        // {0.,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0} 
Function.rescale({4,5,6},{0, 10}); // {0.4, 0.5, 0.6}
Function.rescale({4,5,6},{0,10},{10,20}); // {14.,15.,16.}
+

Notes

+

This function is closely modeled to Rescale in the Wolfram Language.

+

See also

+

Functions.rescale

", revisions = "")); +end rescaleVector; diff --git a/BusinessSimulation/Functions/shiftList.mo b/BusinessSimulation/Functions/shiftList.mo new file mode 100644 index 0000000..803cc02 --- /dev/null +++ b/BusinessSimulation/Functions/shiftList.mo @@ -0,0 +1,36 @@ +within BusinessSimulation.Functions; + +function shiftList "Shift a list n steps, report carry, and fill gaps" + extends BusinessSimulation.Icons.Function; + input Real[:] list "List of values to be shifted"; + input Integer n "Number of steps to shift the lift( n < 0 => shift to the left)"; + input Real fill = 0 "Value to fill the gaps with (default = 0)"; + output Real[size(list, 1)] shiftedList "Shifted list"; + output Real carry "Sum of elements that were pushed out of range by the shift"; +protected + Integer length = size(list, 1) "Length of the list of values"; + Integer nAbs = min(abs(n), length) "Absolute value of n, clipped to never be larger than length"; +algorithm + if n == 0 then + // do nothing really + carry := 0.; + shiftedList := list; + elseif n < 0 then + // shift left + carry := sum(list[1:nAbs]); + shiftedList := if nAbs < length then cat(1, list[nAbs + 1:end], zeros(nAbs)) else zeros(nAbs); + else + // n > 0 + // shift right + carry := sum(list[end - nAbs + 1:end]); + shiftedList := if nAbs < length then cat(1, zeros(nAbs), list[1:end - nAbs]) else zeros(nAbs); + end if; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The function will return a list shifted by n places (n < 0 ⇒ shift to the left), where the elements \"pushed\" out of range are added up and reported as carry. The gaps will be shifted with the real value fill, which by default is set to 0.

+

Syntax

+
+
Functions.shiftList( list, n );   // fill by default is set to zero
Functions.shiftList( list, n, fill ); // explicitly give a real value for fill

+

Examples

+
shiftList( {1, 2, 3, 4, 5},  0);   // ( {1, 2, 3, 4, 5}, 0. )
shiftList( {1, 2, 3, 4, 5}, -2); // ( {3, 4, 5, 0, 0}, 3. )
shiftList( {1, 2, 3, 4, 5}, 2); // ( {0, 0, 1, 2, 3}, 9. )
", revisions = ""), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end shiftList; diff --git a/BusinessSimulation/Functions/sigmf.mo b/BusinessSimulation/Functions/sigmf.mo new file mode 100644 index 0000000..5f25d89 --- /dev/null +++ b/BusinessSimulation/Functions/sigmf.mo @@ -0,0 +1,39 @@ +within BusinessSimulation.Functions; + +function sigmf "Sigmoidal membership function" + extends BusinessSimulation.Icons.Function; + input Real x "Input value for which the degree of membership is to be computed"; + input Real a "Shape parameter controlling the width of s-shaped transition area (higher values → steeper transition)"; + input Real c "Center of the s-shaped transition area"; + output Real y "Degree of membership"; +algorithm + y := 1 / (1 + exp(-a * (x - c))); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The function returns the degree of membership using a sigmoid function function given the real input x and the parameters shape parameter to control width of transition area a and center of transition area c.

+

The sigmoid function will increase from 0 to 1 for positive values of a, while negative values will give rise to a z-shaped transition.

+

Implementation

+
+
y := 1 / (1 + exp(-a * (x - c)));
+
+

Syntax

+

Functions.sigmf(x, a, c);

+

Examples

+

Functions.sigmf( 4, a=2, c=4); // 0.5 +Functions.sigmf( 2, a=2, c=4); // 0.0179862.. +Functions.sigmf( 6, a=2, c=4); // 0.98201379..
+
+

See also

+

+evalmf, +rampmf, +trimf, +trapmf, +smf, +sigmf, +pimf, +psigmf, +gaussmf, +gbellmf +

")); +end sigmf; diff --git a/BusinessSimulation/Functions/smf.mo b/BusinessSimulation/Functions/smf.mo new file mode 100644 index 0000000..051fe44 --- /dev/null +++ b/BusinessSimulation/Functions/smf.mo @@ -0,0 +1,43 @@ +within BusinessSimulation.Functions; + +function smf "S-shaped membership function" + extends BusinessSimulation.Icons.Function; + input Real x "Input value for which the degree of membership is to be computed"; + input Real a "Foot of the function (i.e. f(a) = 0)"; + input Real b "Shoulder of the function (i.e. f(b) = 1)"; + output Real y "Degree of membership"; +protected + Real midpoint = (a + b) / 2; +algorithm + y := if x <= a then 0 elseif a < x and x <= midpoint then 2 * ((x - a) / (b - a)) ^ 2 + elseif midpoint < x and x <= b then 1 - 2 * ((x - b) / (b - a)) ^ 2 else 1; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The function returns the degree of membership using a S-shaped function given the real input x and the parameters foot a and shoulder b of the function.

+

Implementation

+
+
  y := if x <= a then 0
+    elseif a < x and x <= midpoint then 2 * ( (x-a)/(b-a) )^2
+    elseif midpoint < x and x <= b then 1 - 2 * ( (x-b)/(b-a) )^2
+    else 1;
+
+

Syntax

+

Functions.smf(x, a, b);

+

Examples

+

Functions.smf( 5, a=2, b=8); // 0.5 +Functions.smf( 1, a=2, b=8); // 0.0 +Functions.smf( 9, a=2, b=8); // 1.0
+
+

See also

+

+evalmf, +rampmf, +trimf, +trapmf, +sigmf, +pimf, +psigmf, +gaussmf, +gbellmf +

")); +end smf; diff --git a/BusinessSimulation/Functions/stringToTimeBase.mo b/BusinessSimulation/Functions/stringToTimeBase.mo new file mode 100644 index 0000000..cbccfce --- /dev/null +++ b/BusinessSimulation/Functions/stringToTimeBase.mo @@ -0,0 +1,23 @@ +within BusinessSimulation.Functions; + +function stringToTimeBase "Find the corresponding element of the TimeBases enumeration for a given time base string" + extends BusinessSimulation.Icons.Function; + import BusinessSimulation.Types.TimeBases; + import Modelica.Utilities.Strings.isEqual; + input String timeBaseString "String for a time base given in lower case"; + output TimeBases timeBase "Element in the enumeration corresponding to the string given"; +protected + constant Boolean ignoreCase = false "= true, to set caseSensitive flag to true"; +algorithm + timeBase := if isEqual(timeBaseString, "minute", ignoreCase) or isEqual(timeBaseString, "min", ignoreCase) then TimeBases.minutes else if isEqual(timeBaseString, "hour", ignoreCase) or isEqual(timeBaseString, "hours", ignoreCase) or isEqual(timeBaseString, "h", ignoreCase) then TimeBases.hours else if isEqual(timeBaseString, "day", ignoreCase) or isEqual(timeBaseString, "days", ignoreCase) or isEqual(timeBaseString, "d", ignoreCase) then TimeBases.days else if isEqual(timeBaseString, "week", ignoreCase) or isEqual(timeBaseString, "weeks", ignoreCase) or isEqual(timeBaseString, "wk", ignoreCase) then TimeBases.weeks else if isEqual(timeBaseString, "month", ignoreCase) or isEqual(timeBaseString, "months", ignoreCase) or isEqual(timeBaseString, "mo", ignoreCase) then TimeBases.months else if isEqual(timeBaseString, "quarter", ignoreCase) or isEqual(timeBaseString, "quarters", ignoreCase) or isEqual(timeBaseString, "qtr", ignoreCase) then TimeBases.quarters else if isEqual(timeBaseString, "year", ignoreCase) or isEqual(timeBaseString, "years", ignoreCase) or isEqual(timeBaseString, "yr", ignoreCase) then TimeBases.years else TimeBases.seconds; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The function will return the element of the enumeration Types.TimeBases that corresponds to a given unit of time given as a string. The string should be given in lower case letters and should be given either as a word or the unit symbol. If there is no match, the function will default to TimeBases.second.

+

Syntax

+
+
Functions.stringToTimeBase( timeBaseString );   // the string is to be given as lower case

+

Examples

+
+
stringToTimeBase( \"month\" );   // TimesBases.months
stringToTimeBase( \"yr\" ); // TimeBases.years
+"), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end stringToTimeBase; diff --git a/BusinessSimulation/Functions/trapmf.mo b/BusinessSimulation/Functions/trapmf.mo new file mode 100644 index 0000000..95f3c1c --- /dev/null +++ b/BusinessSimulation/Functions/trapmf.mo @@ -0,0 +1,40 @@ +within BusinessSimulation.Functions; + +function trapmf "Trapezoidal membership function" + extends BusinessSimulation.Icons.Function; + input Real x "Input value for which the degree of membership is to be computed"; + input Real a "Lower bound for the support (i.e. f(a) = 0)"; + input Real b "Lower bound for the core (i.e. f(b) = 1)"; + input Real c "Upper bound for the core (i.e. f(c) = 1)"; + input Real d "Upper bound for the support(i.e. f(d) = 0)"; + output Real y "Degree of membership"; +algorithm + y := max(min(1, min((x - a) / (b - a), (d - x) / (d - c))), 0); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The function returns the degree of membership using a trapezoidal function given the real input x and the parameters lower bound of the support a, the lower bound of the core b, the upper bound of the core c, and the upper bound of the support d.

+

Implementation

+
+
y := max( min( 1, min( (x - a)/(b - a), (d - x)/(d - c)) ), 0 );
+
+

Syntax

+

Functions.trapmf(x, a, b, c, d);

+

Examples

+

Functions.trapmf( 5, a=2, b=4, c=6, d=8); // 1.0 +Functions.trapmf( 2, a=2, b=4, c=6, d=8); // 0.0 +Functions.trapmf( 9, a=2, b=4, c=6, d=8); // 0.0 +Functions.trapmf( 7, a=2, b=4, c=6, d=8); // 0.5
+
+

See also

+

+evalmf, +rampmf, +trimf, +smf, +sigmf, +pimf, +psigmf, +gaussmf, +gbellmf +

")); +end trapmf; diff --git a/BusinessSimulation/Functions/trimf.mo b/BusinessSimulation/Functions/trimf.mo new file mode 100644 index 0000000..3899b26 --- /dev/null +++ b/BusinessSimulation/Functions/trimf.mo @@ -0,0 +1,38 @@ +within BusinessSimulation.Functions; + +function trimf "Triangular membership function" + extends BusinessSimulation.Icons.Function; + input Real x "Input value for which the degree of membership is to be computed"; + input Real a "Lower bound (i.e. f(a) = 0)"; + input Real b "Peak (i.e. f(b) = 1)"; + input Real c "Upper bound (i.e. f(c) = 0)"; + output Real y "Degree of membership"; +algorithm + y := max(min((x - a) / (b - a), (c - x) / (c - b)), 0); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The function returns the degree of membership using a triangular function given the real input x and the parameters lower bound of the support a, the upper bound of the support c and the peak or core value b.

+

Implementation

+
+
y := max(min((x - a) / (b - a), (c - x) / (c - b)), 0);
+
+

Syntax

+

Functions.trimf(x, a, b, c);

+

Examples

+

Functions.trimf( 5, a=2, b=5, c=8); // 1.0 +Functions.trimf( 1, a=2, b=5, c=8); // 0.0 +Functions.trimf( 9, a=2, b=5, c=8); // 0.0
+
+

See also

+

+evalmf, +rampmf, +trapmf, +smf, +sigmf, +pimf, +psigmf, +gaussmf, +gbellmf +

")); +end trimf; diff --git a/BusinessSimulation/Icons/BasesPackage/package.mo b/BusinessSimulation/Icons/BasesPackage/package.mo new file mode 100644 index 0000000..491cadb --- /dev/null +++ b/BusinessSimulation/Icons/BasesPackage/package.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Icons; + +partial package BasesPackage "Base class package icon" + extends Package; + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Ellipse(visible = true, lineColor = {128, 128, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-30, -30}, {30, 30}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end BasesPackage; diff --git a/BusinessSimulation/Icons/BidirectionalFlow.mo b/BusinessSimulation/Icons/BidirectionalFlow.mo new file mode 100644 index 0000000..db3d875 --- /dev/null +++ b/BusinessSimulation/Icons/BidirectionalFlow.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Icons; + +partial class BidirectionalFlow "Icon for bidirectional flow classes" + extends ComponentName; + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {0, 128, 0}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-100, -100}, {100, 100}}), Polygon(visible = true, origin = {-72.424, 0}, rotation = 450, lineColor = {0, 128, 0}, fillColor = {0, 128, 0}, fillPattern = FillPattern.Solid, points = {{22.295, -7.943}, {-22.191, -7.943}, {-0.104, 15.886}}), Polygon(visible = true, origin = {72.114, -0.25}, rotation = -450, lineColor = {0, 128, 0}, fillColor = {0, 128, 0}, fillPattern = FillPattern.Solid, points = {{-22.295, -7.943}, {22.191, -7.943}, {0.104, 15.886}}), Line(visible = true, origin = {-0.91, -11.973}, points = {{-67.505, 0}, {67.505, 0}}, color = {0, 128, 0}, thickness = 4, arrowSize = 1), Line(visible = true, origin = {-0.152, 11.777}, points = {{-67.808, 0}, {67.808, 0}}, color = {0, 128, 0}, thickness = 4, arrowSize = 1), Text(visible = true, origin = {-73.452, 37.479}, textColor = {0, 128, 0}, extent = {{-13.452, -20}, {13.452, 20}}, textString = "A"), Text(visible = true, origin = {73.452, -43.134}, textColor = {0, 128, 0}, extent = {{-13.452, -20}, {13.452, 20}}, textString = "B"), Text(visible = true, origin = {2, 0}, textColor = {255, 255, 255}, extent = {{-16.513, -12}, {16.513, 12}}, textString = "X", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {74, 1}, textColor = {255, 255, 255}, extent = {{-13.452, -12}, {13.452, 12}}, textString = "+", fontName = "Lato", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {-74.548, 2}, textColor = {255, 255, 255}, extent = {{-13.452, -12}, {13.452, 12}}, textString = "–", fontName = "Lato", textStyle = {TextStyle.Bold}), Ellipse(visible = true, origin = {1.899, 0}, lineColor = {0, 128, 0}, fillColor = {0, 128, 0}, fillPattern = FillPattern.Solid, lineThickness = 1, extent = {{-17, -17}, {17, 17}}), Text(visible = true, origin = {2, 0}, textColor = {255, 255, 255}, extent = {{-16.513, -12}, {16.513, 12}}, textString = "X", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end BidirectionalFlow; diff --git a/BusinessSimulation/Icons/CapacityLabel.mo b/BusinessSimulation/Icons/CapacityLabel.mo new file mode 100644 index 0000000..297e210 --- /dev/null +++ b/BusinessSimulation/Icons/CapacityLabel.mo @@ -0,0 +1,5 @@ +within BusinessSimulation.Icons; + +partial class CapacityLabel "Mark stock element as having capacity restrictions" + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {61.092, 75}, textColor = {128, 0, 128}, extent = {{-28.908, -20}, {28.908, 20}}, textString = "CPTY", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end CapacityLabel; diff --git a/BusinessSimulation/Icons/Clockface.mo b/BusinessSimulation/Icons/Clockface.mo new file mode 100644 index 0000000..17dcde2 --- /dev/null +++ b/BusinessSimulation/Icons/Clockface.mo @@ -0,0 +1,5 @@ +within BusinessSimulation.Icons; + +partial class Clockface "Face of a clock" + annotation(__Wolfram(itemFlippingEnabled = true), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, pattern = LinePattern.None, lineThickness = 4, extent = {{-100, -100}, {100, 100}}), Ellipse(visible = true, rotation = -30, lineColor = {255, 255, 255}, fillColor = {0, 0, 128}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, extent = {{45, -45}, {-45, 45}}, startAngle = 60, endAngle = 150), Line(visible = true, origin = {34.536, 20.464}, rotation = 300, points = {{0, 5}, {0, -5}}, color = {128, 128, 128}, thickness = 2.5, arrowSize = 0), Line(visible = true, origin = {20.5, 33.33}, rotation = -30, points = {{0, 5}, {0, -5}}, color = {128, 128, 128}, thickness = 2.5, arrowSize = 0), Line(visible = true, origin = {0, 39.149}, points = {{0, 5}, {0, -5}}, color = {128, 128, 128}, thickness = 2.5, arrowSize = 0), Line(visible = true, origin = {-19.464, 33.464}, rotation = 30, points = {{0, 5}, {0, -5}}, color = {128, 128, 128}, thickness = 2.5, arrowSize = 1), Line(visible = true, origin = {-34.5, 19.33}, rotation = -300, points = {{0, 5}, {0, -5}}, color = {128, 128, 128}, thickness = 2.5, arrowSize = 1), Line(visible = true, origin = {-40, 0}, rotation = -270, points = {{0, 5}, {0, -5}}, color = {128, 128, 128}, thickness = 2.5, arrowSize = 1), Line(visible = true, origin = {-33.464, -20.536}, rotation = 300, points = {{0, 5}, {0, -5}}, color = {128, 128, 128}, thickness = 2.5, arrowSize = 1), Line(visible = true, origin = {-19.5, -34.67}, rotation = -30, points = {{0, 5}, {0, -5}}, color = {128, 128, 128}, thickness = 2.5, arrowSize = 0), Line(visible = true, origin = {0, -39.851}, points = {{0, 5}, {0, -5}}, color = {128, 128, 128}, thickness = 2.5, arrowSize = 0), Line(visible = true, origin = {20.536, -33.536}, rotation = 30, points = {{0, 5}, {0, -5}}, color = {128, 128, 128}, thickness = 2.5, arrowSize = 0), Line(visible = true, origin = {33.5, -19.67}, rotation = -300, points = {{0, 5}, {0, -5}}, color = {128, 128, 128}, thickness = 2.5, arrowSize = 0), Line(visible = true, origin = {39.55, -0.72}, rotation = -270, points = {{0, 5}, {0, -5}}, color = {128, 128, 128}, thickness = 2.5, arrowSize = 0), Ellipse(visible = true, rotation = 30, lineColor = {128, 128, 128}, fillColor = {255, 255, 255}, lineThickness = 2.5, extent = {{-45, -45}, {45, 45}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Clockface; diff --git a/BusinessSimulation/Icons/Clockface_white.mo b/BusinessSimulation/Icons/Clockface_white.mo new file mode 100644 index 0000000..c8f0ea5 --- /dev/null +++ b/BusinessSimulation/Icons/Clockface_white.mo @@ -0,0 +1,5 @@ +within BusinessSimulation.Icons; + +partial class Clockface_white "Face of a clock" + annotation(__Wolfram(itemFlippingEnabled = true), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, pattern = LinePattern.None, lineThickness = 4, extent = {{-100, -100}, {100, 100}}), Line(visible = true, origin = {34.536, 20.464}, rotation = 300, points = {{0, 5}, {0, -5}}, color = {255, 255, 255}, thickness = 2.5, arrowSize = 0), Line(visible = true, origin = {20.5, 33.33}, rotation = -30, points = {{0, 5}, {0, -5}}, color = {255, 255, 255}, thickness = 2.5, arrowSize = 0), Line(visible = true, origin = {0, 39.149}, points = {{0, 5}, {0, -5}}, color = {255, 255, 255}, thickness = 2.5, arrowSize = 0), Line(visible = true, origin = {-19.464, 33.464}, rotation = 30, points = {{0, 5}, {0, -5}}, color = {255, 255, 255}, thickness = 2.5, arrowSize = 1), Line(visible = true, origin = {-34.5, 19.33}, rotation = -300, points = {{0, 5}, {0, -5}}, color = {255, 255, 255}, thickness = 2.5, arrowSize = 1), Line(visible = true, origin = {-40, 0}, rotation = -270, points = {{0, 5}, {0, -5}}, color = {255, 255, 255}, thickness = 2.5, arrowSize = 1), Line(visible = true, origin = {-33.464, -20.536}, rotation = 300, points = {{0, 5}, {0, -5}}, color = {255, 255, 255}, thickness = 2.5, arrowSize = 1), Line(visible = true, origin = {-19.5, -34.67}, rotation = -30, points = {{0, 5}, {0, -5}}, color = {255, 255, 255}, thickness = 2.5, arrowSize = 0), Line(visible = true, origin = {0, -39.851}, points = {{0, 5}, {0, -5}}, color = {255, 255, 255}, thickness = 2.5, arrowSize = 0), Line(visible = true, origin = {20.536, -33.536}, rotation = 30, points = {{0, 5}, {0, -5}}, color = {255, 255, 255}, thickness = 2.5, arrowSize = 0), Line(visible = true, origin = {33.5, -19.67}, rotation = -300, points = {{0, 5}, {0, -5}}, color = {255, 255, 255}, thickness = 2.5, arrowSize = 0), Line(visible = true, origin = {39.55, -0.72}, rotation = -270, points = {{0, 5}, {0, -5}}, color = {255, 255, 255}, thickness = 2.5, arrowSize = 0), Ellipse(visible = true, rotation = 30, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, lineThickness = 2.5, extent = {{-45, -45}, {45, 45}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Clockface_white; diff --git a/BusinessSimulation/Icons/ComponentName.mo b/BusinessSimulation/Icons/ComponentName.mo new file mode 100644 index 0000000..39bf956 --- /dev/null +++ b/BusinessSimulation/Icons/ComponentName.mo @@ -0,0 +1,5 @@ +within BusinessSimulation.Icons; + +partial class ComponentName "Component name for Icon View" + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {-0, -125}, textColor = {64, 64, 64}, extent = {{-150, -12}, {150, 12}}, textString = "%name", fontName = "Lato ")}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end ComponentName; diff --git a/BusinessSimulation/Icons/ConnectorsPackage/package.mo b/BusinessSimulation/Icons/ConnectorsPackage/package.mo new file mode 100644 index 0000000..0cbafd1 --- /dev/null +++ b/BusinessSimulation/Icons/ConnectorsPackage/package.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Icons; + +partial package ConnectorsPackage "Icon for a connector package" + extends Package; + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Ellipse(visible = true, origin = {-40, -40}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-24.747, -24.747}, {24.747, 24.747}}), Rectangle(visible = true, origin = {-40, 40}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-22.954, -21.871}, {22.954, 21.871}}), Polygon(visible = true, origin = {121.766, -37.967}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-100, 100}, {-51.766, 78.102}, {-100, 55.933}, {-100, 100}}), Polygon(visible = true, origin = {45, -42.5}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 3, points = {{-20, 12.5}, {20, 12.5}, {25, 7.5}, {20, -10}, {15, -12.5}, {-15, -12.5}, {-20, -10}, {-25, 7.5}}, smooth = Smooth.Bezier)}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end ConnectorsPackage; diff --git a/BusinessSimulation/Icons/ConstantConverter.mo b/BusinessSimulation/Icons/ConstantConverter.mo new file mode 100644 index 0000000..2e68482 --- /dev/null +++ b/BusinessSimulation/Icons/ConstantConverter.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Icons; + +partial block ConstantConverter "Icon for constant converter elements" + extends ConstantConverterName; + annotation(Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Ellipse(visible = true, lineColor = {0, 0, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 4, extent = {{-28.253, -28.253}, {28.253, 28.253}}), Line(visible = true, rotation = -270, points = {{0, 40}, {0, -40}}, color = {0, 0, 128}, thickness = 2.5, arrowSize = 0)})); +end ConstantConverter; diff --git a/BusinessSimulation/Icons/ConstantConverterName.mo b/BusinessSimulation/Icons/ConstantConverterName.mo new file mode 100644 index 0000000..bab0128 --- /dev/null +++ b/BusinessSimulation/Icons/ConstantConverterName.mo @@ -0,0 +1,5 @@ +within BusinessSimulation.Icons; + +partial class ConstantConverterName "Icon for converter elements" + annotation(Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, -55}, textColor = {64, 64, 64}, extent = {{-150, -12}, {150, 12}}, textString = "%name", fontName = "Lato")})); +end ConstantConverterName; diff --git a/BusinessSimulation/Icons/ConstantsPackage/package.mo b/BusinessSimulation/Icons/ConstantsPackage/package.mo new file mode 100644 index 0000000..9ab233d --- /dev/null +++ b/BusinessSimulation/Icons/ConstantsPackage/package.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Icons; + +partial package ConstantsPackage "Icon for a constants package" + extends Package; + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, origin = {14.3, 18.868}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, points = {{-80, -6.372}, {-80, -6.372}, {-76.12, -6.372}, {-76.12, -6.372}, {-60.75, 16.378}, {-9.64, 16.378}, {43.88, 16.378}, {43.88, 16.378}, {43.88, 32.798}, {43.88, 32.798}, {-11.12, 32.798}, {-66.12, 32.798}}, smooth = Smooth.Bezier), Polygon(visible = true, origin = {14.3, 18.868}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, points = {{16.84, 26.921}, {16.84, -51.493}, {33.13, -53.079}, {41.24, -38.779}, {41.24, -38.779}, {45.7, -38.779}, {45.7, -38.779}, {33.13, -75.549}, {6.87, -75.549}, {0, -43.079}, {5.157, 26.921}, {5.157, 26.921}, {16.84, 26.921}}, smooth = Smooth.Bezier), Polygon(visible = true, origin = {14.3, 18.868}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, points = {{-38.493, 26.921}, {-44.229, -29.502}, {-70, -66.269}, {-52.476, -76.921}, {-33.577, -66.269}, {-28.493, 26.921}, {-28.493, 26.921}, {-38.493, 26.921}}, smooth = Smooth.Bezier)}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end ConstantsPackage; diff --git a/BusinessSimulation/Icons/Converter.mo b/BusinessSimulation/Icons/Converter.mo new file mode 100644 index 0000000..100ef67 --- /dev/null +++ b/BusinessSimulation/Icons/Converter.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Icons; + +partial block Converter "Icon for converter elements" + extends ConverterName; + annotation(Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Ellipse(visible = true, lineColor = {0, 0, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 4, extent = {{-60, -60}, {60, 60}})})); +end Converter; diff --git a/BusinessSimulation/Icons/ConverterName.mo b/BusinessSimulation/Icons/ConverterName.mo new file mode 100644 index 0000000..321ac25 --- /dev/null +++ b/BusinessSimulation/Icons/ConverterName.mo @@ -0,0 +1,5 @@ +within BusinessSimulation.Icons; + +partial class ConverterName "Icon for converter elements" + annotation(Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, -95}, textColor = {64, 64, 64}, extent = {{-150, -12}, {150, 12}}, textString = "%name", fontName = "Lato")})); +end ConverterName; diff --git a/BusinessSimulation/Icons/Conveyor.mo b/BusinessSimulation/Icons/Conveyor.mo new file mode 100644 index 0000000..d956e3f --- /dev/null +++ b/BusinessSimulation/Icons/Conveyor.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Icons; + +partial class Conveyor "Icon for conveyor stocks" + extends MaterialStock; + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {-50.416, -31.706}, points = {{0, 131.706}, {0, -68.294}}, color = {255, 0, 0}, thickness = 4, arrowSize = 1), Line(visible = true, origin = {49.584, -30.259}, points = {{0, 130.747}, {0, -69.741}}, color = {255, 0, 0}, thickness = 4, arrowSize = 1), Line(visible = true, origin = {0, 21.356}, points = {{0, 78.644}, {0, -78.644}}, color = {255, 0, 0}, thickness = 4, arrowSize = 1)}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Conveyor; diff --git a/BusinessSimulation/Icons/DataBus.mo b/BusinessSimulation/Icons/DataBus.mo new file mode 100644 index 0000000..8d3521e --- /dev/null +++ b/BusinessSimulation/Icons/DataBus.mo @@ -0,0 +1,7 @@ +within BusinessSimulation.Icons; + +partial class DataBus "Icon for information input and output busses" + annotation(Icon(coordinateSystem(preserveAspectRatio = false, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, lineColor = {0, 0, 128}, fillColor = {192, 192, 192}, fillPattern = FillPattern.Solid, lineThickness = 3, points = {{-80, 50}, {80, 50}, {100, 30}, {80, -40}, {60, -50}, {-60, -50}, {-80, -40}, {-100, 30}}, smooth = Smooth.Bezier), Ellipse(visible = true, origin = {-50, 11.841}, lineColor = {76, 112, 136}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-10, -10}, {10, 10}}), Ellipse(visible = true, origin = {0, 11.571}, lineColor = {76, 112, 136}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-10, -10}, {10, 10}}), Ellipse(visible = true, origin = {48.125, 10}, lineColor = {76, 112, 136}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-10, -10}, {10, 10}}), Ellipse(visible = true, origin = {-22, -16.159}, lineColor = {76, 112, 136}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, extent = {{-10, -10}, {10, 10}}), Ellipse(visible = true, origin = {28, -16.429}, lineColor = {76, 112, 136}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, extent = {{-10, -10}, {10, 10}})}), Diagram(coordinateSystem(preserveAspectRatio = false, extent = {{-100, -100}, {100, 100}}, initialScale = 0.2, grid = {5, 5}), graphics = {Text(visible = true, origin = {-0, 55}, textColor = {128, 128, 128}, extent = {{-100, -12}, {100, 12}}, textString = "%name", fontName = "Lato", textStyle = {TextStyle.Bold}), Polygon(visible = true, lineColor = {0, 0, 128}, fillColor = {192, 192, 192}, fillPattern = FillPattern.Solid, lineThickness = 3, points = {{-40, 25}, {40, 25}, {50, 15}, {40, -20}, {30, -25}, {-30, -25}, {-40, -20}, {-50, 15}}, smooth = Smooth.Bezier), Ellipse(visible = true, origin = {-25, 10}, lineColor = {76, 112, 136}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-5, -5}, {5, 5}}), Ellipse(visible = true, origin = {0, 10}, lineColor = {76, 112, 136}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-5, -5}, {5, 5}}), Ellipse(visible = true, origin = {25, 10}, lineColor = {76, 112, 136}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-5, -5}, {5, 5}}), Ellipse(visible = true, origin = {-13.006, -10}, lineColor = {76, 112, 136}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, extent = {{-5, -5}, {5, 5}}), Ellipse(visible = true, origin = {12.531, -10}, lineColor = {76, 112, 136}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, extent = {{-5, -5}, {5, 5}})}), Documentation(info = " +This icon is designed for a signal bus connector. +")); +end DataBus; diff --git a/BusinessSimulation/Icons/DataInPort.mo b/BusinessSimulation/Icons/DataInPort.mo new file mode 100644 index 0000000..c8794fc --- /dev/null +++ b/BusinessSimulation/Icons/DataInPort.mo @@ -0,0 +1,5 @@ +within BusinessSimulation.Icons; + +partial class DataInPort "Icon for an expandable connector for information input" + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, points = {{-100, 100}, {100, 0}, {-100, -100}, {-100, 100}}), Ellipse(visible = true, origin = {-24.747, 0}, lineColor = {255, 170, 0}, fillColor = {255, 170, 0}, fillPattern = FillPattern.Solid, extent = {{-24.747, -24.747}, {24.747, 24.747}})}), Diagram(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, origin = {-100, 0}, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, points = {{0, 50}, {100, 0}, {0, -50}, {0, 50}}), Text(visible = true, origin = {0, 80}, textColor = {128, 128, 128}, extent = {{-100, -12}, {100, 12}}, textString = "%name", fontName = "Lato", textStyle = {TextStyle.Bold})}), Documentation); +end DataInPort; diff --git a/BusinessSimulation/Icons/DataOutPort.mo b/BusinessSimulation/Icons/DataOutPort.mo new file mode 100644 index 0000000..8af99c3 --- /dev/null +++ b/BusinessSimulation/Icons/DataOutPort.mo @@ -0,0 +1,5 @@ +within BusinessSimulation.Icons; + +partial class DataOutPort "Icon for an expandable connector for information output" + annotation(defaultComponentName = "y", Icon(coordinateSystem(preserveAspectRatio = true, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, lineColor = {1, 37, 163}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-100, 100}, {100, 0}, {-100, -100}}), Ellipse(visible = true, origin = {-24.747, 0}, lineColor = {255, 170, 0}, fillColor = {255, 170, 0}, fillPattern = FillPattern.Solid, extent = {{-24.747, -24.747}, {24.747, 24.747}})}), Diagram(coordinateSystem(preserveAspectRatio = true, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, origin = {100, 0}, lineColor = {1, 37, 163}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-100, 50}, {0, 0}, {-100, -50}}), Text(visible = true, origin = {0, 80}, textColor = {128, 128, 128}, extent = {{-100, -12}, {100, 12}}, textString = "%name", fontName = "Lato", textStyle = {TextStyle.Bold})}), Documentation); +end DataOutPort; diff --git a/BusinessSimulation/Icons/DelayN.mo b/BusinessSimulation/Icons/DelayN.mo new file mode 100644 index 0000000..42aef16 --- /dev/null +++ b/BusinessSimulation/Icons/DelayN.mo @@ -0,0 +1,7 @@ +within BusinessSimulation.Icons; + +partial class DelayN "Icon for DelayN" + extends MaterialStock; + extends Clockface; + annotation(__Wolfram(itemFlippingEnabled = true), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end DelayN; diff --git a/BusinessSimulation/Icons/DiscreteSmoothLabel.mo b/BusinessSimulation/Icons/DiscreteSmoothLabel.mo new file mode 100644 index 0000000..fc7d5e5 --- /dev/null +++ b/BusinessSimulation/Icons/DiscreteSmoothLabel.mo @@ -0,0 +1,5 @@ +within BusinessSimulation.Icons; + +partial class DiscreteSmoothLabel "Mark converters as discrete" + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {53.863, 38}, textColor = {0, 0, 128}, extent = {{-16.137, -20}, {16.137, 20}}, textString = "···", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end DiscreteSmoothLabel; diff --git a/BusinessSimulation/Icons/DiscreteStockLabel.mo b/BusinessSimulation/Icons/DiscreteStockLabel.mo new file mode 100644 index 0000000..e1af492 --- /dev/null +++ b/BusinessSimulation/Icons/DiscreteStockLabel.mo @@ -0,0 +1,5 @@ +within BusinessSimulation.Icons; + +partial class DiscreteStockLabel "Mark stock element as discrete" + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {73.863, 81}, textColor = {128, 0, 128}, extent = {{-16.137, -20}, {16.137, 20}}, textString = "···", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end DiscreteStockLabel; diff --git a/BusinessSimulation/Icons/Enumeration.mo b/BusinessSimulation/Icons/Enumeration.mo new file mode 100644 index 0000000..a4b3a23 --- /dev/null +++ b/BusinessSimulation/Icons/Enumeration.mo @@ -0,0 +1,5 @@ +within BusinessSimulation.Icons; + +partial class Enumeration "Icon for type enumeration" + annotation(Icon(coordinateSystem(preserveAspectRatio = false, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {76, 112, 136}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-100, -100}, {100, 100}}), Text(visible = true, textColor = {76, 112, 136}, extent = {{-90, -50}, {90, 50}}, textString = "1..n", fontName = "Lato", textStyle = {TextStyle.Bold})})); +end Enumeration; diff --git a/BusinessSimulation/Icons/Example.mo b/BusinessSimulation/Icons/Example.mo new file mode 100644 index 0000000..793eaf9 --- /dev/null +++ b/BusinessSimulation/Icons/Example.mo @@ -0,0 +1,5 @@ +within BusinessSimulation.Icons; + +partial model Example "Icon for an example" + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Ellipse(visible = true, lineColor = {76, 112, 136}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-100, -100}, {100, 100}}), Polygon(visible = true, lineColor = {76, 112, 136}, fillColor = {76, 112, 136}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, points = {{-36, 60}, {64, 0}, {-36, -60}, {-36, 60}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Example; diff --git a/BusinessSimulation/Icons/ExamplesPackage/package.mo b/BusinessSimulation/Icons/ExamplesPackage/package.mo new file mode 100644 index 0000000..3f6ae36 --- /dev/null +++ b/BusinessSimulation/Icons/ExamplesPackage/package.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Icons; + +partial package ExamplesPackage "Icon for packages containing examples" + extends Package; + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, origin = {8, 14}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, points = {{-58, 46}, {42, -14}, {-58, -74}, {-58, 46}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end ExamplesPackage; diff --git a/BusinessSimulation/Icons/ExpandableFlowPort.mo b/BusinessSimulation/Icons/ExpandableFlowPort.mo new file mode 100644 index 0000000..5bfb918 --- /dev/null +++ b/BusinessSimulation/Icons/ExpandableFlowPort.mo @@ -0,0 +1,5 @@ +within BusinessSimulation.Icons; + +partial class ExpandableFlowPort "Icon for expandable flow ports" + annotation(Diagram(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, origin = {-5, 5}, lineColor = {128, 0, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-55, -55}, {55, 55}}), Text(visible = true, origin = {0, 90}, textColor = {128, 128, 128}, extent = {{-100, -12}, {100, 12}}, textString = "%name", fontName = "Lato", textStyle = {TextStyle.Bold})}), Documentation, Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {128, 0, 128}, fillColor = {128, 0, 128}, fillPattern = FillPattern.Solid, extent = {{-100, -100}, {100, 100}}), Rectangle(visible = true, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-80, -80}, {80, 80}}), Ellipse(visible = true, lineColor = {255, 170, 0}, fillColor = {255, 170, 0}, fillPattern = FillPattern.Solid, extent = {{-24.747, -24.747}, {24.747, 24.747}})})); +end ExpandableFlowPort; diff --git a/BusinessSimulation/Icons/ExpandableStockPort.mo b/BusinessSimulation/Icons/ExpandableStockPort.mo new file mode 100644 index 0000000..65a442b --- /dev/null +++ b/BusinessSimulation/Icons/ExpandableStockPort.mo @@ -0,0 +1,5 @@ +within BusinessSimulation.Icons; + +partial class ExpandableStockPort "Icon for expandable stock ports" + annotation(Diagram(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, origin = {-5, 5}, lineColor = {128, 0, 128}, fillColor = {128, 0, 128}, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-55, -55}, {55, 55}}), Text(visible = true, origin = {-0, 90}, textColor = {128, 128, 128}, extent = {{-100, -12}, {100, 12}}, textString = "%name", fontName = "Lato", textStyle = {TextStyle.Bold})}), Documentation, Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {128, 0, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 1, extent = {{-100, -100}, {100, 100}}), Rectangle(visible = true, lineColor = {128, 0, 128}, fillColor = {128, 0, 128}, fillPattern = FillPattern.Solid, extent = {{-80, -80}, {80, 80}}), Ellipse(visible = true, lineColor = {255, 170, 0}, fillColor = {255, 170, 0}, fillPattern = FillPattern.Solid, extent = {{-24.747, -24.747}, {24.747, 24.747}})})); +end ExpandableStockPort; diff --git a/BusinessSimulation/Icons/FlowIndicators.mo b/BusinessSimulation/Icons/FlowIndicators.mo new file mode 100644 index 0000000..8a6c333 --- /dev/null +++ b/BusinessSimulation/Icons/FlowIndicators.mo @@ -0,0 +1,5 @@ +within BusinessSimulation.Icons; + +partial class FlowIndicators "Arrows indicating flow" + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, origin = {-80.87, 0}, lineColor = {192, 192, 192}, fillColor = {192, 192, 192}, fillPattern = FillPattern.Solid, points = {{-2.435, 13.229}, {-2.435, -13.344}, {4.87, 0.115}}), Polygon(visible = true, origin = {-70.87, 0}, lineColor = {192, 192, 192}, fillColor = {192, 192, 192}, fillPattern = FillPattern.Solid, points = {{-2.435, 13.229}, {-2.435, -13.344}, {4.87, 0.115}}), Polygon(visible = true, origin = {70.439, 0}, lineColor = {192, 192, 192}, fillColor = {192, 192, 192}, fillPattern = FillPattern.Solid, points = {{-2.435, 13.229}, {-2.435, -13.344}, {4.87, 0.115}}), Polygon(visible = true, origin = {80.439, 0}, lineColor = {192, 192, 192}, fillColor = {192, 192, 192}, fillPattern = FillPattern.Solid, points = {{-2.435, 13.229}, {-2.435, -13.344}, {4.87, 0.115}})}), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end FlowIndicators; diff --git a/BusinessSimulation/Icons/Function.mo b/BusinessSimulation/Icons/Function.mo new file mode 100644 index 0000000..30be781 --- /dev/null +++ b/BusinessSimulation/Icons/Function.mo @@ -0,0 +1,5 @@ +within BusinessSimulation.Icons; + +partial function Function "Icon for functions" + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Ellipse(visible = true, lineColor = {0, 0, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-87.608, -87.608}, {87.608, 87.608}}), Text(visible = true, origin = {-10, 0}, textColor = {0, 0, 128}, extent = {{-90, -90}, {90, 90}}, textString = "f", textStyle = {TextStyle.Italic}), Text(visible = true, origin = {0, 112}, textColor = {64, 64, 64}, extent = {{-100, -12}, {100, 12}}, textString = "%name", fontName = "Lato ")}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Function; diff --git a/BusinessSimulation/Icons/FunctionLetter.mo b/BusinessSimulation/Icons/FunctionLetter.mo new file mode 100644 index 0000000..83b617f --- /dev/null +++ b/BusinessSimulation/Icons/FunctionLetter.mo @@ -0,0 +1,5 @@ +within BusinessSimulation.Icons; + +partial class FunctionLetter "FunctionLetter typically added for general function converters" + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {-2.676, 5.698}, textColor = {0, 0, 128}, extent = {{-40.145, -40.145}, {40.145, 40.145}}, textString = "f", fontName = "Lato", textStyle = {TextStyle.Italic})}), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end FunctionLetter; diff --git a/BusinessSimulation/Icons/FunctionsPackage/package.mo b/BusinessSimulation/Icons/FunctionsPackage/package.mo new file mode 100644 index 0000000..da847ab --- /dev/null +++ b/BusinessSimulation/Icons/FunctionsPackage/package.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Icons; + +partial package FunctionsPackage "Functions package icon" + extends Package; + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {15.113, -2.4}, textColor = {255, 255, 255}, extent = {{-40.266, -40.266}, {40.266, 40.266}}, textString = "(•)", fontName = "Lato"), Text(visible = true, origin = {-55, 5}, textColor = {255, 255, 255}, extent = {{-75, -75}, {75, 75}}, textString = "f", textStyle = {TextStyle.Italic})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end FunctionsPackage; diff --git a/BusinessSimulation/Icons/IconsPackage/package.mo b/BusinessSimulation/Icons/IconsPackage/package.mo new file mode 100644 index 0000000..8ebaa18 --- /dev/null +++ b/BusinessSimulation/Icons/IconsPackage/package.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Icons; + +partial package IconsPackage "Icon for an icons package" + extends Package; + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, origin = {-8.167, -17}, fillColor = {255, 255, 255}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, points = {{-15.833, 20}, {-15.833, 30}, {14.167, 40}, {24.167, 20}, {4.167, -30}, {14.167, -30}, {24.167, -30}, {24.167, -40}, {-5.833, -50}, {-15.833, -30}, {4.167, 20}, {-5.833, 20}}, smooth = Smooth.Bezier), Ellipse(visible = true, origin = {-0.5, 56.5}, fillColor = {255, 255, 255}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, extent = {{-12.5, -12.5}, {12.5, 12.5}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end IconsPackage; diff --git a/BusinessSimulation/Icons/Info.mo b/BusinessSimulation/Icons/Info.mo new file mode 100644 index 0000000..cdebd93 --- /dev/null +++ b/BusinessSimulation/Icons/Info.mo @@ -0,0 +1,5 @@ +within BusinessSimulation.Icons; + +partial class Info "Icon for information pages (UsersGuide)" + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Ellipse(visible = true, lineColor = {255, 170, 0}, fillColor = {255, 170, 0}, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-95, -95}, {95, 95}}), Polygon(visible = true, origin = {-4.167, -15}, fillColor = {255, 255, 255}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, points = {{-15.833, 20}, {-15.833, 30}, {14.167, 40}, {24.167, 20}, {4.167, -30}, {14.167, -30}, {24.167, -30}, {24.167, -40}, {-5.833, -50}, {-15.833, -30}, {4.167, 20}, {-5.833, 20}}, smooth = Smooth.Bezier), Ellipse(visible = true, origin = {7.5, 56.5}, fillColor = {255, 255, 255}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, extent = {{-12.5, -12.5}, {12.5, 12.5}})}), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Info; diff --git a/BusinessSimulation/Icons/InformationProcessing.mo b/BusinessSimulation/Icons/InformationProcessing.mo new file mode 100644 index 0000000..f766e60 --- /dev/null +++ b/BusinessSimulation/Icons/InformationProcessing.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Icons; + +partial block InformationProcessing "Icon for information processing molecules" + extends ComponentName; + annotation(__Wolfram(itemFlippingEnabled = true), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Ellipse(visible = true, lineColor = {0, 0, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 4, extent = {{-90, -90}, {90, 90}}), Rectangle(visible = true, origin = {0, 52.225}, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, lineThickness = 1, extent = {{-15.899, -19.317}, {15.899, 19.317}}, radius = 10), Text(visible = true, origin = {0.5, 52.448}, textColor = {0, 0, 128}, extent = {{-15.5, -20}, {15.5, 20}}, textString = "i", fontName = "Consolas")})); +end InformationProcessing; diff --git a/BusinessSimulation/Icons/InformationSourceIndicator.mo b/BusinessSimulation/Icons/InformationSourceIndicator.mo new file mode 100644 index 0000000..8ac858f --- /dev/null +++ b/BusinessSimulation/Icons/InformationSourceIndicator.mo @@ -0,0 +1,5 @@ +within BusinessSimulation.Icons; + +partial block InformationSourceIndicator "Icon used to indicate external information" + annotation(Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Ellipse(visible = true, lineColor = {0, 0, 128}, fillColor = {76, 112, 136}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-60, -60}, {60, 60}})})); +end InformationSourceIndicator; diff --git a/BusinessSimulation/Icons/InformationSources/package.mo b/BusinessSimulation/Icons/InformationSources/package.mo new file mode 100644 index 0000000..6712b44 --- /dev/null +++ b/BusinessSimulation/Icons/InformationSources/package.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Icons; + +partial package InformationSources "Package Icon for Information Sources" + extends Package; + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {128, 128, 128}, extent = {{-100, -100}, {100, 100}}, radius = 25), Polygon(visible = true, origin = {23.333, 0}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, points = {{-23.333, 30}, {46.667, 0}, {-23.333, -30}}), Rectangle(visible = true, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, extent = {{-70, -4.5}, {0, 4.5}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end InformationSources; diff --git a/BusinessSimulation/Icons/Interaction.mo b/BusinessSimulation/Icons/Interaction.mo new file mode 100644 index 0000000..6e85fc9 --- /dev/null +++ b/BusinessSimulation/Icons/Interaction.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Icons; + +partial class Interaction "Icon for interactional flow classes" + extends ComponentName; + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {0, 128, 0}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 4, extent = {{-100, -100}, {100, 100}}), Polygon(visible = true, origin = {72.114, -0.25}, rotation = -450, lineColor = {0, 128, 0}, fillColor = {0, 128, 0}, fillPattern = FillPattern.Solid, points = {{-22.295, -7.943}, {22.191, -7.943}, {0.104, 15.886}}), Text(visible = true, origin = {-73.452, 37.479}, textColor = {0, 128, 0}, extent = {{-13.452, -20}, {13.452, 20}}, textString = "A"), Text(visible = true, origin = {73.452, -43.134}, textColor = {0, 128, 0}, extent = {{-13.452, -20}, {13.452, 20}}, textString = "B"), Polygon(visible = true, origin = {-72.424, 0}, rotation = 450, lineColor = {0, 128, 0}, fillColor = {0, 128, 0}, fillPattern = FillPattern.Solid, points = {{22.295, -7.943}, {-22.191, -7.943}, {-0.104, 15.886}}), Rectangle(visible = true, origin = {40.723, -0.123}, lineColor = {0, 128, 0}, fillColor = {0, 128, 0}, fillPattern = FillPattern.Solid, extent = {{-26.573, -11.955}, {26.573, 11.955}}), Line(visible = true, origin = {-0, -11.973}, points = {{-66.898, 0}, {66.898, 0}}, color = {0, 128, 0}, thickness = 4, arrowSize = 1), Line(visible = true, origin = {-0, 11.777}, points = {{-66.291, 0}, {66.291, 0}}, color = {0, 128, 0}, thickness = 4, arrowSize = 1), Ellipse(visible = true, origin = {1.899, 0}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 1, extent = {{-17, -17}, {17, 17}}), Ellipse(visible = true, origin = {1.899, 0}, lineColor = {255, 255, 255}, fillColor = {0, 128, 0}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, lineThickness = 1, extent = {{-14, -14}, {14, 14}}), Text(visible = true, origin = {-74, 1}, textColor = {255, 255, 255}, extent = {{-13.452, -12}, {13.452, 12}}, textString = "+", fontName = "Lato", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {74, 1}, textColor = {255, 255, 255}, extent = {{-13.452, -12}, {13.452, 12}}, textString = "+", fontName = "Lato", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {2, 0}, textColor = {255, 255, 255}, extent = {{-16.513, -12}, {16.513, 12}}, textString = "X", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}))); +end Interaction; diff --git a/BusinessSimulation/Icons/InterfacesPackage/package.mo b/BusinessSimulation/Icons/InterfacesPackage/package.mo new file mode 100644 index 0000000..aefe15c --- /dev/null +++ b/BusinessSimulation/Icons/InterfacesPackage/package.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Icons; + +partial package InterfacesPackage "Icon for an interfaces package" + extends Package; + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, origin = {20, 0}, lineColor = {64, 64, 64}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-10, 70}, {10, 70}, {40, 20}, {80, 20}, {80, -20}, {40, -20}, {10, -70}, {-10, -70}}), Polygon(visible = true, fillColor = {255, 255, 255}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, points = {{-100, 20}, {-60, 20}, {-30, 70}, {-10, 70}, {-10, -70}, {-30, -70}, {-60, -20}, {-100, -20}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end InterfacesPackage; diff --git a/BusinessSimulation/Icons/InterpolationTable.mo b/BusinessSimulation/Icons/InterpolationTable.mo new file mode 100644 index 0000000..0a4628b --- /dev/null +++ b/BusinessSimulation/Icons/InterpolationTable.mo @@ -0,0 +1,5 @@ +within BusinessSimulation.Icons; + +partial class InterpolationTable "Icon for table functions" + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, origin = {17.96, 28.906}, lineColor = {255, 255, 255}, fillColor = {192, 192, 192}, fillPattern = FillPattern.Solid, extent = {{-17.96, -8.906}, {17.96, 8.906}}), Rectangle(visible = true, origin = {-17.96, 28.906}, lineColor = {255, 255, 255}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, extent = {{-17.96, -8.906}, {17.96, 8.906}}), Rectangle(visible = true, origin = {-17.96, 9.906}, lineColor = {255, 255, 255}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, extent = {{-17.96, -8.906}, {17.96, 8.906}}), Rectangle(visible = true, origin = {17.96, 9.906}, lineColor = {255, 255, 255}, fillColor = {192, 192, 192}, fillPattern = FillPattern.Solid, extent = {{-17.96, -8.906}, {17.96, 8.906}}), Rectangle(visible = true, origin = {-17.96, -9.094}, lineColor = {255, 255, 255}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, extent = {{-17.96, -8.906}, {17.96, 8.906}}), Rectangle(visible = true, origin = {17.96, -9.094}, lineColor = {255, 255, 255}, fillColor = {192, 192, 192}, fillPattern = FillPattern.Solid, extent = {{-17.96, -8.906}, {17.96, 8.906}}), Rectangle(visible = true, origin = {-17.96, -28.297}, lineColor = {255, 255, 255}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, extent = {{-17.96, -8.906}, {17.96, 8.906}}), Rectangle(visible = true, origin = {17.96, -28.297}, lineColor = {255, 255, 255}, fillColor = {192, 192, 192}, fillPattern = FillPattern.Solid, extent = {{-17.96, -8.906}, {17.96, 8.906}}), Ellipse(visible = true, origin = {16.097, 0}, lineColor = {255, 0, 0}, fillColor = {255, 0, 0}, fillPattern = FillPattern.Solid, extent = {{-3, -3}, {3, 3}}), Ellipse(visible = true, origin = {-18.903, 10}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-2, -2}, {2, 2}}), Ellipse(visible = true, origin = {-18.903, -10}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-2, -2}, {2, 2}}), Ellipse(visible = true, origin = {16.097, -11}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-2, -2}, {2, 2}}), Ellipse(visible = true, origin = {16.097, 10}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-2, -2}, {2, 2}}), Ellipse(visible = true, origin = {-18.903, 0}, lineColor = {128, 128, 128}, fillColor = {128, 128, 128}, fillPattern = FillPattern.Solid, extent = {{-3, -3}, {3, 3}})}), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end InterpolationTable; diff --git a/BusinessSimulation/Icons/MaterialStock.mo b/BusinessSimulation/Icons/MaterialStock.mo new file mode 100644 index 0000000..1b3d0f5 --- /dev/null +++ b/BusinessSimulation/Icons/MaterialStock.mo @@ -0,0 +1,7 @@ +within BusinessSimulation.Icons; + +partial class MaterialStock "General Icon for material stocks" + extends Stock; + extends MaterialStockIndicator; + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end MaterialStock; diff --git a/BusinessSimulation/Icons/MaterialStockIndicator.mo b/BusinessSimulation/Icons/MaterialStockIndicator.mo new file mode 100644 index 0000000..5e978c0 --- /dev/null +++ b/BusinessSimulation/Icons/MaterialStockIndicator.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Icons; + +partial class MaterialStockIndicator "General Icon for stocks" + extends ComponentName; + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {-81.678, 80}, textColor = {128, 0, 128}, extent = {{-16.137, -20}, {16.137, 20}}, textString = "+", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end MaterialStockIndicator; diff --git a/BusinessSimulation/Icons/MultiInput.mo b/BusinessSimulation/Icons/MultiInput.mo new file mode 100644 index 0000000..d653695 --- /dev/null +++ b/BusinessSimulation/Icons/MultiInput.mo @@ -0,0 +1,5 @@ +within BusinessSimulation.Icons; + +partial class MultiInput "Icon for multiple inputs" + annotation(defaultComponentName = "u", Diagram(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, lineColor = {5, 5, 125}, fillColor = {5, 5, 125}, fillPattern = FillPattern.Solid, points = {{0, 50}, {100, 0}, {0, -50}, {0, 50}}), Text(visible = true, origin = {0, 80}, textColor = {128, 128, 128}, extent = {{-100, -12}, {100, 12}}, textString = "%name", fontName = "Lato", textStyle = {TextStyle.Bold})}), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, points = {{-100, 100}, {100, 0}, {-100, -100}, {-100, 100}}), Ellipse(visible = true, origin = {-24.747, 0}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-24.747, -24.747}, {24.747, 24.747}})}), Documentation(info = "")); +end MultiInput; diff --git a/BusinessSimulation/Icons/MultiOutput.mo b/BusinessSimulation/Icons/MultiOutput.mo new file mode 100644 index 0000000..50ab819 --- /dev/null +++ b/BusinessSimulation/Icons/MultiOutput.mo @@ -0,0 +1,5 @@ +within BusinessSimulation.Icons; + +partial class MultiOutput "Icon for multiple outputs" + annotation(defaultComponentName = "y", Icon(coordinateSystem(preserveAspectRatio = true, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, lineColor = {1, 37, 163}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-100, 100}, {100, 0}, {-100, -100}}), Ellipse(visible = true, origin = {-24.747, 0}, lineColor = {255, 255, 255}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, extent = {{-24.747, -24.747}, {24.747, 24.747}})}), Diagram(coordinateSystem(preserveAspectRatio = true, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, lineColor = {1, 37, 163}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-100, 50}, {0, 0}, {-100, -50}}), Text(visible = true, origin = {0, 80}, textColor = {128, 128, 128}, extent = {{-100, -12}, {100, 12}}, textString = "%name", fontName = "Lato", textStyle = {TextStyle.Bold})}), Documentation); +end MultiOutput; diff --git a/BusinessSimulation/Icons/MultiPort.mo b/BusinessSimulation/Icons/MultiPort.mo new file mode 100644 index 0000000..a776708 --- /dev/null +++ b/BusinessSimulation/Icons/MultiPort.mo @@ -0,0 +1,7 @@ +within BusinessSimulation.Icons; + +partial class MultiPort "Icon for mass transport pipelines" + annotation(Icon(coordinateSystem(preserveAspectRatio = false, extent = {{-100, -100}, {100, 100}}, initialScale = 0.2, grid = {10, 10}), graphics = {Polygon(visible = true, lineColor = {128, 0, 128}, fillColor = {192, 192, 192}, fillPattern = FillPattern.Solid, lineThickness = 3, points = {{-80, 50}, {80, 50}, {100, 30}, {80, -40}, {60, -50}, {-60, -50}, {-80, -40}, {-100, 30}}, smooth = Smooth.Bezier), Rectangle(visible = true, origin = {-40, 0}, lineColor = {128, 0, 128}, fillColor = {128, 0, 128}, fillPattern = FillPattern.Solid, extent = {{-30, -30}, {30, 30}}), Rectangle(visible = true, origin = {-40, 0}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-25, -25}, {25, 25}}), Ellipse(visible = true, origin = {-40, 0}, lineColor = {255, 255, 255}, fillColor = {128, 0, 128}, fillPattern = FillPattern.Solid, extent = {{-10, -10}, {10, 10}}), Rectangle(visible = true, origin = {40, 0}, lineColor = {128, 0, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 1, extent = {{-30, -30}, {30, 30}}), Rectangle(visible = true, origin = {40, 0}, lineColor = {128, 0, 128}, fillColor = {128, 0, 128}, fillPattern = FillPattern.Solid, extent = {{-25, -25}, {25, 25}}), Ellipse(visible = true, origin = {40, 0}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-10, -10}, {10, 10}})}), Diagram(coordinateSystem(preserveAspectRatio = false, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {5, 5}), graphics = {Polygon(visible = true, lineColor = {128, 0, 128}, fillColor = {192, 192, 192}, fillPattern = FillPattern.Solid, lineThickness = 3, points = {{-40, 25}, {40, 25}, {50, 15}, {40, -20}, {30, -25}, {-30, -25}, {-40, -20}, {-50, 15}}, smooth = Smooth.Bezier), Text(visible = true, origin = {-0, 55}, textColor = {128, 128, 128}, extent = {{-100, -12}, {100, 12}}, textString = "%name", fontName = "Lato", textStyle = {TextStyle.Bold})}), Documentation(info = " +This icon is designed for a signal bus connector. +")); +end MultiPort; diff --git a/BusinessSimulation/Icons/OmniBus.mo b/BusinessSimulation/Icons/OmniBus.mo new file mode 100644 index 0000000..18d1488 --- /dev/null +++ b/BusinessSimulation/Icons/OmniBus.mo @@ -0,0 +1,7 @@ +within BusinessSimulation.Icons; + +partial class OmniBus "Icon for combined mass and information transport pipelines" + annotation(Icon(coordinateSystem(preserveAspectRatio = false, extent = {{-100, -100}, {100, 100}}, initialScale = 0.2, grid = {10, 10}), graphics = {Polygon(visible = true, lineColor = {76, 112, 136}, fillColor = {192, 192, 192}, fillPattern = FillPattern.Solid, lineThickness = 3, points = {{-80, 50}, {80, 50}, {100, 30}, {80, -40}, {60, -50}, {-60, -50}, {-80, -40}, {-100, 30}}, smooth = Smooth.Bezier), Rectangle(visible = true, origin = {-33.091, -6.909}, lineColor = {128, 0, 128}, fillColor = {128, 0, 128}, fillPattern = FillPattern.Solid, extent = {{-23.091, -23.091}, {23.091, 23.091}}), Rectangle(visible = true, origin = {-32.5, -7.5}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-17.5, -17.5}, {17.5, 17.5}}), Ellipse(visible = true, origin = {-32.394, -7.606}, lineColor = {255, 255, 255}, fillColor = {128, 0, 128}, fillPattern = FillPattern.Solid, extent = {{-7.606, -7.606}, {7.606, 7.606}}), Rectangle(visible = true, origin = {33.223, -6.777}, lineColor = {128, 0, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 1, extent = {{-23.223, -23.223}, {23.223, 23.223}}), Rectangle(visible = true, origin = {33.644, -6.614}, lineColor = {128, 0, 128}, fillColor = {128, 0, 128}, fillPattern = FillPattern.Solid, extent = {{-17.356, -17.356}, {17.356, 17.356}}), Ellipse(visible = true, origin = {34.394, -6.606}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-7.606, -7.606}, {7.606, 7.606}}), Ellipse(visible = true, origin = {-40, 33.069}, lineColor = {76, 112, 136}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-5, -5}, {5, 5}}), Ellipse(visible = true, origin = {-22.337, 32.861}, lineColor = {76, 112, 136}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, extent = {{-5, -5}, {5, 5}}), Ellipse(visible = true, origin = {25, 32.213}, lineColor = {76, 112, 136}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, extent = {{-5, -5}, {5, 5}}), Ellipse(visible = true, origin = {42.663, 32.005}, lineColor = {76, 112, 136}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-5, -5}, {5, 5}})}), Diagram(coordinateSystem(preserveAspectRatio = false, extent = {{-100, -100}, {100, 100}}, initialScale = 0.2, grid = {5, 5}), graphics = {Polygon(visible = true, lineColor = {76, 112, 136}, fillColor = {192, 192, 192}, fillPattern = FillPattern.Solid, lineThickness = 3, points = {{-40, 25}, {40, 25}, {50, 15}, {40, -20}, {30, -25}, {-30, -25}, {-40, -20}, {-50, 15}}, smooth = Smooth.Bezier), Text(visible = true, origin = {-0, 55}, textColor = {128, 128, 128}, extent = {{-100, -12}, {100, 12}}, textString = "%name", fontName = "Lato", textStyle = {TextStyle.Bold})}), Documentation(info = " +This icon is designed for a signal bus connector. +")); +end OmniBus; diff --git a/BusinessSimulation/Icons/Outflow.mo b/BusinessSimulation/Icons/Outflow.mo new file mode 100644 index 0000000..bd12046 --- /dev/null +++ b/BusinessSimulation/Icons/Outflow.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Icons; + +partial model Outflow "Icon for outflow classes" + extends ComponentName; + annotation(__Wolfram(itemFlippingEnabled = true), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {0, 128, 0}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{100, 100}, {-100, -100}}), Polygon(visible = true, origin = {72.114, -0.25}, rotation = -450, lineColor = {0, 128, 0}, fillColor = {0, 128, 0}, fillPattern = FillPattern.Solid, points = {{-22.295, -7.943}, {22.191, -7.943}, {0.104, 15.886}}), Text(visible = true, origin = {-73.452, 37.479}, textColor = {0, 128, 0}, extent = {{-13.452, -20}, {13.452, 20}}, textString = "A"), Text(visible = true, origin = {73.452, -43.134}, textColor = {0, 128, 0}, extent = {{-13.452, -20}, {13.452, 20}}, textString = "B"), Line(visible = true, origin = {-3.902, 11.777}, points = {{-70.951, 0}, {70.951, 0}}, color = {0, 128, 0}, thickness = 4, arrowSize = 1), Line(visible = true, origin = {-4.227, -11.973}, points = {{-70.669, 0}, {70.669, 0}}, color = {0, 128, 0}, thickness = 4, arrowSize = 1)}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Outflow; diff --git a/BusinessSimulation/Icons/Oven.mo b/BusinessSimulation/Icons/Oven.mo new file mode 100644 index 0000000..95ea40b --- /dev/null +++ b/BusinessSimulation/Icons/Oven.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Icons; + +partial class Oven "Icon for ovens" + extends DelayN; + annotation(__Wolfram(itemFlippingEnabled = true), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {255, 0, 0}, fillColor = {255, 255, 255}, lineThickness = 4, extent = {{-60, -60}, {60, 60}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Oven; diff --git a/BusinessSimulation/Icons/Package/package.mo b/BusinessSimulation/Icons/Package/package.mo new file mode 100644 index 0000000..ef5ba29 --- /dev/null +++ b/BusinessSimulation/Icons/Package/package.mo @@ -0,0 +1,5 @@ +within BusinessSimulation.Icons; + +partial package Package "Basic package icon" + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {76, 112, 136}, fillColor = {113, 166, 201}, pattern = LinePattern.None, fillPattern = FillPattern.HorizontalCylinder, lineThickness = 4, extent = {{-100, -100}, {100, 100}}, radius = 25)}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Package; diff --git a/BusinessSimulation/Icons/Policy.mo b/BusinessSimulation/Icons/Policy.mo new file mode 100644 index 0000000..b9f829d --- /dev/null +++ b/BusinessSimulation/Icons/Policy.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Icons; + +partial block Policy "Policy Block (Controller)" + extends ComponentName; + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Ellipse(visible = true, lineColor = {0, 0, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 4, extent = {{-90, -90}, {90, 90}}), Line(visible = true, origin = {0.067, 70}, rotation = -90, points = {{0, 55.552}, {0, -55.552}}, color = {0, 0, 128}, thickness = 2.5, arrowSize = 0), Line(visible = true, origin = {0.335, -70}, rotation = -90, points = {{0, 55.955}, {0, -55.955}}, color = {0, 0, 128}, thickness = 2.5, arrowSize = 0)}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Policy; diff --git a/BusinessSimulation/Icons/Queue.mo b/BusinessSimulation/Icons/Queue.mo new file mode 100644 index 0000000..e40a0d5 --- /dev/null +++ b/BusinessSimulation/Icons/Queue.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Icons; + +partial class Queue "Icon for queues" + extends MaterialStock; + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {0, 21.356}, points = {{0, 78.644}, {0, -78.644}}, color = {255, 0, 0}, thickness = 4, arrowSize = 1), Line(visible = true, origin = {-50, -22.696}, points = {{0, 77.304}, {0, -77.304}}, color = {255, 0, 0}, thickness = 4, arrowSize = 1), Line(visible = true, origin = {50, -22.696}, points = {{0, 77.304}, {0, -77.304}}, color = {255, 0, 0}, thickness = 4, arrowSize = 1)}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Queue; diff --git a/BusinessSimulation/Icons/Record.mo b/BusinessSimulation/Icons/Record.mo new file mode 100644 index 0000000..1faa62e --- /dev/null +++ b/BusinessSimulation/Icons/Record.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Icons; + +partial class Record "Icon for records" + extends Icons.ComponentName; + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, origin = {0, -25}, lineColor = {64, 64, 64}, fillColor = {255, 215, 136}, fillPattern = FillPattern.Solid, extent = {{-100, -75}, {100, 75}}, radius = 25), Rectangle(visible = true, origin = {0, -25}, lineColor = {255, 255, 255}, fillColor = {76, 112, 136}, fillPattern = FillPattern.Solid, extent = {{-100, -75}, {100, 75}}, radius = 25), Line(visible = true, points = {{-100, 0}, {100, 0}}, color = {255, 255, 255}), Line(visible = true, origin = {0, -50}, points = {{-100, 0}, {100, 0}}, color = {255, 255, 255}), Line(visible = true, origin = {0, -25}, points = {{0, 75}, {0, -75}}, color = {255, 255, 255})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Record; diff --git a/BusinessSimulation/Icons/SimulationModel.mo b/BusinessSimulation/Icons/SimulationModel.mo new file mode 100644 index 0000000..9eb2cf0 --- /dev/null +++ b/BusinessSimulation/Icons/SimulationModel.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Icons; + +partial model SimulationModel "Icon for Base Model" + extends Package; + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, origin = {-51.766, 60}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-10, -10}, {10, 10}}), Rectangle(visible = true, origin = {0, 25.188}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-10, -10}, {10, 10}}), Rectangle(visible = true, origin = {41.891, 60}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-10, -10}, {10, 10}}), Rectangle(visible = true, origin = {40, -17.73}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-10, -10}, {10, 10}}), Rectangle(visible = true, origin = {-51.947, 1.702}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-10, -10}, {10, 10}}), Line(visible = true, origin = {-3.23, 60}, points = {{-41.28, 0}, {41.28, 0}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-52.032, 30.442}, points = {{0, 27.078}, {0, -27.078}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {40, 21.017}, points = {{0, 31.017}, {0, -31.017}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-32.173, 14.201}, points = {{24.74, 10.755}, {5.98, 10.755}, {5.98, -12.961}, {-12.072, -12.961}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-24.173, 6.201}, points = {{55.852, -24.074}, {24.173, -24.074}, {24.173, 10.789}}, color = {255, 255, 255}, thickness = 1), Rectangle(visible = true, origin = {0, -62.812}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-10, -10}, {10, 10}}), Line(visible = true, origin = {-6.173, -0.119}, points = {{6.173, -55.896}, {6.173, 16.134}}, color = {255, 255, 255}, thickness = 1)}), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end SimulationModel; diff --git a/BusinessSimulation/Icons/Sink.mo b/BusinessSimulation/Icons/Sink.mo new file mode 100644 index 0000000..4b29a77 --- /dev/null +++ b/BusinessSimulation/Icons/Sink.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Icons; + +partial class Sink "General icon for sinks" + extends ComponentName; + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {0, 128, 0}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 4, extent = {{-100, -100}, {100, 100}}), Rectangle(visible = true, origin = {-59.838, 0}, lineColor = {255, 0, 0}, fillColor = {255, 255, 255}, lineThickness = 2.5, extent = {{-32.838, -32.117}, {32.838, 32.117}}), Polygon(visible = true, origin = {-9.461, 0.052}, rotation = -990, lineColor = {0, 128, 0}, fillColor = {0, 128, 0}, fillPattern = FillPattern.Solid, points = {{-22.295, -7.943}, {22.191, -7.943}, {0.104, 15.886}}), Line(visible = true, origin = {40.959, 10}, points = {{45.054, 0}, {-45.054, 0}}, color = {0, 128, 0}, thickness = 4, arrowSize = 0), Line(visible = true, origin = {41.034, -10}, points = {{44.979, 0}, {-44.979, 0}}, color = {0, 128, 0}, thickness = 4, arrowSize = 0), Ellipse(visible = true, origin = {41.899, 0}, lineColor = {0, 128, 0}, fillColor = {0, 128, 0}, fillPattern = FillPattern.Solid, lineThickness = 1, extent = {{-17, -17}, {17, 17}}), Line(visible = true, origin = {-59.639, -1.461}, points = {{-19.013, -1.251}, {-19.013, 5.61}, {-13.146, 10.097}, {-4.518, 6.3}, {3.107, -1.637}, {9.976, -6.855}, {16.533, -6.855}, {19.639, -3.018}, {19.639, 4.92}, {13.107, 11.132}, {6.525, 8.716}, {3.107, 3.145}, {-4.173, -6.855}, {-14.872, -8.539}, {-19.013, -1.251}, {-19.013, -1.251}}, color = {255, 0, 0}, thickness = 2.5, smooth = Smooth.Bezier), Text(visible = true, origin = {42, 0}, textColor = {255, 255, 255}, extent = {{-16.513, -12}, {16.513, 12}}, textString = "X", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Sink; diff --git a/BusinessSimulation/Icons/Smooth.mo b/BusinessSimulation/Icons/Smooth.mo new file mode 100644 index 0000000..3a01538 --- /dev/null +++ b/BusinessSimulation/Icons/Smooth.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Icons; + +partial block Smooth "Icon to be used for converters that contain stocks" + extends ConverterName; + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {0, 0, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-80, -50}, {80, 50}})}), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Smooth; diff --git a/BusinessSimulation/Icons/Source.mo b/BusinessSimulation/Icons/Source.mo new file mode 100644 index 0000000..351a4ca --- /dev/null +++ b/BusinessSimulation/Icons/Source.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Icons; + +partial class Source "General icon for sources" + extends ComponentName; + annotation(__Wolfram(itemFlippingEnabled = true), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {0, 128, 0}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 4, extent = {{-100, -100}, {100, 100}}), Line(visible = true, origin = {19.916, -10}, points = {{-46.748, 0}, {46.748, 0}}, color = {0, 128, 0}, thickness = 4, arrowSize = 0), Line(visible = true, origin = {19.213, 8.274}, points = {{-46.013, 0}, {46.013, 0}}, color = {0, 128, 0}, thickness = 4, arrowSize = 0), Rectangle(visible = true, origin = {-59.838, 0}, lineColor = {255, 0, 0}, fillColor = {255, 255, 255}, lineThickness = 2.5, extent = {{-32.838, -32.117}, {32.838, 32.117}}), Polygon(visible = true, origin = {72.114, -0.25}, rotation = -450, lineColor = {0, 128, 0}, fillColor = {0, 128, 0}, fillPattern = FillPattern.Solid, points = {{-22.295, -7.943}, {22.191, -7.943}, {0.104, 15.886}}), Ellipse(visible = true, origin = {21.899, 0}, lineColor = {0, 128, 0}, fillColor = {0, 128, 0}, fillPattern = FillPattern.Solid, lineThickness = 1, extent = {{-15.107, -15.107}, {15.107, 15.107}}), Line(visible = true, origin = {-59.639, -1.461}, points = {{-19.013, -1.251}, {-19.013, 5.61}, {-13.146, 10.097}, {-4.518, 6.3}, {3.107, -1.637}, {9.976, -6.855}, {16.533, -6.855}, {19.639, -3.018}, {19.639, 4.92}, {13.107, 11.132}, {6.525, 8.716}, {3.107, 3.145}, {-4.173, -6.855}, {-14.872, -8.539}, {-19.013, -1.251}, {-19.013, -1.251}}, color = {255, 0, 0}, thickness = 2.5, smooth = Smooth.Bezier), Text(visible = true, origin = {22, 0}, textColor = {255, 255, 255}, extent = {{-16.513, -12}, {16.513, 12}}, textString = "X", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Source; diff --git a/BusinessSimulation/Icons/SourceOrSink.mo b/BusinessSimulation/Icons/SourceOrSink.mo new file mode 100644 index 0000000..cf3ad34 --- /dev/null +++ b/BusinessSimulation/Icons/SourceOrSink.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Icons; + +partial class SourceOrSink "General icon for sources or sinks" + extends ComponentName; + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {0, 128, 0}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 4, extent = {{-100, -100}, {100, 100}}), Polygon(visible = true, origin = {72.114, -0.25}, rotation = -450, lineColor = {0, 128, 0}, fillColor = {0, 128, 0}, fillPattern = FillPattern.Solid, points = {{-22.295, -7.943}, {22.191, -7.943}, {0.104, 15.886}}), Rectangle(visible = true, origin = {-59.838, 0}, lineColor = {255, 0, 0}, fillColor = {255, 255, 255}, lineThickness = 2.5, extent = {{-32.838, -32.117}, {32.838, 32.117}}), Polygon(visible = true, origin = {-9.461, 0.052}, rotation = -990, lineColor = {0, 128, 0}, fillColor = {0, 128, 0}, fillPattern = FillPattern.Solid, points = {{-22.295, -7.943}, {22.191, -7.943}, {0.104, 15.886}}), Line(visible = true, origin = {-59.639, -1.461}, points = {{-19.013, -1.251}, {-19.013, 5.61}, {-13.146, 10.097}, {-4.518, 6.3}, {3.107, -1.637}, {9.976, -6.855}, {16.533, -6.855}, {19.639, -3.018}, {19.639, 4.92}, {13.107, 11.132}, {6.525, 8.716}, {3.107, 3.145}, {-4.173, -6.855}, {-14.872, -8.539}, {-19.013, -1.251}, {-19.013, -1.251}}, color = {255, 0, 0}, thickness = 2.5, smooth = Smooth.Bezier), Line(visible = true, origin = {31.043, -10}, points = {{-34.814, 0}, {34.814, 0}}, color = {0, 128, 0}, thickness = 4, arrowSize = 0), Line(visible = true, origin = {31.312, 10}, points = {{-35.083, 0}, {35.083, 0}}, color = {0, 128, 0}, thickness = 4, arrowSize = 0), Text(visible = true, origin = {74, 1}, textColor = {255, 255, 255}, extent = {{-13.452, -12}, {13.452, 12}}, textString = "+", fontName = "Lato", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {-12, 2}, textColor = {255, 255, 255}, extent = {{-13.452, -12}, {13.452, 12}}, textString = "–", fontName = "Lato", textStyle = {TextStyle.Bold}), Ellipse(visible = true, origin = {31.899, 0}, lineColor = {0, 128, 0}, fillColor = {0, 128, 0}, fillPattern = FillPattern.Solid, lineThickness = 1, extent = {{-17, -17}, {17, 17}}), Text(visible = true, origin = {32, 0}, textColor = {255, 255, 255}, extent = {{-16.513, -12}, {16.513, 12}}, textString = "X", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end SourceOrSink; diff --git a/BusinessSimulation/Icons/Stock.mo b/BusinessSimulation/Icons/Stock.mo new file mode 100644 index 0000000..cfc165d --- /dev/null +++ b/BusinessSimulation/Icons/Stock.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Icons; + +partial class Stock "General Icon for stocks" + extends ComponentName; + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {255, 0, 0}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 4, extent = {{-100, -100}, {100, 100}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Stock; diff --git a/BusinessSimulation/Icons/SubsystemActuator.mo b/BusinessSimulation/Icons/SubsystemActuator.mo new file mode 100644 index 0000000..14315b9 --- /dev/null +++ b/BusinessSimulation/Icons/SubsystemActuator.mo @@ -0,0 +1,7 @@ +within BusinessSimulation.Icons; + +partial class SubsystemActuator "Icon for subsystems with flow ports" + // extends ComponentName; + extends Icons.SubsystemTransceiver; + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end SubsystemActuator; diff --git a/BusinessSimulation/Icons/SubsystemBlock.mo b/BusinessSimulation/Icons/SubsystemBlock.mo new file mode 100644 index 0000000..f1af324 --- /dev/null +++ b/BusinessSimulation/Icons/SubsystemBlock.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Icons; + +partial class SubsystemBlock "Icon for subsystems with flow ports" + extends ComponentName; + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {0, 0, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 4, extent = {{-100, -100}, {100, 100}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end SubsystemBlock; diff --git a/BusinessSimulation/Icons/SubsystemIncubator.mo b/BusinessSimulation/Icons/SubsystemIncubator.mo new file mode 100644 index 0000000..c554760 --- /dev/null +++ b/BusinessSimulation/Icons/SubsystemIncubator.mo @@ -0,0 +1,7 @@ +within BusinessSimulation.Icons; + +partial class SubsystemIncubator "General Icon for stocks" + // extends Icons.Stock; + extends Icons.SubsystemTransceiver; + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end SubsystemIncubator; diff --git a/BusinessSimulation/Icons/SubsystemTransceiver.mo b/BusinessSimulation/Icons/SubsystemTransceiver.mo new file mode 100644 index 0000000..76cc667 --- /dev/null +++ b/BusinessSimulation/Icons/SubsystemTransceiver.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Icons; + +partial class SubsystemTransceiver "Icon for subsystems with mixed ports" + extends ComponentName; + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {76, 112, 136}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 4, extent = {{-100, -100}, {100, 100}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end SubsystemTransceiver; diff --git a/BusinessSimulation/Icons/Theta.mo b/BusinessSimulation/Icons/Theta.mo new file mode 100644 index 0000000..655c16e --- /dev/null +++ b/BusinessSimulation/Icons/Theta.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Icons; + +partial class Theta "Icon for a class providing global parameters" + extends ConverterName; + annotation(Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {192, 192, 192}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 1, extent = {{-50, -50}, {50, 50}}), Text(visible = true, textColor = {0, 0, 128}, extent = {{-100, -24}, {100, 24}}, textString = "θ", fontName = "Lato", textStyle = {TextStyle.Bold, TextStyle.Italic})})); +end Theta; diff --git a/BusinessSimulation/Icons/TypesPackage/package.mo b/BusinessSimulation/Icons/TypesPackage/package.mo new file mode 100644 index 0000000..100fe62 --- /dev/null +++ b/BusinessSimulation/Icons/TypesPackage/package.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Icons; + +partial package TypesPackage "Icon for a types package" + extends Package; + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, origin = {-12.167, -23}, fillColor = {255, 255, 255}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, points = {{12.167, 65}, {14.167, 93}, {36.167, 89}, {24.167, 20}, {4.167, -30}, {14.167, -30}, {24.167, -30}, {24.167, -40}, {-5.833, -50}, {-15.833, -30}, {4.167, 20}, {12.167, 65}}, smooth = Smooth.Bezier), Polygon(visible = true, origin = {2.74, 1.667}, fillColor = {255, 255, 255}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, points = {{49.26, 22.333}, {31.26, 24.333}, {7.26, 18.333}, {-26.74, 10.333}, {-46.74, 14.333}, {-48.74, 6.333}, {-32.74, 0.333}, {-6.74, 4.333}, {33.26, 14.333}, {49.26, 14.333}, {49.26, 22.333}}, smooth = Smooth.Bezier)}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end TypesPackage; diff --git a/BusinessSimulation/Icons/UnidirectionalFlow.mo b/BusinessSimulation/Icons/UnidirectionalFlow.mo new file mode 100644 index 0000000..7ab89fd --- /dev/null +++ b/BusinessSimulation/Icons/UnidirectionalFlow.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Icons; + +partial class UnidirectionalFlow "Icon for unidirectional flow classes" + extends ComponentName; + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {0, 128, 0}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-100, -100}, {100, 100}}), Rectangle(visible = true, lineColor = {0, 128, 0}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-100, -100}, {100, 100}}), Line(visible = true, origin = {-4.075, -11.973}, points = {{-70.821, 0}, {70.821, 0}}, color = {0, 128, 0}, thickness = 4, arrowSize = 1), Line(visible = true, origin = {-4.357, 11.777}, points = {{-70.496, 0}, {70.496, 0}}, color = {0, 128, 0}, thickness = 4, arrowSize = 1), Polygon(visible = true, origin = {72.114, -0.25}, rotation = -450, lineColor = {0, 128, 0}, fillColor = {0, 128, 0}, fillPattern = FillPattern.Solid, points = {{-22.295, -7.943}, {22.191, -7.943}, {0.104, 15.886}}), Text(visible = true, origin = {-73.452, 37.479}, textColor = {0, 128, 0}, extent = {{-13.452, -20}, {13.452, 20}}, textString = "A"), Text(visible = true, origin = {73.452, -43.134}, textColor = {0, 128, 0}, extent = {{-13.452, -20}, {13.452, 20}}, textString = "B"), Ellipse(visible = true, origin = {1.899, 0}, lineColor = {0, 128, 0}, fillColor = {0, 128, 0}, fillPattern = FillPattern.Solid, lineThickness = 1, extent = {{-17, -17}, {17, 17}}), Text(visible = true, origin = {2, 0}, textColor = {255, 255, 255}, extent = {{-16.513, -12}, {16.513, 12}}, textString = "X", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end UnidirectionalFlow; diff --git a/BusinessSimulation/Icons/UnitsPackage/package.mo b/BusinessSimulation/Icons/UnitsPackage/package.mo new file mode 100644 index 0000000..ccf44c5 --- /dev/null +++ b/BusinessSimulation/Icons/UnitsPackage/package.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Icons; + +partial package UnitsPackage "Units package icon" + extends Package; + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {255, 255, 255}, extent = {{-53.838, -67.501}, {53.838, 67.501}}, textString = "kg", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end UnitsPackage; diff --git a/BusinessSimulation/Icons/UtilitiesPackage/package.mo b/BusinessSimulation/Icons/UtilitiesPackage/package.mo new file mode 100644 index 0000000..c07e0f5 --- /dev/null +++ b/BusinessSimulation/Icons/UtilitiesPackage/package.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Icons; + +partial package UtilitiesPackage "Package icon for utilities" + extends Package; + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, origin = {1.383, -4.142}, rotation = 45, lineColor = {76, 112, 136}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-15, 93.333}, {-15, 68.333}, {0, 58.333}, {15, 68.333}, {15, 93.333}, {20, 93.333}, {25, 83.333}, {25, 58.333}, {10, 43.333}, {10, -41.667}, {25, -56.667}, {25, -76.667}, {10, -91.667}, {0, -91.667}, {0, -81.667}, {5, -81.667}, {15, -71.667}, {15, -61.667}, {5, -51.667}, {-5, -51.667}, {-15, -61.667}, {-15, -71.667}, {-5, -81.667}, {0, -81.667}, {0, -91.667}, {-10, -91.667}, {-25, -76.667}, {-25, -56.667}, {-10, -41.667}, {-10, 43.333}, {-25, 58.333}, {-25, 83.333}, {-20, 93.333}}), Polygon(visible = true, origin = {10.102, 5.218}, rotation = -45, lineColor = {76, 112, 136}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-15, 87.273}, {15, 87.273}, {20, 82.273}, {20, 27.273}, {10, 17.273}, {10, 7.273}, {20, 2.273}, {20, -2.727}, {5, -2.727}, {5, -77.727}, {10, -87.727}, {5, -112.727}, {-5, -112.727}, {-10, -87.727}, {-5, -77.727}, {-5, -2.727}, {-20, -2.727}, {-20, 2.273}, {-10, 7.273}, {-10, 17.273}, {-20, 27.273}, {-20, 82.273}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end UtilitiesPackage; diff --git a/BusinessSimulation/Icons/VariantsPackage/package.mo b/BusinessSimulation/Icons/VariantsPackage/package.mo new file mode 100644 index 0000000..7687e77 --- /dev/null +++ b/BusinessSimulation/Icons/VariantsPackage/package.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Icons; + +partial package VariantsPackage "Variants class package icon" + extends Package; + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Ellipse(visible = true, origin = {-40, 40}, lineColor = {128, 128, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-30, -30}, {30, 30}}), Ellipse(visible = true, origin = {40, 40}, lineColor = {128, 128, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-30, -30}, {30, 30}}), Ellipse(visible = true, origin = {-40, -40}, lineColor = {128, 128, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-30, -30}, {30, 30}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end VariantsPackage; diff --git a/BusinessSimulation/Icons/World.mo b/BusinessSimulation/Icons/World.mo new file mode 100644 index 0000000..75c20d2 --- /dev/null +++ b/BusinessSimulation/Icons/World.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Icons; + +partial class World "Icon to represent the world or the environment" + extends ComponentName; + annotation(Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Bitmap(visible = true, origin = {0, -5.282}, fileName = "modelica://BusinessSimulation/Resources/Images/Icons/World/World.png", imageSource = "", extent = {{-97.75, -57.683}, {97.75, 57.683}})})); +end World; diff --git a/BusinessSimulation/Icons/package.mo b/BusinessSimulation/Icons/package.mo new file mode 100644 index 0000000..0a800ce --- /dev/null +++ b/BusinessSimulation/Icons/package.mo @@ -0,0 +1,11 @@ +within BusinessSimulation; + +package Icons "Partial classes for icons" + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This package contains partial classes for icons used in the library.

+
+
+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {76, 112, 136}, fillColor = {113, 166, 201}, pattern = LinePattern.None, fillPattern = FillPattern.HorizontalCylinder, lineThickness = 4, extent = {{-100, -100}, {100, 100}}, radius = 25), Polygon(visible = true, origin = {-8.167, -17}, fillColor = {255, 255, 255}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, points = {{-15.833, 20}, {-15.833, 30}, {14.167, 40}, {24.167, 20}, {4.167, -30}, {14.167, -30}, {24.167, -30}, {24.167, -40}, {-5.833, -50}, {-15.833, -30}, {4.167, 20}, {-5.833, 20}}, smooth = Smooth.Bezier), Ellipse(visible = true, origin = {-0.5, 56.5}, fillColor = {255, 255, 255}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, extent = {{-12.5, -12.5}, {12.5, 12.5}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Icons; diff --git a/BusinessSimulation/Icons/package.order b/BusinessSimulation/Icons/package.order new file mode 100644 index 0000000..4572271 --- /dev/null +++ b/BusinessSimulation/Icons/package.order @@ -0,0 +1,65 @@ +ComponentName +ConverterName +ConstantConverterName +Package +BasesPackage +ConnectorsPackage +ConstantsPackage +ExamplesPackage +FunctionsPackage +IconsPackage +InformationSources +InterfacesPackage +VariantsPackage +UnitsPackage +TypesPackage +UtilitiesPackage +SimulationModel +Example +Enumeration +Function +Info +Theta +BidirectionalFlow +UnidirectionalFlow +Interaction +Outflow +Stock +MaterialStock +Conveyor +Queue +DelayN +Oven +Source +SourceOrSink +Sink +SubsystemBlock +SubsystemIncubator +SubsystemTransceiver +SubsystemActuator +CapacityLabel +DiscreteStockLabel +FlowIndicators +MaterialStockIndicator +World +Record +Smooth +DiscreteSmoothLabel +InformationProcessing +Policy +Converter +ConstantConverter +Clockface +Clockface_white +FunctionLetter +InformationSourceIndicator +InterpolationTable +DataBus +DataInPort +DataOutPort +ExpandableStockPort +ExpandableFlowPort +MultiPort +MultiInput +MultiOutput +OmniBus diff --git a/BusinessSimulation/InformationSources/ConstantInput.mo b/BusinessSimulation/InformationSources/ConstantInput.mo new file mode 100644 index 0000000..185ffd4 --- /dev/null +++ b/BusinessSimulation/InformationSources/ConstantInput.mo @@ -0,0 +1,21 @@ +within BusinessSimulation.InformationSources; + +block ConstantInput "Input signal with constant value" + import BusinessSimulation.Units.Amount; + import BusinessSimulation.Constants.'1each'; + extends Icons.Converter; + extends Icons.InformationSourceIndicator; + extends Interfaces.Basics.OutputTypeChoice; + RealOutput y annotation(Placement(visible = true, transformation(origin = {161.841, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {80, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + parameter Amount value "Value of constant output using counting units (default = 'each')"; +equation + y = value / '1each'; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The real output y is obtained by converting the constant parameter value into a continuous time signal.

+

Notes

+

This component is included for the sake of completeness; traditionally in System Dynamics an exogenous constant signal is modeled using a converter (→ConstantConverter).

+

See also

+

ConstantInputRate, ConstantInputTime, Converters.ConstantConverterConverters.Vector.ConstantConverter

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, points = {{-50, 0}, {50, 0}}, color = {255, 255, 255}, thickness = 4, arrowSize = 0), Text(visible = true, origin = {0, 90}, textColor = {0, 0, 128}, extent = {{-100, -6}, {100, 6}}, textString = "%value", fontName = "Lato")})); +end ConstantInput; diff --git a/BusinessSimulation/InformationSources/ConstantInputRate.mo b/BusinessSimulation/InformationSources/ConstantInputRate.mo new file mode 100644 index 0000000..792672d --- /dev/null +++ b/BusinessSimulation/InformationSources/ConstantInputRate.mo @@ -0,0 +1,27 @@ +within BusinessSimulation.InformationSources; + +block ConstantInputRate "Input signal with constant rate information" + import BusinessSimulation.Units.Rate; + import BusinessSimulation.Types.TimeBases; + extends Icons.Converter; + extends Icons.InformationSourceIndicator; + extends Interfaces.Basics.OutputTypeChoice(redeclare replaceable type OutputType = Rate); + parameter Real value = 1 "Value of constant rate per time base given"; + parameter String timeBaseString = "second" "Time base of the rate entered (default = second)" annotation(choices(choice = "second", choice = "minute", choice = "hour", choice = "day", choice = "week", choice = "month", choice = "quarter", choice = "year")); + RealOutput y annotation(Placement(visible = true, transformation(origin = {161.717, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {80, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +protected + final parameter TimeBases timeBase = Functions.stringToTimeBase(timeBaseString) "Element of the enumeration TimeBases corresponding to the timeBase given as string" annotation(Dialog(tab = "Initialization", enable = false)); + Converters.RateConversion convertRate(timeBaseA = timeBase, timeBaseB = TimeBases.seconds) "Convert the rate input to a rate per seconds" annotation(Placement(visible = true, transformation(origin = {0, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + convertRate.u = value; + // connect equations + connect(convertRate.y, y) annotation(Line(visible = true, origin = {87.259, -2.118}, points = {{-79.259, 2.118}, {74.457, 2.118}}, color = {1, 37, 163})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The real output y is obtained by converting the constant rate value into a continuous signal. The output will always give rates per second [1/s], but rates can be entered using non-SI-units of time.

+

Notes

+

This component is included for the sake of completeness; traditionally in System Dynamics an exogenous constant signal is modeled using a converter (→ConstantConverterRate).

+

See also

+

ConstantInput, ConstantInputTime, Converters.ConstantConverterRateConverters.Vector.ConstantConverterRate

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, points = {{-50, 0}, {50, 0}}, color = {255, 255, 255}, thickness = 4, arrowSize = 0), Text(visible = true, origin = {0, 90}, textColor = {0, 0, 128}, extent = {{-100, -6}, {100, 6}}, textString = "%value per %timeBaseString", fontName = "Lato")})); +end ConstantInputRate; diff --git a/BusinessSimulation/InformationSources/ConstantInputTime.mo b/BusinessSimulation/InformationSources/ConstantInputTime.mo new file mode 100644 index 0000000..0ccb980 --- /dev/null +++ b/BusinessSimulation/InformationSources/ConstantInputTime.mo @@ -0,0 +1,21 @@ +within BusinessSimulation.InformationSources; + +block ConstantInputTime "Input signal with constant time information" + import BusinessSimulation.Units.Time; + import BusinessSimulation.Types.TimeBases; + extends Icons.Converter; + extends Icons.InformationSourceIndicator; + extends Interfaces.Basics.OutputTypeChoice(redeclare replaceable type OutputType = Time); + RealOutput y annotation(Placement(visible = true, transformation(origin = {161.74, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {80, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + parameter Time value "Constant value of time"; +equation + y = value; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The real output y is obtained by converting the time parameter value into a continuous time signal. The output will always be given in seconds [s], but values can be entered using non-SI-units of time.

+

Notes

+

This component is included for the sake of completeness; traditionally in System Dynamics an exogenous constant signal is modeled using a converter (→ConstantConverterTime).

+

See also

+

ConstantInput, ConstantInputRate, Converters.ConstantConverterTimeConverters.Vector.ConstantConverterTime

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, points = {{-50, 0}, {50, 0}}, color = {255, 255, 255}, thickness = 4, arrowSize = 0), Text(visible = true, origin = {0, 90}, textColor = {0, 0, 128}, extent = {{-100, -6}, {100, 6}}, textString = "%value", fontName = "Lato")})); +end ConstantInputTime; diff --git a/BusinessSimulation/InformationSources/ExogenousData.mo b/BusinessSimulation/InformationSources/ExogenousData.mo new file mode 100644 index 0000000..aa8129b --- /dev/null +++ b/BusinessSimulation/InformationSources/ExogenousData.mo @@ -0,0 +1,38 @@ +within BusinessSimulation.InformationSources; + +block ExogenousData "Reading external data from a file using Modelica's CombiTimeTable format (MCTT)" + import BusinessSimulation.Units.Time; + import Modelica.Blocks.Types.{Smoothness,Extrapolation,TimeEvents}; + extends Interfaces.Basics.BaseConverter; + extends Icons.InformationSourceIndicator; + RealOutput y if combiTimeTable.nout == 1 "Single Output" annotation(Placement(visible = true, transformation(origin = {160, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {80, 0}, extent = {{-10, -10}, {10, 10}}, rotation = -1440))); + RealMultiOutput[combiTimeTable.nout] y_nout if combiTimeTable.nout > 1 "Output vector" annotation(Placement(visible = true, transformation(origin = {150, -20}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {80, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + // RealMultiOutput y_nout[combiTimeTable.nout] if combiTimeTable.nout > 1 "Output vector" annotation(Placement(visible = true, transformation(origin = {150, -20}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {80, 0}, extent = {{-10, -10}, {10, 10}}, rotation = -1440))); + parameter Boolean tableOnFile = true "= true, if table is defined on file or in function usertab (combiTimeTable.tableOnFile)" annotation(Dialog(group = "TableDataDefinition")); + parameter Real table[:, :] = fill(0.0, 0, 2) "Table matrix (time = first column; e.g., table=[0, 0; 1, 1; 2, 4]) (combiTimeTable.table)" annotation(Dialog(group = "TableDataDefinition", enable = not tableOnFile)); + parameter String tableName = "NoName" "Table name on file or in function usertab (see docu) (combiTimeTable.tableName)" annotation(Dialog(group = "TableDataDefinition", enable = tableOnFile)); + parameter String fileNameURI = modelSettings.exogenousDataFileURI "URI for the exogenous data file" annotation(Evaluate = true, Dialog(group = "TableDataDefinition", enable = tableOnFile)); + parameter Boolean verboseRead = true "= true, if info message that file is loading is to be printed (combiTimeTable.verboseRead)" annotation(Dialog(group = "TableDataDefinition", enable = tableOnFile)); + parameter Integer columns[:] = 2:size(table, 2) "Columns of table to be interpolated (combiTimeTable.columns)" annotation(Dialog(group = "TableDataInterpretation")); + parameter Smoothness smoothness = Smoothness.LinearSegments "Smoothness of table interpolation (combiTimeTable.smoothness)" annotation(Dialog(group = "TableDataInterpretation")); + parameter Extrapolation extrapolation = Extrapolation.LastTwoPoints "Extrapolation of data outside the definition range (combiTimeTable.extrapolation)" annotation(Dialog(group = "TableDataInterpretation")); + parameter Time timeScale(min = Modelica.Constants.eps) = 1 "Time scale of first table column (combiTimeTable.timeScale)" annotation(Dialog(group = "TableDataInterpretation")); + parameter Real offset[:] = {0} "Offsets of output signals (combiTimeTable.offset)" annotation(Dialog(group = "TableDataInterpretation")); + parameter Time startTime = 0 "Output = offset for time < startTime (combiTimeTable.startTime)" annotation(Dialog(group = "TableDataInterpretation")); + parameter Time shiftTime = startTime "Shift time of first table column (combiTimeTable.shiftTime)" annotation(Dialog(group = "TableDataInterpretation")); + parameter TimeEvents timeEvents = TimeEvents.Always "Time event handling of table interpolation (combiTimeTable.timeEvents)" annotation(Dialog(group = "TableDataInterpretation")); + parameter Boolean verboseExtrapolation = false "= true, if warning messages are to be printed if time is outside the table definition range (combiTimeTable.verboseExtrapolation)" annotation(Dialog(group = "TableDataInterpretation")); + outer ModelSettings modelSettings; +protected + parameter String fileName = if tableOnFile then Modelica.Utilities.Files.loadResource(fileNameURI) else "NoName" annotation(Dialog(group = "Initialization", enable = false)); + Modelica.Blocks.Sources.CombiTimeTable combiTimeTable(tableOnFile = tableOnFile, table = table, tableName = tableName, fileName = fileName, verboseRead = verboseRead, columns = columns, smoothness = smoothness, extrapolation = extrapolation, timeScale = timeScale, offset = offset, startTime = startTime, shiftTime = shiftTime, timeEvents = timeEvents, verboseExtrapolation = verboseExtrapolation) annotation(Placement(visible = true, transformation(origin = {50, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(combiTimeTable.y[1], y) annotation(Line(visible = true, origin = {110.5, 0}, points = {{-49.5, 0}, {49.5, 0}}, color = {1, 37, 163})); + connect(combiTimeTable.y, y_nout) annotation(Line(visible = true, origin = {91.912, -10}, points = {{-30.912, 10}, {-11.912, 10}, {-11.912, -10}, {58.088, -10}}, color = {1, 37, 163})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This block generates an output signal y_nout[:] (or y in case of a single output) by constant, linear or cubic Hermite spline interpolation in a table. The time points and function values are stored in a matrix table[i,j], where the first column table[:,1] contains the time points and the other columns contain the data to be interpolated. For more information → Modelica.Blocks.Sources.CombiTimeTable.

+

See also

+

LinearTimeTable

+"), __Wolfram(itemFlippingEnabled = true), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Ellipse(visible = true, origin = {0, -29}, lineColor = {255, 255, 255}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, lineThickness = 4, extent = {{-34.897, -8.406}, {34.897, 8.406}}), Rectangle(visible = true, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, extent = {{-34.267, -28.975}, {34.267, 28.975}}), Line(visible = true, origin = {35.015, -1.665}, points = {{0, -29.101}, {0, 29.101}}, color = {255, 255, 255}, thickness = 4, arrowSize = 0), Line(visible = true, origin = {-35.03, -0.899}, points = {{0, -29.101}, {0, 29.101}}, color = {255, 255, 255}, thickness = 4, arrowSize = 0), Ellipse(visible = true, origin = {0, 28.406}, lineColor = {255, 255, 255}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, lineThickness = 4, extent = {{-34.897, -8.406}, {34.897, 8.406}}), Line(visible = true, origin = {-2.144, -12.375}, rotation = 5.164, points = {{-28.995, -11.343}, {-19.983, -5.85}, {-14.635, -5.914}, {-9.262, 7.899}, {-1.929, -1.174}, {5.533, 18.233}, {9.982, 4.086}, {18.558, 3.311}, {21.756, -5.914}, {31.554, 9.574}}, color = {255, 255, 255}, thickness = 2.5, arrowSize = 0, smooth = Smooth.Bezier), Ellipse(visible = true, origin = {28.294, 0.181}, lineColor = {255, 0, 0}, fillColor = {255, 0, 0}, fillPattern = FillPattern.Solid, extent = {{-2.706, -2.706}, {2.706, 2.706}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end ExogenousData; diff --git a/BusinessSimulation/InformationSources/LinearTimeTable.mo b/BusinessSimulation/InformationSources/LinearTimeTable.mo new file mode 100644 index 0000000..7acba45 --- /dev/null +++ b/BusinessSimulation/InformationSources/LinearTimeTable.mo @@ -0,0 +1,20 @@ +within BusinessSimulation.InformationSources; + +block LinearTimeTable "Generate a (possibly discontinuous) signal by linear interpolation in a table of (time,value) pairs" + import BusinessSimulation.Units.Time; + extends Interfaces.PartialConverters.InformationSource_SO; + extends Icons.InterpolationTable; + parameter Real offset = 0 "Offset of output signal y"; + parameter Time startTime = 0 "Output y = offset for time < startTime"; + parameter Real[:, 2] data = [0, 0] "n x 2 matrix of time series data (t,u(t))"; + parameter Time timeScale = 1 "Time scale of first table column (e.g. if first column is given in hours, then timeScale should be 3600)"; + parameter Time shiftTime = startTime "Shift time of first table column (timeTable.shiftTime)"; +protected + Modelica.Blocks.Sources.TimeTable timeTable(offset = offset, startTime = startTime, table = data, timeScale = timeScale, shiftTime = shiftTime) annotation(Placement(visible = true, transformation(origin = {90, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(timeTable.y, y) annotation(Line(visible = true, origin = {130.5, 0}, points = {{-29.5, 0}, {29.5, 0}}, color = {0, 0, 127})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The Real output y is found by linear interpolation in a time table → Modelica.Blocks.Sources.TimeTable.

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end LinearTimeTable; diff --git a/BusinessSimulation/InformationSources/PulseInput.mo b/BusinessSimulation/InformationSources/PulseInput.mo new file mode 100644 index 0000000..25d1541 --- /dev/null +++ b/BusinessSimulation/InformationSources/PulseInput.mo @@ -0,0 +1,22 @@ +within BusinessSimulation.InformationSources; + +model PulseInput "Generate pulse or pulse-train signal of real input" + import BusinessSimulation.Units.Time; + extends Interfaces.PartialConverters.InformationSource_SO; + parameter OutputType offset = 0 "Offset of output signal y"; + parameter Time startTime = 0 "Output y = offset for time < startTime"; + parameter OutputType amplitude = 1 "Amplitude of pulse (with regard to offset)"; + parameter Real width(final min = Modelica.Constants.small, final max = 100) = 50 "Width of pulse in % of period"; + parameter Time period(final min = Modelica.Constants.small, start = 1) "Timespan for one period"; + parameter Integer nperiod = -1 "Number of periods (< 0 means infinite number of periods)"; +protected + Modelica.Blocks.Sources.Pulse pulse(offset = offset, startTime = startTime, amplitude = amplitude, width = width, period = period, nperiod = nperiod) annotation(Placement(visible = true, transformation(origin = {0.863, 0}, extent = {{-55.863, -55.863}, {55.863, 55.863}}, rotation = 0))); +equation + connect(pulse.y, y) annotation(Line(visible = true, origin = {111.156, 0}, points = {{-48.844, 0}, {48.844, 0}}, color = {0, 0, 127})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The Real output y is a pulse signal → Modelica.Blocks.Sources.Pulse.

+

See also

+

ConstantInput, StepInput, RampInput, SineInput

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {-17.67, 4.296}, points = {{-30, -24.296}, {0, -24.296}, {0, 24.296}, {30, 24.296}}, color = {255, 255, 255}, thickness = 4, arrowSize = 0), Line(visible = true, origin = {16.467, 4.296}, points = {{30, -24.296}, {0, -24.296}, {0, 24.296}, {-30, 24.296}}, color = {255, 255, 255}, thickness = 4, arrowSize = 0)}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end PulseInput; diff --git a/BusinessSimulation/InformationSources/RampInput.mo b/BusinessSimulation/InformationSources/RampInput.mo new file mode 100644 index 0000000..acbb96e --- /dev/null +++ b/BusinessSimulation/InformationSources/RampInput.mo @@ -0,0 +1,22 @@ +within BusinessSimulation.InformationSources; + +block RampInput "Generate ramp signal of real input" + import BusinessSimulation.Units.Time; + extends Interfaces.PartialConverters.InformationSource_SO; + parameter OutputType offset = 0 "Offset of output signal y"; + parameter Time startTime = 0 "Output y = offset for time < startTime"; + parameter OutputType height = 1 "Height of ramp"; + parameter Time duration = 1 "Duration of ramp (0 gives step)"; +protected + Modelica.Blocks.Sources.Ramp ramp(final offset = offset, final startTime = startTime, final height = height, final duration = duration) annotation(Placement(visible = true, transformation(origin = {1.356, 0}, extent = {{-48.644, -48.644}, {48.644, 48.644}}, rotation = 0))); +equation + connect(ramp.y, y) annotation(Line(visible = true, origin = {107.432, -0}, points = {{-52.568, -0}, {52.568, 0}}, color = {0, 0, 127})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The Real output y is a ramp signal → Modelica.Blocks.Sources.Ramp.

+

Notes

+

If parameter duration is set to zero, the output will be a step signal.

+

See also

+

ConstantInput, StepInput, PulseInputSineInput

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {-1.364, 0}, points = {{-38.636, -24.296}, {-8.636, -24.296}, {9.463, 24.296}, {37.808, 24.296}}, color = {255, 255, 255}, thickness = 4, arrowSize = 0)}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end RampInput; diff --git a/BusinessSimulation/InformationSources/SineInput.mo b/BusinessSimulation/InformationSources/SineInput.mo new file mode 100644 index 0000000..02f85f3 --- /dev/null +++ b/BusinessSimulation/InformationSources/SineInput.mo @@ -0,0 +1,25 @@ +within BusinessSimulation.InformationSources; + +block SineInput "Generate sine wave as input signal" + import BusinessSimulation.Units.Time; + import Modelica.SIunits.{Frequency,Angle}; + extends Interfaces.PartialConverters.InformationSource_SO; + parameter OutputType offset = 0 "Offset of output signal y"; + parameter Time startTime = 0 "Output y = offset for time < startTime"; + parameter OutputType amplitude = 1 "Amplitude of sine wave (with regard to offset)"; + parameter Time period(min = 0.001) = 1 "Period of sine wave (= 1/freqHz)"; + parameter Angle phase = 0 "Phase of sine wave"; +protected + final Modelica.Blocks.Sources.Sine sine(offset = offset, startTime = startTime, amplitude = amplitude, freqHz = 1 / period, phase = phase) annotation(Placement(visible = true, transformation(origin = {1.413, -0}, extent = {{-46.413, -46.413}, {46.413, 46.413}}, rotation = 0))); +equation + assert(period > 0., "Period must be greater than zero"); + connect(sine.y, y) annotation(Line(visible = true, origin = {106.234, 0}, points = {{-53.766, 0}, {53.766, 0}}, color = {0, 0, 127})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The Real output y is a sine signal → Modelica.Blocks.Sources.Sine.

+

Notes

+

A cosine input signal can be simply achieved by using a SineInput with a phase of 90°.

+

See also

+

ConstantInput, StepInput, RampInput, PulseInput

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {-3.666, -2.761}, points = {{-38.911, 1.472}, {-28.911, 27.793}, {-14.004, 36.075}, {-2.224, 22.761}, {4.77, -23.743}, {20.599, -31.106}, {33.666, -17.239}, {38.269, 3.313}}, color = {255, 255, 255}, thickness = 4, arrowSize = 0, smooth = Smooth.Bezier)}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end SineInput; diff --git a/BusinessSimulation/InformationSources/StepInput.mo b/BusinessSimulation/InformationSources/StepInput.mo new file mode 100644 index 0000000..fb496d9 --- /dev/null +++ b/BusinessSimulation/InformationSources/StepInput.mo @@ -0,0 +1,19 @@ +within BusinessSimulation.InformationSources; + +model StepInput "Generate a step signal of real input" + import BusinessSimulation.Units.Time; + extends Interfaces.PartialConverters.InformationSource_SO; + parameter OutputType offset = 0 "Offset of output signal y"; + parameter Time startTime = 0 "Output y = offset for time < startTime"; + parameter OutputType height = 1 "Height of step"; +protected + Modelica.Blocks.Sources.Step step(final offset = offset, final startTime = startTime, final height = height) annotation(Placement(visible = true, transformation(origin = {1.316, -0}, extent = {{-58.684, -58.684}, {58.684, 58.684}}, rotation = 0))); +equation + connect(step.y, y) annotation(Line(visible = true, origin = {112.934, 0}, points = {{-47.066, 0}, {47.066, 0}}, color = {0, 0, 127})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The Real output y is a step signal. For more information → Modelica.Blocks.Sources.Step.

+

See also

+

ConstantInput, RampInput, PulseInputSineInput

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {0, 1.104}, points = {{-30, -24.296}, {0, -24.296}, {0, 24.296}, {30, 24.296}}, color = {255, 255, 255}, thickness = 4, arrowSize = 0)}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end StepInput; diff --git a/BusinessSimulation/InformationSources/TimeInput.mo b/BusinessSimulation/InformationSources/TimeInput.mo new file mode 100644 index 0000000..d5a7aa1 --- /dev/null +++ b/BusinessSimulation/InformationSources/TimeInput.mo @@ -0,0 +1,22 @@ +within BusinessSimulation.InformationSources; + +block TimeInput "Clock to provide time-signal" + import BusinessSimulation.Units.Time; + extends Interfaces.PartialConverters.InformationSource_SO(redeclare final type OutputType = Time); + extends Icons.Clockface_white; + parameter Time offset = modelSettings.modelStartTime "Offset of output signal y (default = modelStartTime)"; + parameter OutputType startTime = modelSettings.modelStartTime "Output y = offset for time <= startTime (default = modelStartTime)"; + outer ModelSettings modelSettings; +protected + final Modelica.Blocks.Sources.Clock clock(offset = offset, startTime = startTime) annotation(Placement(visible = true, transformation(origin = {10, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(clock.y, y) annotation(Line(visible = true, origin = {90.5, 0}, points = {{-69.5, 0}, {69.5, 0}}, color = {1, 37, 163})); + annotation(__Wolfram(itemFlippingEnabled = true), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output y is a time signal (e.g. a clock) → Modelica.Blocks.Sources.Clock.

+

Notes

+

Time will always be given in the SIunit s so that models are compatible with those from other domains. To provide a time signal in non SIunits (e.g. min, h, d, wk etc.) TimeInputConverted should be used.

+

See also

+

TimeInputConverted

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {0, 13}, rotation = -300, points = {{12.863, 7.426}, {-12.863, -7.426}}, color = {255, 255, 255}, thickness = 2.5, arrowSize = 0), Line(visible = true, origin = {7, -6}, rotation = -300, points = {{0, 9.158}, {0, -9.158}}, color = {255, 255, 255}, thickness = 2.5, arrowSize = 0)}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end TimeInput; diff --git a/BusinessSimulation/InformationSources/TimeInputConverted.mo b/BusinessSimulation/InformationSources/TimeInputConverted.mo new file mode 100644 index 0000000..6cb479c --- /dev/null +++ b/BusinessSimulation/InformationSources/TimeInputConverted.mo @@ -0,0 +1,28 @@ +within BusinessSimulation.InformationSources; + +block TimeInputConverted "Clock to provide time-signal in a different time base" + extends Icons.InformationSourceIndicator; + extends Icons.Clockface_white; + import BusinessSimulation.Units.Time; + import BusinessSimulation.Types.TimeBases; + Interfaces.Connectors.RealOutput y(final unit = clockTimeBaseUnit, final quantity = "Time") annotation(Placement(visible = true, transformation(origin = {160, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {80, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + parameter Time offset = modelSettings.modelStartTime "Offset of output signal y given in seconds (default = modelStartTime)"; + parameter Time startTime = modelSettings.modelStartTime "Output y = offset for time <= startTime (default = modelStartTime)"; + parameter TimeBases clockTimeBase = TimeBases.seconds "TimeBase for the output signal" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + outer ModelSettings modelSettings; +protected + parameter String clockTimeBaseUnit = BusinessSimulation.Constants.timeBaseUnits[clockTimeBase] annotation(Evaluate = true, Dialog(enable = false, tab = "Initialization")); + Modelica.Blocks.Sources.Clock clock(offset = offset, startTime = startTime) annotation(Placement(visible = true, transformation(origin = {10, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.TimeConversion timeConversion(timeBaseA = TimeBases.seconds, timeBaseB = clockTimeBase) annotation(Placement(visible = true, transformation(origin = {70, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(timeConversion.u, clock.y) annotation(Line(visible = true, origin = {41.813, 0}, points = {{20.813, 0}, {-20.813, -0}}, color = {0, 0, 127})); + connect(timeConversion.y, y) annotation(Line(visible = true, origin = {118.681, 0}, points = {{-40.681, 0}, {0.319, 0}, {0.319, -0}, {41.319, -0}}, color = {0, 0, 127})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output y is a time signal (e.g. a clock) → Modelica.Blocks.Sources.Clock. The units for the output will here be a non-SIunit (e.g. min, h, d, wk etc.).

+

Notes

+

To make models compatible internally time will always be in the SIunit s while displayUnit is used to enter and present values in a different unit of time.

+

See also

+

TimeInputTimeBases

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {0, 13}, rotation = -300, points = {{12.863, 7.426}, {-12.863, -7.426}}, color = {255, 255, 255}, thickness = 2.5, arrowSize = 0), Line(visible = true, origin = {7, -6}, rotation = -300, points = {{0, 9.158}, {0, -9.158}}, color = {255, 255, 255}, thickness = 2.5, arrowSize = 0), Line(visible = true, origin = {0, -8.842}, points = {{0, 9.158}, {0, -9.158}}, color = {255, 0, 0}, thickness = 2.5, arrowSize = 0), Line(visible = true, origin = {-13.853, -0}, rotation = -570, points = {{12.863, 7.426}, {-12.863, -7.426}}, color = {255, 0, 0}, thickness = 2.5, arrowSize = 0)}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end TimeInputConverted; diff --git a/BusinessSimulation/InformationSources/package.mo b/BusinessSimulation/InformationSources/package.mo new file mode 100644 index 0000000..08ea7bf --- /dev/null +++ b/BusinessSimulation/InformationSources/package.mo @@ -0,0 +1,11 @@ +within BusinessSimulation; + +package InformationSources "External information input" + extends Icons.InformationSources; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This package contains sources that provide continuous information (signals). Next to a ConstantInput there are typical test inputs (StepInput, RampInput, PulseInput, SineInput), inputs of time (TimeInput, ConvertedTimeInput), and interpolation tables (LinearTimeTable, ExogenousData).

+

+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+"), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end InformationSources; diff --git a/BusinessSimulation/InformationSources/package.order b/BusinessSimulation/InformationSources/package.order new file mode 100644 index 0000000..7c454f4 --- /dev/null +++ b/BusinessSimulation/InformationSources/package.order @@ -0,0 +1,11 @@ +ConstantInput +ConstantInputRate +ConstantInputTime +ExogenousData +LinearTimeTable +PulseInput +RampInput +SineInput +StepInput +TimeInput +TimeInputConverted diff --git a/BusinessSimulation/Interfaces/Basics/BaseConverter.mo b/BusinessSimulation/Interfaces/Basics/BaseConverter.mo new file mode 100644 index 0000000..7e507c0 --- /dev/null +++ b/BusinessSimulation/Interfaces/Basics/BaseConverter.mo @@ -0,0 +1,10 @@ +within BusinessSimulation.Interfaces.Basics; + +partial block BaseConverter "Basic converter class" + extends Icons.Converter; + extends OutputTypeChoice; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial block extending from Icons.Converter and →OutputTypeChoice. This is the base class for Converter components.

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end BaseConverter; diff --git a/BusinessSimulation/Interfaces/Basics/BaseInformationProcessing.mo b/BusinessSimulation/Interfaces/Basics/BaseInformationProcessing.mo new file mode 100644 index 0000000..7a5b02c --- /dev/null +++ b/BusinessSimulation/Interfaces/Basics/BaseInformationProcessing.mo @@ -0,0 +1,12 @@ +within BusinessSimulation.Interfaces.Basics; + +partial block BaseInformationProcessing "Basic information processing class" + extends Icons.InformationProcessing; + extends OutputTypeChoice; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial block extending from Icons.InformationProcessing and →OutputTypeChoice. This is the base class for InformationProcessing-related components.

+

See also

+

MoleculesOfStructure.InformationProcessing

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end BaseInformationProcessing; diff --git a/BusinessSimulation/Interfaces/Basics/BaseInformationProcessing_MO.mo b/BusinessSimulation/Interfaces/Basics/BaseInformationProcessing_MO.mo new file mode 100644 index 0000000..5a71aff --- /dev/null +++ b/BusinessSimulation/Interfaces/Basics/BaseInformationProcessing_MO.mo @@ -0,0 +1,13 @@ +within BusinessSimulation.Interfaces.Basics; + +partial block BaseInformationProcessing_MO "Basic information processing class with multiple outputs" + extends Icons.InformationProcessing; + extends OutputTypeChoice; + parameter Integer nout(min = 1) = 2 "Number of outputs" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial block extending from Icons.InformationProcessing and →OutputTypeChoice. This is the base class for InformationProcessing-related components with multiple outputs.

+

See also

+

MoleculesOfStructure.InformationProcessing

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end BaseInformationProcessing_MO; diff --git a/BusinessSimulation/Interfaces/Basics/BasePolicy.mo b/BusinessSimulation/Interfaces/Basics/BasePolicy.mo new file mode 100644 index 0000000..39dbdaa --- /dev/null +++ b/BusinessSimulation/Interfaces/Basics/BasePolicy.mo @@ -0,0 +1,11 @@ +within BusinessSimulation.Interfaces.Basics; + +partial block BasePolicy "Basic policy class" + extends Icons.Policy; + extends OutputTypeChoice; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial block extending from Icons.Policy and →OutputTypeChoice. This is the base class for Policy-related components.

+

See also

+

MoleculesOfStructure.Policy

"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end BasePolicy; diff --git a/BusinessSimulation/Interfaces/Basics/BasePolicy_MO.mo b/BusinessSimulation/Interfaces/Basics/BasePolicy_MO.mo new file mode 100644 index 0000000..5580f8f --- /dev/null +++ b/BusinessSimulation/Interfaces/Basics/BasePolicy_MO.mo @@ -0,0 +1,13 @@ +within BusinessSimulation.Interfaces.Basics; + +partial block BasePolicy_MO "Basic policy class with multiple outputs" + extends Icons.Policy; + extends OutputTypeChoice; + parameter Integer nout(min = 1) = 2 "Number of outputs" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial block extending from Icons.Policy and →OutputTypeChoice_MO. This is the base class for Policy-related components with multiple outputs.

+

See also

+

MoleculesOfStructure.Policy

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end BasePolicy_MO; diff --git a/BusinessSimulation/Interfaces/Basics/GenericFlow.mo b/BusinessSimulation/Interfaces/Basics/GenericFlow.mo new file mode 100644 index 0000000..8c6ba77 --- /dev/null +++ b/BusinessSimulation/Interfaces/Basics/GenericFlow.mo @@ -0,0 +1,9 @@ +within BusinessSimulation.Interfaces.Basics; + +partial model GenericFlow "Flow Template with two FlowPorts" + Connectors.FlowPort portA "Flow from/to Stock A" annotation(Placement(visible = true, transformation(origin = {-148.334, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-100, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Connectors.FlowPort portB "Flow to/from Stock B" annotation(Placement(visible = true, transformation(origin = {148.464, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {100, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial model class with two →FlowPort connectors.

"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end GenericFlow; diff --git a/BusinessSimulation/Interfaces/Basics/GenericFlow_Special.mo b/BusinessSimulation/Interfaces/Basics/GenericFlow_Special.mo new file mode 100644 index 0000000..1bb0cbf --- /dev/null +++ b/BusinessSimulation/Interfaces/Basics/GenericFlow_Special.mo @@ -0,0 +1,9 @@ +within BusinessSimulation.Interfaces.Basics; + +partial model GenericFlow_Special "Flow Template with a FlowPort_Special (portA)" + Connectors.FlowPort_Special portA "Flow from/to Stock A (stock signals the rate)" annotation(Placement(visible = true, transformation(origin = {-148.205, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-100, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Connectors.FlowPort portB "Flow to/from Stock B" annotation(Placement(visible = true, transformation(origin = {148.205, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {100, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial model class with a →FlowPort_Special (portA) and a regular →FlowPort (portB).

"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end GenericFlow_Special; diff --git a/BusinessSimulation/Interfaces/Basics/GenericSensor.mo b/BusinessSimulation/Interfaces/Basics/GenericSensor.mo new file mode 100644 index 0000000..c12d423 --- /dev/null +++ b/BusinessSimulation/Interfaces/Basics/GenericSensor.mo @@ -0,0 +1,15 @@ +within BusinessSimulation.Interfaces.Basics; + +partial model GenericSensor "Generic sensor with connection to the ports of a stock" + Connectors.RealOutput inFlow(quantity = "Rate") "Current rate of inflow" annotation(Placement(visible = true, transformation(origin = {160, 80}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-100, 40}, extent = {{-10, -10}, {10, 10}}, rotation = -270))); + Connectors.RealOutput outFlow(quantity = "Rate") "Current rate of outflow" annotation(Placement(visible = true, transformation(origin = {160, -80}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {100, 40}, extent = {{-10, -10}, {10, 10}}, rotation = -270))); + Connectors.RealOutput stock "Current level of stock" annotation(Placement(visible = true, transformation(origin = {160, 38.364}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-49.512, 40}, extent = {{-10, -10}, {10, 10}}, rotation = -270))); + Connectors.RealOutput netFlow(quantity = "Rate") "Current netflow" annotation(Placement(visible = true, transformation(origin = {160, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {50.237, 40}, extent = {{-10, -10}, {10, 10}}, rotation = -270))); + Connectors.RealOutput meanResidenceTime(quantity = "Time") "Mean Residence Time" annotation(Placement(visible = true, transformation(origin = {160, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {0.237, 40}, extent = {{-10, -10}, {10, 10}}, rotation = -270))); + Connectors.StockInfoInput u_stockInfo annotation(Placement(visible = true, transformation(origin = {-145, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {0, -40}, extent = {{-10, -10}, {10, 10}}, rotation = -270))); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial model with a →StockInfoInput connector and five Real output connectors. The class is extended by sensor components that \"measure\" stock-related information.

+

See also

+

AbsoluteSensor

"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {-19.625, -53.619}, points = {{-74, 53.619}, {100, 53.619}, {126, 53.619}}, color = {0, 0, 128}, thickness = 5), Ellipse(visible = true, origin = {-100, 0}, rotation = 30, lineColor = {0, 0, 128}, fillColor = {76, 112, 136}, fillPattern = FillPattern.Solid, lineThickness = 3, extent = {{-20.708, -20.708}, {20.708, 20.708}}), Line(visible = true, origin = {-114.33, 7.5}, rotation = -300, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-108.5, 13.33}, rotation = 30, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-99.781, 16.375}, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-102.624, 3.453}, rotation = -300, points = {{2.435, 4.688}, {-2.435, -4.688}}, color = {255, 0, 0}, thickness = 1), Line(visible = true, origin = {-86.143, 8.141}, rotation = 660, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-92.078, 14.346}, rotation = -30, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-116, 0}, rotation = -270, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-84, 0}, rotation = -270, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Text(visible = true, origin = {-100, -10}, textColor = {255, 255, 255}, extent = {{-12.617, -6}, {12.617, 6}}, textString = "IN", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Ellipse(visible = true, origin = {-99.903, 0}, lineColor = {255, 0, 0}, fillColor = {255, 0, 0}, fillPattern = FillPattern.Solid, extent = {{-3, -3}, {3, 3}}), Ellipse(visible = true, origin = {100, 0}, rotation = 30, lineColor = {0, 0, 128}, fillColor = {76, 112, 136}, fillPattern = FillPattern.Solid, lineThickness = 3, extent = {{-20.708, -20.708}, {20.708, 20.708}}), Line(visible = true, origin = {85.67, 7.5}, rotation = -300, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {91.5, 13.33}, rotation = 30, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {100.219, 16.375}, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {97.376, 3.453}, rotation = -300, points = {{2.435, 4.688}, {-2.435, -4.688}}, color = {255, 0, 0}, thickness = 1), Line(visible = true, origin = {113.857, 8.141}, rotation = 660, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {107.922, 14.346}, rotation = -30, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {84, 0}, rotation = -270, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {116, 0}, rotation = -270, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Text(visible = true, origin = {100, -10}, textColor = {255, 255, 255}, extent = {{-12.617, -6}, {12.617, 6}}, textString = "OUT", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Ellipse(visible = true, origin = {100.097, 0}, lineColor = {255, 0, 0}, fillColor = {255, 0, 0}, fillPattern = FillPattern.Solid, extent = {{-3, -3}, {3, 3}}), Ellipse(visible = true, origin = {-50, 0}, rotation = 30, lineColor = {0, 0, 128}, fillColor = {76, 112, 136}, fillPattern = FillPattern.Solid, lineThickness = 3, extent = {{-20.708, -20.708}, {20.708, 20.708}}), Line(visible = true, origin = {-64.33, 7.5}, rotation = -300, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-58.5, 13.33}, rotation = 30, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-49.781, 16.375}, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-52.624, 3.453}, rotation = -300, points = {{2.435, 4.688}, {-2.435, -4.688}}, color = {255, 0, 0}, thickness = 1), Line(visible = true, origin = {-36.143, 8.141}, rotation = 660, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-42.078, 14.346}, rotation = -30, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-66, 0}, rotation = -270, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-34, 0}, rotation = -270, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Text(visible = true, origin = {-50, -10}, textColor = {255, 255, 255}, extent = {{-12.617, -6}, {12.617, 6}}, textString = "S", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Ellipse(visible = true, origin = {-49.903, 0}, lineColor = {255, 0, 0}, fillColor = {255, 0, 0}, fillPattern = FillPattern.Solid, extent = {{-3, -3}, {3, 3}}), Ellipse(visible = true, origin = {50, 0}, rotation = 30, lineColor = {0, 0, 128}, fillColor = {76, 112, 136}, fillPattern = FillPattern.Solid, lineThickness = 3, extent = {{-20.708, -20.708}, {20.708, 20.708}}), Line(visible = true, origin = {35.67, 7.5}, rotation = -300, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {41.5, 13.33}, rotation = 30, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {50.219, 16.375}, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {47.376, 3.453}, rotation = -300, points = {{2.435, 4.688}, {-2.435, -4.688}}, color = {255, 0, 0}, thickness = 1), Line(visible = true, origin = {63.857, 8.141}, rotation = 660, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {57.922, 14.346}, rotation = -30, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {34, 0}, rotation = -270, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {66, 0}, rotation = -270, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Text(visible = true, origin = {50, -10}, textColor = {255, 255, 255}, extent = {{-12.617, -6}, {12.617, 6}}, textString = "F", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Ellipse(visible = true, origin = {50.097, 0}, lineColor = {255, 0, 0}, fillColor = {255, 0, 0}, fillPattern = FillPattern.Solid, extent = {{-3, -3}, {3, 3}}), Ellipse(visible = true, rotation = 30, lineColor = {0, 0, 128}, fillColor = {76, 112, 136}, fillPattern = FillPattern.Solid, lineThickness = 3, extent = {{-20.708, -20.708}, {20.708, 20.708}}), Line(visible = true, origin = {-14.33, 7.5}, rotation = -300, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-8.5, 13.33}, rotation = 30, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {0.219, 16.375}, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-2.624, 3.453}, rotation = -300, points = {{2.435, 4.688}, {-2.435, -4.688}}, color = {255, 0, 0}, thickness = 1), Line(visible = true, origin = {13.857, 8.141}, rotation = 660, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {7.922, 14.346}, rotation = -30, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-16, 0}, rotation = -270, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {16, 0}, rotation = -270, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Text(visible = true, origin = {0, -10}, textColor = {255, 255, 255}, extent = {{-12.617, -6}, {12.617, 6}}, textString = "MRT", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Ellipse(visible = true, origin = {0.097, 0}, lineColor = {255, 0, 0}, fillColor = {255, 0, 0}, fillPattern = FillPattern.Solid, extent = {{-3, -3}, {3, 3}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end GenericSensor; diff --git a/BusinessSimulation/Interfaces/Basics/GenericSmooth.mo b/BusinessSimulation/Interfaces/Basics/GenericSmooth.mo new file mode 100644 index 0000000..d2f77f6 --- /dev/null +++ b/BusinessSimulation/Interfaces/Basics/GenericSmooth.mo @@ -0,0 +1,10 @@ +within BusinessSimulation.Interfaces.Basics; + +partial block GenericSmooth "Partial smooth-like converter class" + extends Icons.Smooth; + extends OutputTypeChoice; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial block extending from Icons.Smooth and →OutputTypeChoice. This is the base class for Smooth-like Converters.

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end GenericSmooth; diff --git a/BusinessSimulation/Interfaces/Basics/GenericSourceOrSink.mo b/BusinessSimulation/Interfaces/Basics/GenericSourceOrSink.mo new file mode 100644 index 0000000..7eba31c --- /dev/null +++ b/BusinessSimulation/Interfaces/Basics/GenericSourceOrSink.mo @@ -0,0 +1,10 @@ +within BusinessSimulation.Interfaces.Basics; + +partial model GenericSourceOrSink "SinkOrSource template with one flow port" + extends ThreeSO_rate; + Connectors.FlowPort massPort "Inflow to or outflow from connected stock" annotation(Placement(visible = true, transformation(origin = {148.334, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {100, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial model with three Real output connectors and a single →FlowPort connector. This is the base class for SourcesOrSinks components.

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end GenericSourceOrSink; diff --git a/BusinessSimulation/Interfaces/Basics/GenericStock.mo b/BusinessSimulation/Interfaces/Basics/GenericStock.mo new file mode 100644 index 0000000..3273b85 --- /dev/null +++ b/BusinessSimulation/Interfaces/Basics/GenericStock.mo @@ -0,0 +1,19 @@ +within BusinessSimulation.Interfaces.Basics; + +partial model GenericStock "Generic Stock to collect material or information" + import BusinessSimulation.Interfaces.Connectors.StockPort; + import BusinessSimulation.Interfaces.Basics.ThreeSO; + import BusinessSimulation.Types.InitializationOptions; + import BusinessSimulation.Interfaces.Connectors.StockInfoOutput; + import BusinessSimulation.Icons.FlowIndicators; + extends ThreeSO; + extends FlowIndicators; + StockPort inflow "Inflow port of the stock" annotation(Placement(visible = true, transformation(origin = {-148.205, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-100, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + StockPort outflow "Outflow port of the stock" annotation(Placement(visible = true, transformation(origin = {148.464, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {100, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + parameter InitializationOptions init = InitializationOptions.FixedValue "Provide InitializationOptions (Free, FixedValue, SteadyState)" annotation(Evaluate = true, Dialog(tab = "Advanced")); + parameter Boolean hasStockInfoOutput = false "= true, if a StockInfoOutput should be added to the stock" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + StockInfoOutput y_stockInfo if hasStockInfoOutput "Optional StockInfoOutput" annotation(Placement(visible = true, transformation(origin = {150, -80}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {80, 104}, extent = {{-10, -10}, {10, 10}}, rotation = -270))); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial model with three Real output connectors, two →StockPorts, and an optional →StockInfoOutput. This is the base class for stock components.

"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end GenericStock; diff --git a/BusinessSimulation/Interfaces/Basics/GenericStockInfo.mo b/BusinessSimulation/Interfaces/Basics/GenericStockInfo.mo new file mode 100644 index 0000000..0bd223b --- /dev/null +++ b/BusinessSimulation/Interfaces/Basics/GenericStockInfo.mo @@ -0,0 +1,13 @@ +within BusinessSimulation.Interfaces.Basics; + +partial model GenericStockInfo + Connectors.StockPort inPort "Connect to inflow of stock" annotation(Placement(visible = true, transformation(origin = {-148.318, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-60, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Connectors.StockPort outPort "Connect to outflow of stock" annotation(Placement(visible = true, transformation(origin = {147.895, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {60, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Connectors.StockInfoOutput y_stockInfo "StockInformation output" annotation(Placement(visible = true, transformation(origin = {150, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {0, 60}, extent = {{-10, -10}, {10, 10}}, rotation = -270))); + Connectors.RealInput levelInfo "Connect to level output of stock" annotation(Placement(visible = true, transformation(origin = {-145, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {0, -60}, extent = {{10, -10}, {-10, 10}}, rotation = -90))); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial model with two →StockPorts, a Real information input (levelInfo), and a →StockInfoOutput connector. This is the base class for a →StockInfo sensor.

+

See also

+

GenericStockInfo_Special

"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Ellipse(visible = true, rotation = 30, lineColor = {0, 0, 128}, fillColor = {76, 112, 136}, fillPattern = FillPattern.Solid, lineThickness = 3, extent = {{-20.708, -20.708}, {20.708, 20.708}}), Line(visible = true, origin = {-14.33, 7.5}, rotation = -300, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-8.5, 13.33}, rotation = 30, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {0.219, 16.375}, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-2.624, 3.453}, rotation = -300, points = {{2.435, 4.688}, {-2.435, -4.688}}, color = {255, 0, 0}, thickness = 1), Line(visible = true, origin = {13.857, 8.141}, rotation = 660, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {7.922, 14.346}, rotation = -30, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-16, 0}, rotation = -270, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {16, 0}, rotation = -270, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Ellipse(visible = true, origin = {0.097, 0}, lineColor = {255, 0, 0}, fillColor = {255, 0, 0}, fillPattern = FillPattern.Solid, extent = {{-3, -3}, {3, 3}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end GenericStockInfo; diff --git a/BusinessSimulation/Interfaces/Basics/GenericStockInfo_Special.mo b/BusinessSimulation/Interfaces/Basics/GenericStockInfo_Special.mo new file mode 100644 index 0000000..ea31c88 --- /dev/null +++ b/BusinessSimulation/Interfaces/Basics/GenericStockInfo_Special.mo @@ -0,0 +1,13 @@ +within BusinessSimulation.Interfaces.Basics; + +partial model GenericStockInfo_Special + Connectors.StockPort inPort "Connect to inflow port of stock" annotation(Placement(visible = true, transformation(origin = {-148.318, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-60, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Connectors.StockPort_Special outPort "Connect to special outflow port of stock" annotation(Placement(visible = true, transformation(origin = {148.413, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {60, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Connectors.StockInfoOutput y_stockInfo "StockInformation output" annotation(Placement(visible = true, transformation(origin = {150, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {0, 60}, extent = {{-10, -10}, {10, 10}}, rotation = -270))); + Connectors.RealInput levelInfo "Connect to level output of stock" annotation(Placement(visible = true, transformation(origin = {-145, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {0, -60}, extent = {{10, -10}, {-10, 10}}, rotation = -90))); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial model with a →StockPort connector on the inflow side, a →StockPort_Special connector on the outflow side, a Real information input (levelInfo), and a →StockInfoOutput connector. This is the base class for a →DynamicStockInfo sensor.

+

See also

+

GenericStockInfo

"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Ellipse(visible = true, rotation = 30, lineColor = {0, 0, 128}, fillColor = {76, 112, 136}, fillPattern = FillPattern.Solid, lineThickness = 3, extent = {{-20.708, -20.708}, {20.708, 20.708}}), Line(visible = true, origin = {-14.33, 7.5}, rotation = -300, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-8.5, 13.33}, rotation = 30, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {0.219, 16.375}, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-2.624, 3.453}, rotation = -300, points = {{2.435, 4.688}, {-2.435, -4.688}}, color = {255, 0, 0}, thickness = 1), Line(visible = true, origin = {13.857, 8.141}, rotation = 660, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {7.922, 14.346}, rotation = -30, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-16, 0}, rotation = -270, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {16, 0}, rotation = -270, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Ellipse(visible = true, origin = {0.097, 0}, lineColor = {255, 0, 0}, fillColor = {255, 0, 0}, fillPattern = FillPattern.Solid, extent = {{-3, -3}, {3, 3}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end GenericStockInfo_Special; diff --git a/BusinessSimulation/Interfaces/Basics/GenericStock_Special.mo b/BusinessSimulation/Interfaces/Basics/GenericStock_Special.mo new file mode 100644 index 0000000..af3ec88 --- /dev/null +++ b/BusinessSimulation/Interfaces/Basics/GenericStock_Special.mo @@ -0,0 +1,20 @@ +within BusinessSimulation.Interfaces.Basics; + +partial model GenericStock_Special "Generic Stock with internal dynamics" + import BusinessSimulation.Interfaces.Connectors.StockPort; + import BusinessSimulation.Interfaces.Connectors.StockPort_Special; + import BusinessSimulation.Interfaces.Connectors.StockInfoOutput; + import BusinessSimulation.Types.InitializationOptions; + import BusinessSimulation.Interfaces.Basics.ThreeSO; + import BusinessSimulation.Icons.FlowIndicators; + extends ThreeSO; + extends FlowIndicators; + StockPort inflow "Inflow port of the stock" annotation(Placement(visible = true, transformation(origin = {-148.075, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-100, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + StockPort_Special outflow "Special outflow port of the stock (stock sets rate)" annotation(Placement(visible = true, transformation(origin = {148.334, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {100, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + parameter InitializationOptions init = InitializationOptions.FixedValue "Provide InitializationOptions (Free, FixedValue, SteadyState)" annotation(Evaluate = true, Dialog(tab = "Advanced")); + parameter Boolean hasStockInfoOutput = false "= true, if a StockInfoOutput should be added to the stock" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + StockInfoOutput y_stockInfo if hasStockInfoOutput "Optional StockInfoOutput" annotation(Placement(visible = true, transformation(origin = {150, -80}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {80, 104}, extent = {{-10, -10}, {10, 10}}, rotation = -270))); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial model with three Real output connectors, a →StockPort connector on the inflow side, a →StockPort_Special connector on the outflow side, and an optional →StockInfoOutput. This is the base class for dynamic stock components that will usually signal the rate of outflow to a connected flow component.

"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end GenericStock_Special; diff --git a/BusinessSimulation/Interfaces/Basics/Interaction4SO.mo b/BusinessSimulation/Interfaces/Basics/Interaction4SO.mo new file mode 100644 index 0000000..d0600cb --- /dev/null +++ b/BusinessSimulation/Interfaces/Basics/Interaction4SO.mo @@ -0,0 +1,20 @@ +within BusinessSimulation.Interfaces.Basics; + +partial class Interaction4SO "Output connectors for interaction elements reporting rates" + replaceable type OutputType_A = Units.Rate constrainedby Units.Rate "Type selection for the flow to/from A"; + replaceable type OutputType_B = Units.Rate constrainedby Units.Rate "Type selection for the flow to/from B"; + RealOutput_B y_B "Rate for flow to and from B (positive value indicates inflow)" annotation(Placement(visible = true, transformation(origin = {160, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {50, 104}, extent = {{-10, -10}, {10, 10}}, rotation = -1350))); + RealOutput_B y1_B "Rate for flow to and from B (positive value indicates inflow)" annotation(Placement(visible = true, transformation(origin = {160, -80}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {105, -50}, extent = {{-10, -10}, {10, 10}}, rotation = -360))); + RealOutput_A y1_A "Rate for flow to and from A (positive value indicates inflow)" annotation(Placement(visible = true, transformation(origin = {160, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-105, -50}, extent = {{-10, 10}, {10, -10}}, rotation = -180))); + RealOutput_A y_A "Rate for flow to and from A (positive value indicates inflow)" annotation(Placement(visible = true, transformation(origin = {160, 80}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-50, 104}, extent = {{-10, -10}, {10, 10}}, rotation = -1350))); + connector RealOutput_A = output OutputType_A "Output signal for A" annotation(defaultComponentName = "y", Icon(coordinateSystem(preserveAspectRatio = true, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, lineColor = {1, 37, 163}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-100, 100}, {100, 0}, {-100, -100}})}), Diagram(coordinateSystem(preserveAspectRatio = true, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, lineColor = {1, 37, 163}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-100, 50}, {0, 0}, {-100, -50}}), Text(visible = true, origin = {0, 80}, textColor = {128, 128, 128}, extent = {{-100, -12}, {100, 12}}, textString = "%name", fontName = "Lato", textStyle = {TextStyle.Bold})}), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

A Real output connector.

")); + connector RealOutput_B = output OutputType_B "Output signal for B" annotation(defaultComponentName = "y", Icon(coordinateSystem(preserveAspectRatio = true, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, lineColor = {1, 37, 163}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-100, 100}, {100, 0}, {-100, -100}})}), Diagram(coordinateSystem(preserveAspectRatio = true, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, lineColor = {1, 37, 163}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-100, 50}, {0, 0}, {-100, -50}}), Text(visible = true, origin = {0, 80}, textColor = {128, 128, 128}, extent = {{-100, -12}, {100, 12}}, textString = "%name", fontName = "Lato", textStyle = {TextStyle.Bold})}), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

A Real output connector.

")); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial model that has four Real output connectors (unit = \"1/s\"). It is typically used by interaction flow components to report the current rates of flow for the two flow ports (two output connectors per port).

+"), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}))); +end Interaction4SO; diff --git a/BusinessSimulation/Interfaces/Basics/OutputTypeChoice.mo b/BusinessSimulation/Interfaces/Basics/OutputTypeChoice.mo new file mode 100644 index 0000000..7f242c8 --- /dev/null +++ b/BusinessSimulation/Interfaces/Basics/OutputTypeChoice.mo @@ -0,0 +1,17 @@ +within BusinessSimulation.Interfaces.Basics; + +partial class OutputTypeChoice "Partial model to set output type" + replaceable encapsulated type OutputType = .BusinessSimulation.Types.Reals; + connector RealOutput = output OutputType "Output signal" annotation(defaultComponentName = "y", Icon(coordinateSystem(preserveAspectRatio = true, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, lineColor = {1, 37, 163}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-100, 100}, {100, 0}, {-100, -100}})}), Diagram(coordinateSystem(preserveAspectRatio = true, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, lineColor = {1, 37, 163}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-100, 50}, {0, 0}, {-100, -50}}), Text(visible = true, origin = {0, 80}, textColor = {128, 128, 128}, extent = {{-100, -12}, {100, 12}}, textString = "%name", fontName = "Lato", textStyle = {TextStyle.Bold})}), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

A Real output connector.

")); + connector RealMultiOutput = output OutputType "Output signal" annotation(defaultComponentName = "y", Icon(coordinateSystem(preserveAspectRatio = true, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, lineColor = {1, 37, 163}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-100, 100}, {100, 0}, {-100, -100}}), Ellipse(visible = true, origin = {-24.747, 0}, lineColor = {255, 255, 255}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, extent = {{-24.747, -24.747}, {24.747, 24.747}})}), Diagram(coordinateSystem(preserveAspectRatio = true, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, origin = {100, 0}, lineColor = {1, 37, 163}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-100, 50}, {0, 0}, {-100, -50}}), Text(visible = true, origin = {0, 80}, textColor = {128, 128, 128}, extent = {{-100, -12}, {100, 12}}, textString = "%name", fontName = "Lato", textStyle = {TextStyle.Bold})}), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

A Real output connector to indicate vector or list output.

")); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial class that enables the redeclaration of type OutputType which by default is set to Types.Reals. This class is only used for extensions.

+

See also

+

Types.RealsUnits

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, fillColor = {255, 255, 255}, pattern = LinePattern.None, extent = {{-100, -100}, {100, 100}})}), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end OutputTypeChoice; diff --git a/BusinessSimulation/Interfaces/Basics/OutputTypeChoice_Rate.mo b/BusinessSimulation/Interfaces/Basics/OutputTypeChoice_Rate.mo new file mode 100644 index 0000000..0cf800b --- /dev/null +++ b/BusinessSimulation/Interfaces/Basics/OutputTypeChoice_Rate.mo @@ -0,0 +1,17 @@ +within BusinessSimulation.Interfaces.Basics; + +partial class OutputTypeChoice_Rate "Partial model to set the output type to some kind of rate" + replaceable encapsulated type OutputType = .BusinessSimulation.Units.Rate; + connector RealOutput = output OutputType "Output rate signal" annotation(defaultComponentName = "y", Icon(coordinateSystem(preserveAspectRatio = true, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, lineColor = {1, 37, 163}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-100, 100}, {100, 0}, {-100, -100}})}), Diagram(coordinateSystem(preserveAspectRatio = true, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, lineColor = {1, 37, 163}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-100, 50}, {0, 0}, {-100, -50}}), Text(visible = true, origin = {0, 80}, textColor = {128, 128, 128}, extent = {{-100, -12}, {100, 12}}, textString = "%name", fontName = "Lato", textStyle = {TextStyle.Bold})}), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

A Real output connector.

")); + connector RealMultiOutput = output OutputType "Output signal" annotation(defaultComponentName = "y", Icon(coordinateSystem(preserveAspectRatio = true, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, lineColor = {1, 37, 163}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-100, 100}, {100, 0}, {-100, -100}}), Ellipse(visible = true, origin = {-24.747, 0}, lineColor = {255, 255, 255}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, extent = {{-24.747, -24.747}, {24.747, 24.747}})}), Diagram(coordinateSystem(preserveAspectRatio = true, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, origin = {100, 0}, lineColor = {1, 37, 163}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-100, 50}, {0, 0}, {-100, -50}}), Text(visible = true, origin = {0, 80}, textColor = {128, 128, 128}, extent = {{-100, -12}, {100, 12}}, textString = "%name", fontName = "Lato", textStyle = {TextStyle.Bold})}), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

A Real output connector to indicate vector or list output.

")); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial class that enables the redeclaration of type OutputType which by default is set to Units.Rate. This class is only used for extensions.

+

See also

+

Units.RateUnits

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, fillColor = {255, 255, 255}, pattern = LinePattern.None, extent = {{-100, -100}, {100, 100}})}), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end OutputTypeChoice_Rate; diff --git a/BusinessSimulation/Interfaces/Basics/OutputTypeChoice_Time.mo b/BusinessSimulation/Interfaces/Basics/OutputTypeChoice_Time.mo new file mode 100644 index 0000000..2d5a83f --- /dev/null +++ b/BusinessSimulation/Interfaces/Basics/OutputTypeChoice_Time.mo @@ -0,0 +1,17 @@ +within BusinessSimulation.Interfaces.Basics; + +partial class OutputTypeChoice_Time "Partial model to set output type to some derivative of time" + replaceable encapsulated type OutputType = .BusinessSimulation.Units.Time; + connector RealOutput = output OutputType "Output time signal" annotation(defaultComponentName = "y", Icon(coordinateSystem(preserveAspectRatio = true, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, lineColor = {1, 37, 163}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-100, 100}, {100, 0}, {-100, -100}})}), Diagram(coordinateSystem(preserveAspectRatio = true, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, lineColor = {1, 37, 163}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-100, 50}, {0, 0}, {-100, -50}}), Text(visible = true, origin = {0, 80}, textColor = {128, 128, 128}, extent = {{-100, -12}, {100, 12}}, textString = "%name", fontName = "Lato", textStyle = {TextStyle.Bold})}), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

A Real output connector.

")); + connector RealMultiOutput = output OutputType "Output signal" annotation(defaultComponentName = "y", Icon(coordinateSystem(preserveAspectRatio = true, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, lineColor = {1, 37, 163}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-100, 100}, {100, 0}, {-100, -100}}), Ellipse(visible = true, origin = {-24.747, 0}, lineColor = {255, 255, 255}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, extent = {{-24.747, -24.747}, {24.747, 24.747}})}), Diagram(coordinateSystem(preserveAspectRatio = true, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, origin = {100, 0}, lineColor = {1, 37, 163}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-100, 50}, {0, 0}, {-100, -50}}), Text(visible = true, origin = {0, 80}, textColor = {128, 128, 128}, extent = {{-100, -12}, {100, 12}}, textString = "%name", fontName = "Lato", textStyle = {TextStyle.Bold})}), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

A Real output connector to indicate vector or list output.

")); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial class that enables the redeclaration of type OutputType which by default is set to Units.Time. This class is only used for extensions.

+

See also

+

Units.TimeUnits

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, fillColor = {255, 255, 255}, pattern = LinePattern.None, extent = {{-100, -100}, {100, 100}})}), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end OutputTypeChoice_Time; diff --git a/BusinessSimulation/Interfaces/Basics/SingleInput.mo b/BusinessSimulation/Interfaces/Basics/SingleInput.mo new file mode 100644 index 0000000..c1e3b95 --- /dev/null +++ b/BusinessSimulation/Interfaces/Basics/SingleInput.mo @@ -0,0 +1,9 @@ +within BusinessSimulation.Interfaces.Basics; + +partial model SingleInput "Single Input to Stock, Flow, or Source/Sink component" + input Connectors.RealInput u "Input signal" annotation(Placement(visible = true, transformation(origin = {-140, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-50, 100}, extent = {{10, 10}, {-10, -10}}, rotation = -270))); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial model with a single Real input connector u. This class is typically used by Stock, Flow or SourcesOrSinks components to allow for an unnamed input connector in a standard position.

+"), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end SingleInput; diff --git a/BusinessSimulation/Interfaces/Basics/ThreeSO.mo b/BusinessSimulation/Interfaces/Basics/ThreeSO.mo new file mode 100644 index 0000000..9273719 --- /dev/null +++ b/BusinessSimulation/Interfaces/Basics/ThreeSO.mo @@ -0,0 +1,17 @@ +within BusinessSimulation.Interfaces.Basics; + +partial class ThreeSO "Generic information output for stock and rate elements" + extends Basics.OutputTypeChoice; + // the output y may be given a start value sometimes and accordingly is put into an Initialization tab + RealOutput y "Level or rate information" annotation(Dialog(enable = false, tab = "Initialization"), Placement(visible = true, transformation(origin = {160, 30}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {50, 104}, extent = {{-10, -10}, {10, 10}}, rotation = -1350))); + RealOutput y1 "Level or rate information" annotation(Placement(visible = true, transformation(origin = {160, 70}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {105, -50}, extent = {{-10, -10}, {10, 10}}, rotation = -360))); + RealOutput y2 "Level or rate information" annotation(Placement(visible = true, transformation(origin = {160, -50}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-105, -50}, extent = {{-10, 10}, {10, -10}}, rotation = -180))); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial model that extends →OutputTypeChoice and has three Real output connectors. It is typically used by Stock components to report the amount inside (e.g. its state).

+

See also

+

+ThreeSO_rate +

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end ThreeSO; diff --git a/BusinessSimulation/Interfaces/Basics/ThreeSO_rate.mo b/BusinessSimulation/Interfaces/Basics/ThreeSO_rate.mo new file mode 100644 index 0000000..d0e4203 --- /dev/null +++ b/BusinessSimulation/Interfaces/Basics/ThreeSO_rate.mo @@ -0,0 +1,12 @@ +within BusinessSimulation.Interfaces.Basics; + +partial class ThreeSO_rate "Generic information output for flow elements" + extends OutputTypeChoice_Rate; + RealOutput y "Rate information" annotation(Placement(visible = true, transformation(origin = {160, 30}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {50, 104}, extent = {{-10, -10}, {10, 10}}, rotation = -1350))); + RealOutput y1 "Rate information" annotation(Placement(visible = true, transformation(origin = {160, 70}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {105, -50}, extent = {{-10, -10}, {10, 10}}, rotation = -360))); + RealOutput y2 "Rate information" annotation(Placement(visible = true, transformation(origin = {160, -50}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-105, -50}, extent = {{-10, 10}, {10, -10}}, rotation = -180))); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial model that has three Real output connectors (unit = \"1/s\"). It is typically used by flow components to report the current rate of flow.

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end ThreeSO_rate; diff --git a/BusinessSimulation/Interfaces/Basics/package.mo b/BusinessSimulation/Interfaces/Basics/package.mo new file mode 100644 index 0000000..618440e --- /dev/null +++ b/BusinessSimulation/Interfaces/Basics/package.mo @@ -0,0 +1,12 @@ +within BusinessSimulation.Interfaces; + +package Basics "Partial models for stocks,flows, sources etc." + extends Icons.BasesPackage; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This package contains partial classes at a very basic level (e.g. mostly just connectors and/or rudimentory functionality).

+
+
+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+"), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Basics; diff --git a/BusinessSimulation/Interfaces/Basics/package.order b/BusinessSimulation/Interfaces/Basics/package.order new file mode 100644 index 0000000..8722cf3 --- /dev/null +++ b/BusinessSimulation/Interfaces/Basics/package.order @@ -0,0 +1,21 @@ +OutputTypeChoice +OutputTypeChoice_Rate +OutputTypeChoice_Time +GenericFlow +GenericFlow_Special +ThreeSO +ThreeSO_rate +Interaction4SO +GenericStock +GenericStock_Special +GenericSourceOrSink +SingleInput +GenericStockInfo +GenericStockInfo_Special +GenericSensor +BaseConverter +GenericSmooth +BasePolicy +BasePolicy_MO +BaseInformationProcessing +BaseInformationProcessing_MO diff --git a/BusinessSimulation/Interfaces/Connectors/BooleanInput.mo b/BusinessSimulation/Interfaces/Connectors/BooleanInput.mo new file mode 100644 index 0000000..a5ebc84 --- /dev/null +++ b/BusinessSimulation/Interfaces/Connectors/BooleanInput.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Interfaces.Connectors; + +connector BooleanInput = input Boolean "Input flag" annotation(defaultComponentName = "u", Diagram(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, origin = {-100, 0}, lineColor = {190, 52, 178}, fillColor = {190, 52, 178}, fillPattern = FillPattern.Solid, points = {{0, 50}, {100, 0}, {0, -50}, {0, 50}}), Text(visible = true, origin = {0, 80}, textColor = {128, 128, 128}, extent = {{-100, -12}, {100, 12}}, textString = "%name", fontName = "Lato", textStyle = {TextStyle.Bold})}), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, lineColor = {190, 52, 178}, fillColor = {190, 52, 178}, fillPattern = FillPattern.Solid, points = {{-100, 100}, {100, 0}, {-100, -100}, {-100, 100}})}), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

A Boolean input connector.

+")); diff --git a/BusinessSimulation/Interfaces/Connectors/BooleanMultiInput.mo b/BusinessSimulation/Interfaces/Connectors/BooleanMultiInput.mo new file mode 100644 index 0000000..3b3f63c --- /dev/null +++ b/BusinessSimulation/Interfaces/Connectors/BooleanMultiInput.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Interfaces.Connectors; + +connector BooleanMultiInput = input Boolean "Input of a vector of Booleans" annotation(defaultComponentName = "u", Diagram(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, origin = {-100, 0}, lineColor = {190, 52, 178}, fillColor = {190, 52, 178}, fillPattern = FillPattern.Solid, points = {{0, 50}, {100, 0}, {0, -50}, {0, 50}}), Text(visible = true, origin = {0, 80}, textColor = {128, 128, 128}, extent = {{-100, -12}, {100, 12}}, textString = "%name", fontName = "Lato", textStyle = {TextStyle.Bold})}), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, lineColor = {190, 52, 178}, fillColor = {190, 52, 178}, fillPattern = FillPattern.Solid, points = {{-100, 100}, {100, 0}, {-100, -100}, {-100, 100}}), Ellipse(visible = true, origin = {-24.747, 0}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-24.747, -24.747}, {24.747, 24.747}})}), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

A Boolean vector input connector.

+")); diff --git a/BusinessSimulation/Interfaces/Connectors/BooleanOutput.mo b/BusinessSimulation/Interfaces/Connectors/BooleanOutput.mo new file mode 100644 index 0000000..70d8da2 --- /dev/null +++ b/BusinessSimulation/Interfaces/Connectors/BooleanOutput.mo @@ -0,0 +1,6 @@ +within BusinessSimulation.Interfaces.Connectors; + +connector BooleanOutput = output Boolean "Output flag" annotation(defaultComponentName = "y", Icon(coordinateSystem(preserveAspectRatio = true, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, lineColor = {190, 52, 178}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-100, 100}, {100, 0}, {-100, -100}})}), Diagram(coordinateSystem(preserveAspectRatio = true, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, origin = {100, 0}, lineColor = {190, 52, 178}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-100, 50}, {0, 0}, {-100, -50}}), Text(visible = true, origin = {0, 80}, textColor = {128, 128, 128}, extent = {{-100, -12}, {100, 12}}, textString = "%name", fontName = "Lato", textStyle = {TextStyle.Bold})}), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

A Boolean output connector.

+")); diff --git a/BusinessSimulation/Interfaces/Connectors/DataBus.mo b/BusinessSimulation/Interfaces/Connectors/DataBus.mo new file mode 100644 index 0000000..7112a93 --- /dev/null +++ b/BusinessSimulation/Interfaces/Connectors/DataBus.mo @@ -0,0 +1,13 @@ +within BusinessSimulation.Interfaces.Connectors; + +expandable connector DataBus "Expandable connector for multiple data signals (input/output)" + extends Icons.DataBus; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

A DataBus is an expandable connector for information inputs and outputs.

+

Notes

+

All expandable connectors can be connected to each other and will propagate variables and connectors contained within. Nevertheless, it is good practice in System Dynamics modeling, to keep information and \"material\" networks separated from each other for clarity. Elements within a MultiPort should only be connected to elements in other MultiPorts, FlowPorts or StockPorts.

+

See also

+

FlowPort, StockPort, MultiPortOmniBus

+")); +end DataBus; diff --git a/BusinessSimulation/Interfaces/Connectors/DataInPort.mo b/BusinessSimulation/Interfaces/Connectors/DataInPort.mo new file mode 100644 index 0000000..9149c8b --- /dev/null +++ b/BusinessSimulation/Interfaces/Connectors/DataInPort.mo @@ -0,0 +1,13 @@ +within BusinessSimulation.Interfaces.Connectors; + +expandable connector DataInPort "Expandable connector for multiple inputs" + extends Icons.DataInPort; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

A DataBus is an expandable connector for information inputs and outputs.

+

Notes

+

All expandable connectors can be connected to each other and will propagate variables and connectors contained within. Nevertheless, it is good practice in System Dynamics modeling, to keep information and \"material\" networks separated from each other for clarity. Elements within a MultiPort should only be connected to elements in other MultiPorts, FlowPorts or StockPorts.

+

See also

+

FlowPort, StockPort, MultiPortOmniBus

+", revisions = ""), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}))); +end DataInPort; diff --git a/BusinessSimulation/Interfaces/Connectors/DataOutPort.mo b/BusinessSimulation/Interfaces/Connectors/DataOutPort.mo new file mode 100644 index 0000000..7399a1b --- /dev/null +++ b/BusinessSimulation/Interfaces/Connectors/DataOutPort.mo @@ -0,0 +1,13 @@ +within BusinessSimulation.Interfaces.Connectors; + +expandable connector DataOutPort "Expandable connector for multiple outputs" + extends Icons.DataOutPort; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

A DataBus is an expandable connector for information inputs and outputs.

+

Notes

+

All expandable connectors can be connected to each other and will propagate variables and connectors contained within. Nevertheless, it is good practice in System Dynamics modeling, to keep information and \"material\" networks separated from each other for clarity. Elements within a MultiPort should only be connected to elements in other MultiPorts, FlowPorts or StockPorts.

+

See also

+

FlowPort, StockPort, MultiPortOmniBus

+", revisions = ""), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}))); +end DataOutPort; diff --git a/BusinessSimulation/Interfaces/Connectors/ExpandableFlowPort.mo b/BusinessSimulation/Interfaces/Connectors/ExpandableFlowPort.mo new file mode 100644 index 0000000..ea31d82 --- /dev/null +++ b/BusinessSimulation/Interfaces/Connectors/ExpandableFlowPort.mo @@ -0,0 +1,13 @@ +within BusinessSimulation.Interfaces.Connectors; + +expandable connector ExpandableFlowPort "Expandable connector for flow ports" + extends Icons.ExpandableFlowPort; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Expandable connector to accomodate multiple flow ports.

+

Notes

+

While the FlowMultiPort component is typically used to visually show the presence of an array of FlowPort, this component is an expandable connector that is much more flexible.

+

See also

+

FlowMultiPortFlowPort

+")); +end ExpandableFlowPort; diff --git a/BusinessSimulation/Interfaces/Connectors/ExpandableStockPort.mo b/BusinessSimulation/Interfaces/Connectors/ExpandableStockPort.mo new file mode 100644 index 0000000..2f6d739 --- /dev/null +++ b/BusinessSimulation/Interfaces/Connectors/ExpandableStockPort.mo @@ -0,0 +1,13 @@ +within BusinessSimulation.Interfaces.Connectors; + +expandable connector ExpandableStockPort "Expandable connector for stock ports" + extends Icons.ExpandableStockPort; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Expandable connector to accomodate multiple stock ports.

+

Notes

+

While the StockMultiPort component is typically used to visually show the presence of an array of StockPort, this component is an expandable connector that is much more flexible.

+

See also

+

StockMultiPortStockPort

+")); +end ExpandableStockPort; diff --git a/BusinessSimulation/Interfaces/Connectors/FlowMultiPort.mo b/BusinessSimulation/Interfaces/Connectors/FlowMultiPort.mo new file mode 100644 index 0000000..fef408e --- /dev/null +++ b/BusinessSimulation/Interfaces/Connectors/FlowMultiPort.mo @@ -0,0 +1,12 @@ +within BusinessSimulation.Interfaces.Connectors; + +connector FlowMultiPort "Used to represent multiple flow connectors" + extends FlowPort; + annotation(Diagram(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, origin = {-5, 5}, lineColor = {128, 0, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-55, -55}, {55, 55}})}), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The FlowPort is the counter part to the StockPort and contains an acausal connector with the Real potential variable stock indicating the stored amount in a connected reservoir and the Real flow variable rate indicating the rate of flow into the connected stock (rate < 0) or out of the connected stock (rate > 0).

+

There are also two Boolean input variables, which indicate whether draining the connected reservoir (stopOutflow) or filling it (stopInflow) is prohibited. These signals originate with the connected stock.

+

See also

+

StockPortFlowMultiPort

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Ellipse(visible = true, lineColor = {255, 255, 255}, fillColor = {128, 0, 128}, fillPattern = FillPattern.Solid, extent = {{-24.747, -24.747}, {24.747, 24.747}})})); +end FlowMultiPort; diff --git a/BusinessSimulation/Interfaces/Connectors/FlowPort.mo b/BusinessSimulation/Interfaces/Connectors/FlowPort.mo new file mode 100644 index 0000000..0974f2c --- /dev/null +++ b/BusinessSimulation/Interfaces/Connectors/FlowPort.mo @@ -0,0 +1,16 @@ +within BusinessSimulation.Interfaces.Connectors; + +connector FlowPort "Used to represent stock and flow connections" + import BusinessSimulation.Units.Rate; + Real stock "The current amount of 'mass' in a connected stock"; + flow Rate rate "Flow that affects the stock"; + input Boolean stopInflow "= true, if nothing can flow into a connected stock"; + input Boolean stopOutflow "= true, if nothing can flow out of a connected stock"; + annotation(Diagram(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, origin = {-5, 5}, lineColor = {128, 0, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-55, -55}, {55, 55}}), Text(visible = true, origin = {0, 90}, textColor = {128, 128, 128}, extent = {{-100, -12}, {100, 12}}, textString = "%name", fontName = "Lato", textStyle = {TextStyle.Bold})}), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The FlowPort is the counter part to the StockPort and contains an acausal connector with the Real potential variable stock indicating the stored amount in a connected reservoir and the Real flow variable rate indicating the rate of flow into the connected stock (rate < 0) or out of the connected stock (rate > 0).

+

There are also two Boolean input variables, which indicate whether draining the connected reservoir (stopOutflow) or filling it (stopInflow) is prohibited. These signals originate with the connected stock.

+

See also

+

StockPortFlowMultiPort

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {128, 0, 128}, fillColor = {128, 0, 128}, fillPattern = FillPattern.Solid, extent = {{-100, -100}, {100, 100}}), Rectangle(visible = true, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-80, -80}, {80, 80}})})); +end FlowPort; diff --git a/BusinessSimulation/Interfaces/Connectors/FlowPort_Special.mo b/BusinessSimulation/Interfaces/Connectors/FlowPort_Special.mo new file mode 100644 index 0000000..4290c6b --- /dev/null +++ b/BusinessSimulation/Interfaces/Connectors/FlowPort_Special.mo @@ -0,0 +1,35 @@ +within BusinessSimulation.Interfaces.Connectors; + +connector FlowPort_Special "Used to represent a flow connected to a dynamic stock that will set the rate of flow" + import BusinessSimulation.Units.Rate; + Real data "Flow value to be observed by connected flow element"; + flow Rate rate "Flow that affects the stock"; + annotation(Diagram(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, origin = {-5, 5}, lineColor = {255, 0, 0}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 4, extent = {{-55, -55}, {55, 55}}), Text(visible = true, origin = {0, 90}, textColor = {128, 128, 128}, extent = {{-100, -12}, {100, 12}}, textString = "%name", fontName = "Lato", textStyle = {TextStyle.Bold})}), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The FlowPort_Special is the corresponding connector to the StockPort_Special and will only connect to these. While usually the rate of flow is determined by a flow component, in the case of dynamic stocks (e.g. higher order delays) the rate of outflow will be determined by the stock component and transmitted to the connected flow using the variable data

+

It has the following connectors:

+ + + + + + + + + + + + + + +
CONNECTORTYPEDESCRIPTION
dataReal +

Rate of flow to be observed by connected flow element

+
rate (flow)Real +

Flow that affects the stock

+
+

Acknowledgements

+

The FlowPort_Special connector class is used as MassPortF  by Peter Junglas for his approach to SystemDynamics modeling [18, Chapter 12] (see here for a System Dynamics Modelica library published by Peter Junglas) and has been simplified for the Business Simulation library.

+

See also

+

StockPort_Special

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {255, 0, 0}, fillColor = {255, 0, 0}, fillPattern = FillPattern.Solid, extent = {{-100, -100}, {100, 100}}), Rectangle(visible = true, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-80, -80}, {80, 80}})})); +end FlowPort_Special; diff --git a/BusinessSimulation/Interfaces/Connectors/MultiPort.mo b/BusinessSimulation/Interfaces/Connectors/MultiPort.mo new file mode 100644 index 0000000..48eed0b --- /dev/null +++ b/BusinessSimulation/Interfaces/Connectors/MultiPort.mo @@ -0,0 +1,13 @@ +within BusinessSimulation.Interfaces.Connectors; + +expandable connector MultiPort "Expandable connector for mass transport pipelines" + extends Icons.MultiPort; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Like a DataBus for information inputs and outputs, the FlowMultiPort is an expandable connector that should only contain named FlowPort and/or StockPort connectors.

+

Notes

+

All expandable connectors can be connected to each other and will propagate variables and connectors contained within. Nevertheless, it is good practice in System Dynamics modeling, to keep information and \"material\" networks separated from each other for clarity. Elements within a MultiPort should only be connected to elements in other MultiPorts, FlowPorts or StockPorts.

+

See also

+

FlowPort, StockPortDataBusOmniBus

+")); +end MultiPort; diff --git a/BusinessSimulation/Interfaces/Connectors/OmniBus.mo b/BusinessSimulation/Interfaces/Connectors/OmniBus.mo new file mode 100644 index 0000000..13a0ef1 --- /dev/null +++ b/BusinessSimulation/Interfaces/Connectors/OmniBus.mo @@ -0,0 +1,13 @@ +within BusinessSimulation.Interfaces.Connectors; + +expandable connector OmniBus "Expandable connector for combined mass and information transport pipelines" + extends Icons.OmniBus; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The OmniBus is an expandable connector that can contain input and output-connnectors (data) as well as Stock- and Flow-Ports.

+

Notes

+

All expandable connectors can be connected to each other and will propagate variables and connectors contained within.

+

See also

+

FlowPort, StockPortDataBusMultiPort

+", revisions = "")); +end OmniBus; diff --git a/BusinessSimulation/Interfaces/Connectors/RealInput.mo b/BusinessSimulation/Interfaces/Connectors/RealInput.mo new file mode 100644 index 0000000..26334df --- /dev/null +++ b/BusinessSimulation/Interfaces/Connectors/RealInput.mo @@ -0,0 +1,5 @@ +within BusinessSimulation.Interfaces.Connectors; + +connector RealInput = input Real "Input signal" annotation(defaultComponentName = "u", Diagram(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, origin = {-100, 0}, lineColor = {5, 5, 125}, fillColor = {5, 5, 125}, fillPattern = FillPattern.Solid, points = {{0, 50}, {100, 0}, {0, -50}, {0, 50}}), Text(visible = true, origin = {0, 80}, textColor = {128, 128, 128}, extent = {{-100, -12}, {100, 12}}, textString = "%name", fontName = "Lato", textStyle = {TextStyle.Bold})}), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, points = {{-100, 100}, {100, 0}, {-100, -100}, {-100, 100}})}), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

A Real input connector.

")); diff --git a/BusinessSimulation/Interfaces/Connectors/RealMultiInput.mo b/BusinessSimulation/Interfaces/Connectors/RealMultiInput.mo new file mode 100644 index 0000000..45aab9f --- /dev/null +++ b/BusinessSimulation/Interfaces/Connectors/RealMultiInput.mo @@ -0,0 +1,8 @@ +within BusinessSimulation.Interfaces.Connectors; + +connector RealMultiInput = input RealInput "Multiple input signals" annotation(defaultComponentName = "u", Diagram(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, origin = {-100, 0}, lineColor = {5, 5, 125}, fillColor = {5, 5, 125}, fillPattern = FillPattern.Solid, points = {{0, 50}, {100, 0}, {0, -50}, {0, 50}}), Text(visible = true, origin = {0, 80}, textColor = {128, 128, 128}, extent = {{-100, -12}, {100, 12}}, textString = "%name", fontName = "Lato", textStyle = {TextStyle.Bold})}), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, points = {{-100, 100}, {100, 0}, {-100, -100}, {-100, 100}}), Ellipse(visible = true, origin = {-24.747, 0}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-24.747, -24.747}, {24.747, 24.747}})}), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

A Real input connector to indicate vector inputs.

+

See also

+

RealInput

+")); diff --git a/BusinessSimulation/Interfaces/Connectors/RealMultiOutput.mo b/BusinessSimulation/Interfaces/Connectors/RealMultiOutput.mo new file mode 100644 index 0000000..3ece649 --- /dev/null +++ b/BusinessSimulation/Interfaces/Connectors/RealMultiOutput.mo @@ -0,0 +1,8 @@ +within BusinessSimulation.Interfaces.Connectors; + +connector RealMultiOutput = output Real "Multiple output signals" annotation(defaultComponentName = "y", Icon(coordinateSystem(preserveAspectRatio = true, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, lineColor = {1, 37, 163}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-100, 100}, {100, 0}, {-100, -100}}), Ellipse(visible = true, origin = {-24.747, 0}, lineColor = {255, 255, 255}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, extent = {{-24.747, -24.747}, {24.747, 24.747}})}), Diagram(coordinateSystem(preserveAspectRatio = true, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, origin = {100, 0}, lineColor = {1, 37, 163}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-100, 50}, {0, 0}, {-100, -50}}), Text(visible = true, origin = {0, 80}, textColor = {128, 128, 128}, extent = {{-100, -12}, {100, 12}}, textString = "%name", fontName = "Lato", textStyle = {TextStyle.Bold})}), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

A Real output connector to indicate vector or list output.

+

See also

+

RealInput

+")); diff --git a/BusinessSimulation/Interfaces/Connectors/RealOutput.mo b/BusinessSimulation/Interfaces/Connectors/RealOutput.mo new file mode 100644 index 0000000..167fc51 --- /dev/null +++ b/BusinessSimulation/Interfaces/Connectors/RealOutput.mo @@ -0,0 +1,5 @@ +within BusinessSimulation.Interfaces.Connectors; + +connector RealOutput = output Real "Output signal" annotation(defaultComponentName = "y", Icon(coordinateSystem(preserveAspectRatio = true, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, lineColor = {1, 37, 163}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-100, 100}, {100, 0}, {-100, -100}})}), Diagram(coordinateSystem(preserveAspectRatio = true, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, lineColor = {1, 37, 163}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-100, 50}, {0, 0}, {-100, -50}}), Text(visible = true, origin = {0, 80}, textColor = {128, 128, 128}, extent = {{-100, -12}, {100, 12}}, textString = "%name", fontName = "Lato", textStyle = {TextStyle.Bold})}), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

A Real output connector.

")); diff --git a/BusinessSimulation/Interfaces/Connectors/StockInfoInput.mo b/BusinessSimulation/Interfaces/Connectors/StockInfoInput.mo new file mode 100644 index 0000000..afd2eb7 --- /dev/null +++ b/BusinessSimulation/Interfaces/Connectors/StockInfoInput.mo @@ -0,0 +1,5 @@ +within BusinessSimulation.Interfaces.Connectors; + +connector StockInfoInput = input Types.StockInformation "Input of record with stock-related information" annotation(Diagram(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, origin = {-100, 0}, lineColor = {128, 0, 128}, fillColor = {128, 0, 128}, fillPattern = FillPattern.Solid, points = {{0, 50}, {100, 0}, {0, -50}, {0, 50}}), Text(visible = true, origin = {0, 80}, textColor = {128, 128, 128}, extent = {{-100, -12}, {100, 12}}, textString = "%name", fontName = "Lato", textStyle = {TextStyle.Bold})}), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, lineColor = {128, 0, 128}, fillColor = {128, 0, 128}, fillPattern = FillPattern.Solid, points = {{-100, 100}, {100, 0}, {-100, -100}, {-100, 100}})}), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Input connector for →StockInformation.

")); diff --git a/BusinessSimulation/Interfaces/Connectors/StockInfoOutput.mo b/BusinessSimulation/Interfaces/Connectors/StockInfoOutput.mo new file mode 100644 index 0000000..634f924 --- /dev/null +++ b/BusinessSimulation/Interfaces/Connectors/StockInfoOutput.mo @@ -0,0 +1,5 @@ +within BusinessSimulation.Interfaces.Connectors; + +connector StockInfoOutput = output Types.StockInformation "Output of record with stock-related information" annotation(Diagram(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, origin = {100, 0}, lineColor = {128, 0, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-100, 50}, {0, 0}, {-100, -50}, {-100, 50}}), Text(visible = true, origin = {0, 80}, textColor = {128, 128, 128}, extent = {{-100, -12}, {100, 12}}, textString = "%name", fontName = "Lato", textStyle = {TextStyle.Bold})}), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, lineColor = {128, 0, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 1, points = {{-100, 100}, {100, 0}, {-100, -100}, {-100, 100}})}), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Output connector for →StockInformation.

")); diff --git a/BusinessSimulation/Interfaces/Connectors/StockMultiPort.mo b/BusinessSimulation/Interfaces/Connectors/StockMultiPort.mo new file mode 100644 index 0000000..cf08e79 --- /dev/null +++ b/BusinessSimulation/Interfaces/Connectors/StockMultiPort.mo @@ -0,0 +1,11 @@ +within BusinessSimulation.Interfaces.Connectors; + +connector StockMultiPort "Used to represent multiple stock connectors" + extends StockPort; + annotation(Diagram(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, origin = {-5, 5}, lineColor = {128, 0, 128}, fillColor = {128, 0, 128}, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-55, -55}, {55, 55}})}), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The StockPort is a composite connector and consists of an acausal connector with the Real potential variable stock indicating the stored amount in a reservoir and the Real flow variable rate indicating the rate of flow into (rate > 0) or out of (rate < 0) the reservoir.

+

There are also two Boolean output variables, which indicate whether draining the reservoir (stopOutflow) or filling it (stopInflow) is prohibited. Since a generic reservoir will have two ports it is possible to allow inflows and outflows on both ports (standard) or give the stock a clear direction of flow with one port serving as inflow and the other as outflow connector.

+ +"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Ellipse(visible = true, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-24.747, -24.747}, {24.747, 24.747}})})); +end StockMultiPort; diff --git a/BusinessSimulation/Interfaces/Connectors/StockPort.mo b/BusinessSimulation/Interfaces/Connectors/StockPort.mo new file mode 100644 index 0000000..6d60f51 --- /dev/null +++ b/BusinessSimulation/Interfaces/Connectors/StockPort.mo @@ -0,0 +1,16 @@ +within BusinessSimulation.Interfaces.Connectors; + +connector StockPort "Connector for stock components" + import BusinessSimulation.Units.Rate; + Real stock "Current amount of 'mass' in the stock"; + flow Rate rate "Flow that affects the stock"; + output Boolean stopInflow "= true, if nothing can flow into the stock"; + output Boolean stopOutflow " = true, if nothing can flow out of the stock"; + annotation(Diagram(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, origin = {-5, 5}, lineColor = {128, 0, 128}, fillColor = {128, 0, 128}, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-55, -55}, {55, 55}}), Text(visible = true, origin = {0, 90}, textColor = {128, 128, 128}, extent = {{-100, -12}, {100, 12}}, textString = "%name", fontName = "Lato", textStyle = {TextStyle.Bold})}), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The StockPort is a composite connector and consists of an acausal connector with the Real potential variable stock indicating the stored amount in a reservoir and the Real flow variable rate indicating the rate of flow into (rate > 0) or out of (rate < 0) the reservoir.

+

There are also two Boolean output variables, which indicate whether draining the reservoir (stopOutflow) or filling it (stopInflow) is prohibited. Since a generic reservoir will have two ports it is possible to allow inflows and outflows on both ports (standard) or give the stock a clear direction of flow with one port serving as inflow and the other as outflow connector.

+

See also

+

FlowPortStockMultiPort

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {128, 0, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 1, extent = {{-100, -100}, {100, 100}}), Rectangle(visible = true, lineColor = {128, 0, 128}, fillColor = {128, 0, 128}, fillPattern = FillPattern.Solid, extent = {{-80, -80}, {80, 80}})})); +end StockPort; diff --git a/BusinessSimulation/Interfaces/Connectors/StockPort_Special.mo b/BusinessSimulation/Interfaces/Connectors/StockPort_Special.mo new file mode 100644 index 0000000..948ac0e --- /dev/null +++ b/BusinessSimulation/Interfaces/Connectors/StockPort_Special.mo @@ -0,0 +1,36 @@ +within BusinessSimulation.Interfaces.Connectors; + +connector StockPort_Special "Used to represent a dynamic stock that will set the rate of the connected flow" + import BusinessSimulation.Units.Rate; + Real data "Rate of flow to be observed by connected flow element"; + flow Rate rate "Flow that affect the stock"; + annotation(Diagram(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, origin = {-5, 5}, lineColor = {255, 0, 0}, fillColor = {255, 0, 0}, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-55, -55}, {55, 55}}), Text(visible = true, origin = {0, 90}, textColor = {128, 128, 128}, extent = {{-100, -12}, {100, 12}}, textString = "%name", fontName = "Lato", textStyle = {TextStyle.Bold})}), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The StockPort_Special is typically used for a dynamic stock, e.g. a stock with some kind of internal behavior (e.g. a higher-order delay, a conveyor or an oven). While usually the rate of flow is determined by flow elements, here the real variable data is most often used to signal the value of flow to the flow element, as the rate of flow is determined by the stock - not the flow - in that case.

+

It has the following connectors:

+ + + + + + + + + + + + + + +
CONNECTORTYPEDESCRIPTION
dataReal +

Rate of flow to be observed by connected flow element

+
rate (flow)Real +

Flow that affects the stock

+
+

StockPort_Sepcial connectors will only connect to FlowPort_Special connectors.

+

Acknowledgements

+

The StockPort_Special connector was used by Peter Junglas as MassPortR for his approach to SystemDynamics modeling [18, Chapter 12] (see here for a SystemDynamics Modelica library published by Peter Junglas) and has been simplified for the Business Simulation library.

+

See also

+

FlowPort_Special

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {255, 0, 0}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 1, extent = {{-100, -100}, {100, 100}}), Rectangle(visible = true, lineColor = {255, 0, 0}, fillColor = {255, 0, 0}, fillPattern = FillPattern.Solid, extent = {{-80, -80}, {80, 80}})})); +end StockPort_Special; diff --git a/BusinessSimulation/Interfaces/Connectors/package.mo b/BusinessSimulation/Interfaces/Connectors/package.mo new file mode 100644 index 0000000..a072fe1 --- /dev/null +++ b/BusinessSimulation/Interfaces/Connectors/package.mo @@ -0,0 +1,12 @@ +within BusinessSimulation.Interfaces; + +package Connectors "Ports to establish connections between components" + extends Icons.ConnectorsPackage; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This package contains connector classes.

+
+
+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Ellipse(visible = true, origin = {-40, -40}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-24.747, -24.747}, {24.747, 24.747}}), Polygon(visible = true, origin = {45, -42.5}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 3, points = {{-20, 12.5}, {20, 12.5}, {25, 7.5}, {20, -10}, {15, -12.5}, {-15, -12.5}, {-20, -10}, {-25, 7.5}}, smooth = Smooth.Bezier)}), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Connectors; diff --git a/BusinessSimulation/Interfaces/Connectors/package.order b/BusinessSimulation/Interfaces/Connectors/package.order new file mode 100644 index 0000000..b5ad633 --- /dev/null +++ b/BusinessSimulation/Interfaces/Connectors/package.order @@ -0,0 +1,22 @@ +StockPort +StockMultiPort +ExpandableStockPort +FlowPort +FlowMultiPort +ExpandableFlowPort +MultiPort +StockPort_Special +FlowPort_Special +StockInfoOutput +StockInfoInput +BooleanOutput +BooleanInput +BooleanMultiInput +RealInput +RealOutput +RealMultiInput +RealMultiOutput +DataBus +DataInPort +DataOutPort +OmniBus diff --git a/BusinessSimulation/Interfaces/PartialConverters/BooleanMISO.mo b/BusinessSimulation/Interfaces/PartialConverters/BooleanMISO.mo new file mode 100644 index 0000000..d262f55 --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialConverters/BooleanMISO.mo @@ -0,0 +1,11 @@ +within BusinessSimulation.Interfaces.PartialConverters; + +partial block BooleanMISO "Converter with single input and single output" + extends BooleanSO; + Connectors.BooleanMultiInput u[nin] "Input" annotation(Placement(visible = true, transformation(origin = {-145, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, 0}, extent = {{-10, 10}, {10, -10}}, rotation = 0))); + parameter Integer nin(min = 1) = 2 "Number of Boolean input signals" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial block extending from the →BooleanSO class with a Boolean output and a Boolean multi input connector.

+"), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end BooleanMISO; diff --git a/BusinessSimulation/Interfaces/PartialConverters/BooleanSI2SO.mo b/BusinessSimulation/Interfaces/PartialConverters/BooleanSI2SO.mo new file mode 100644 index 0000000..9003800 --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialConverters/BooleanSI2SO.mo @@ -0,0 +1,11 @@ +within BusinessSimulation.Interfaces.PartialConverters; + +partial block BooleanSI2SO "Converter with two boolean inputs and a boolean output" + extends BooleanSO; + Connectors.BooleanInput u1 "Input 1" annotation(Placement(visible = true, transformation(origin = {-145, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, 50}, extent = {{-10, 10}, {10, -10}}, rotation = 0))); + Connectors.BooleanInput u2 "Input 2" annotation(Placement(visible = true, transformation(origin = {-145, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, -50}, extent = {{-10, 10}, {10, -10}}, rotation = 0))); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial block extending from →BooleanSO with two Boolean input converters and a single Boolean output converter.

+"), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end BooleanSI2SO; diff --git a/BusinessSimulation/Interfaces/PartialConverters/BooleanSIRealSO.mo b/BusinessSimulation/Interfaces/PartialConverters/BooleanSIRealSO.mo new file mode 100644 index 0000000..4386cc5 --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialConverters/BooleanSIRealSO.mo @@ -0,0 +1,9 @@ +within BusinessSimulation.Interfaces.PartialConverters; + +partial block BooleanSIRealSO "Converter with single boolean input and single real output" + extends SO; + Connectors.BooleanInput u "Input" annotation(Placement(visible = true, transformation(origin = {-145, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, 0}, extent = {{-10, 10}, {10, -10}}, rotation = 0))); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial block extending from the →SO class with a Real output and a Boolean input connector.

"), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end BooleanSIRealSO; diff --git a/BusinessSimulation/Interfaces/PartialConverters/BooleanSISO.mo b/BusinessSimulation/Interfaces/PartialConverters/BooleanSISO.mo new file mode 100644 index 0000000..8265da8 --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialConverters/BooleanSISO.mo @@ -0,0 +1,9 @@ +within BusinessSimulation.Interfaces.PartialConverters; + +partial block BooleanSISO "Converter with single input and single output" + extends BooleanSO; + Connectors.BooleanInput u "Input" annotation(Placement(visible = true, transformation(origin = {-145, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, 0}, extent = {{-10, 10}, {10, -10}}, rotation = 0))); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial block extending from the →BooleanSO class with a Boolean output and a Boolean input connector.

"), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end BooleanSISO; diff --git a/BusinessSimulation/Interfaces/PartialConverters/BooleanSO.mo b/BusinessSimulation/Interfaces/PartialConverters/BooleanSO.mo new file mode 100644 index 0000000..8ba96ac --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialConverters/BooleanSO.mo @@ -0,0 +1,10 @@ +within BusinessSimulation.Interfaces.PartialConverters; + +partial block BooleanSO "Generic converter with a boolean output" + extends Icons.Converter; + Connectors.BooleanOutput y "Boolean output" annotation(Placement(visible = true, transformation(origin = {150, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {80, 0}, extent = {{-10, -10}, {10, 10}}, rotation = -1440))); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial block with a Boolean output connector.

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end BooleanSO; diff --git a/BusinessSimulation/Interfaces/PartialConverters/InformationProcessing_MO.mo b/BusinessSimulation/Interfaces/PartialConverters/InformationProcessing_MO.mo new file mode 100644 index 0000000..70a9693 --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialConverters/InformationProcessing_MO.mo @@ -0,0 +1,12 @@ +within BusinessSimulation.Interfaces.PartialConverters; + +partial block InformationProcessing_MO "Information processing block with multiple outputs" + extends Basics.BaseInformationProcessing_MO; + RealMultiOutput[nout] y "Vector of information output signals" annotation(Placement(visible = true, transformation(origin = {150, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {110, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial block extending from the →BaseInformationProcessing_MO base class with nmultiple Real output connectors. This is the base class for InformationProcessing components with multiple outputs.

+

See also

+

MoleculesOfStructure.InformationProcessing

+"), __Wolfram(itemFlippingEnabled = true), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end InformationProcessing_MO; diff --git a/BusinessSimulation/Interfaces/PartialConverters/InformationProcessing_SO.mo b/BusinessSimulation/Interfaces/PartialConverters/InformationProcessing_SO.mo new file mode 100644 index 0000000..c0e60fe --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialConverters/InformationProcessing_SO.mo @@ -0,0 +1,12 @@ +within BusinessSimulation.Interfaces.PartialConverters; + +partial block InformationProcessing_SO "Information Processing Block" + extends Basics.BaseInformationProcessing; + RealOutput y "Information output signal" annotation(Placement(visible = true, transformation(origin = {160, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {110, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial block extending from the →BaseInformationProcessing base class with a Real output connector. This is the base class for InformationProcessing components.

+

See also

+

MoleculesOfStructure.InformationProcessing

+"), __Wolfram(itemFlippingEnabled = true), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end InformationProcessing_SO; diff --git a/BusinessSimulation/Interfaces/PartialConverters/InformationSource_MO.mo b/BusinessSimulation/Interfaces/PartialConverters/InformationSource_MO.mo new file mode 100644 index 0000000..e285ea1 --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialConverters/InformationSource_MO.mo @@ -0,0 +1,12 @@ +within BusinessSimulation.Interfaces.PartialConverters; + +partial block InformationSource_MO "Information Source with multiple outputs" + extends MO; + extends Icons.InformationSourceIndicator; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial block extending from the →MO partial converter class with multiple Real output connectors. This is the base class for InformationSource components with multiple outputs.

+

See also

+

InformationSources

+"), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end InformationSource_MO; diff --git a/BusinessSimulation/Interfaces/PartialConverters/InformationSource_SO.mo b/BusinessSimulation/Interfaces/PartialConverters/InformationSource_SO.mo new file mode 100644 index 0000000..d651d40 --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialConverters/InformationSource_SO.mo @@ -0,0 +1,12 @@ +within BusinessSimulation.Interfaces.PartialConverters; + +partial block InformationSource_SO "Generic Information Source" + extends SO; + extends Icons.InformationSourceIndicator; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial block extending from the →SO partial converter class with a Real output connector. This is the base class for InformationSource components.

+

See also

+

InformationSources

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Ellipse(visible = true, lineColor = {0, 0, 128}, fillColor = {76, 112, 136}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-58, -58}, {58, 58}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end InformationSource_SO; diff --git a/BusinessSimulation/Interfaces/PartialConverters/MIMO.mo b/BusinessSimulation/Interfaces/PartialConverters/MIMO.mo new file mode 100644 index 0000000..654474e --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialConverters/MIMO.mo @@ -0,0 +1,11 @@ +within BusinessSimulation.Interfaces.PartialConverters; + +partial block MIMO "Converter with multiple inputs and outputs" + extends MO; + parameter Integer nin(min = 2) = 2 "Number of input signals" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + Connectors.RealMultiInput u[nin] "Input" annotation(Placement(visible = true, transformation(origin = {-145, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, 0}, extent = {{-10, 10}, {10, -10}}, rotation = 0))); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial block extending the →MO partial converter class with vectors of nin Real input connectors and nout Real output connectors.

+"), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end MIMO; diff --git a/BusinessSimulation/Interfaces/PartialConverters/MIMO_nin.mo b/BusinessSimulation/Interfaces/PartialConverters/MIMO_nin.mo new file mode 100644 index 0000000..ab4b58b --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialConverters/MIMO_nin.mo @@ -0,0 +1,12 @@ +within BusinessSimulation.Interfaces.PartialConverters; + +partial block MIMO_nin "Converter with multiple inputs and outputs of dimensions nin" + extends Basics.BaseConverter; + Connectors.RealMultiInput u[nin] "Input" annotation(Placement(visible = true, transformation(origin = {-145, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, 0}, extent = {{-10, 10}, {10, -10}}, rotation = 0))); + RealMultiOutput[nin] y annotation(Placement(visible = true, transformation(origin = {150, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {80, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + parameter Integer nin(min = 2) = 2 "Number of input and output signals" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial block with multiple Real input and output connectors each of which have nin elements.

+"), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end MIMO_nin; diff --git a/BusinessSimulation/Interfaces/PartialConverters/MISO.mo b/BusinessSimulation/Interfaces/PartialConverters/MISO.mo new file mode 100644 index 0000000..0bd31f5 --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialConverters/MISO.mo @@ -0,0 +1,11 @@ +within BusinessSimulation.Interfaces.PartialConverters; + +partial block MISO "Converter with multiple inputs and a single output" + extends SO; + parameter Integer nin(min = 2) = 2 "Number of input signals" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + Connectors.RealMultiInput u[nin] "Input" annotation(Placement(visible = true, transformation(origin = {-145, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, 0}, extent = {{-10, 10}, {10, -10}}, rotation = 0))); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial block extending the →BaseConverter class with a vector of nin Real input connectors and one Real output connector.

+"), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end MISO; diff --git a/BusinessSimulation/Interfaces/PartialConverters/MO.mo b/BusinessSimulation/Interfaces/PartialConverters/MO.mo new file mode 100644 index 0000000..e3cf709 --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialConverters/MO.mo @@ -0,0 +1,11 @@ +within BusinessSimulation.Interfaces.PartialConverters; + +partial block MO "Converter with multiple outputs" + extends Basics.BaseConverter; + RealMultiOutput[nout] y "Vector of output signals" annotation(Placement(visible = true, transformation(origin = {150, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {80, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + parameter Integer nout(min = 2) = 2 "Number of output signals" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial block extending the →BaseConverter class with a vector of nout Real output connectors.

+"), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end MO; diff --git a/BusinessSimulation/Interfaces/PartialConverters/Policy_MO.mo b/BusinessSimulation/Interfaces/PartialConverters/Policy_MO.mo new file mode 100644 index 0000000..98b1a43 --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialConverters/Policy_MO.mo @@ -0,0 +1,12 @@ +within BusinessSimulation.Interfaces.PartialConverters; + +partial block Policy_MO "Policy block with multiple outputs" + extends Basics.BasePolicy_MO; + RealMultiOutput[nout] y "Vector of policy output signals" annotation(Placement(visible = true, transformation(origin = {150, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {110, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial block extending from the →BasePolicy_MO base class with multiple Real output connectors. This is the base class for Policy components used to model decision making with multiple outputs.

+

See also

+

MoleculesOfStructure.Policy

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Policy_MO; diff --git a/BusinessSimulation/Interfaces/PartialConverters/Policy_SO.mo b/BusinessSimulation/Interfaces/PartialConverters/Policy_SO.mo new file mode 100644 index 0000000..379d621 --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialConverters/Policy_SO.mo @@ -0,0 +1,12 @@ +within BusinessSimulation.Interfaces.PartialConverters; + +partial block Policy_SO "Policy Block (Decision Making/Controller)" + extends Basics.BasePolicy; + RealOutput y "Policy output signal" annotation(Placement(visible = true, transformation(origin = {160, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {110, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial block extending from the →BasePolicy base class with a Real output connector. This is the base class for Policy components used to model decision making.

+

See also

+

MoleculesOfStructure.Policy

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Policy_SO; diff --git a/BusinessSimulation/Interfaces/PartialConverters/SI2BooleanSO.mo b/BusinessSimulation/Interfaces/PartialConverters/SI2BooleanSO.mo new file mode 100644 index 0000000..ec4b305 --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialConverters/SI2BooleanSO.mo @@ -0,0 +1,11 @@ +within BusinessSimulation.Interfaces.PartialConverters; + +partial block SI2BooleanSO "Converter with two real inputs and boolean output" + extends BooleanSO; + Connectors.RealInput u1 "Input 1" annotation(Placement(visible = true, transformation(origin = {-145, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, 50}, extent = {{-10, 10}, {10, -10}}, rotation = 0))); + Connectors.RealInput u2 "Input 2" annotation(Placement(visible = true, transformation(origin = {-145, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, -50}, extent = {{-10, 10}, {10, -10}}, rotation = 0))); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial block extending from →BooleanSO with two Real input converters and a single Boolean output converter.

+"), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end SI2BooleanSO; diff --git a/BusinessSimulation/Interfaces/PartialConverters/SI2SO.mo b/BusinessSimulation/Interfaces/PartialConverters/SI2SO.mo new file mode 100644 index 0000000..c82b629 --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialConverters/SI2SO.mo @@ -0,0 +1,11 @@ +within BusinessSimulation.Interfaces.PartialConverters; + +partial block SI2SO "Converter with two inputs and a single output" + extends SO; + Connectors.RealInput u1 "Input 1" annotation(Placement(visible = true, transformation(origin = {-145, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, 50}, extent = {{-10, 10}, {10, -10}}, rotation = 0))); + Connectors.RealInput u2 "Input 2" annotation(Placement(visible = true, transformation(origin = {-145, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, -50}, extent = {{-10, 10}, {10, -10}}, rotation = 0))); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial block extending the →SO partial converter class with one Real output connector and two Real input connectors.

+"), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end SI2SO; diff --git a/BusinessSimulation/Interfaces/PartialConverters/SI3SO.mo b/BusinessSimulation/Interfaces/PartialConverters/SI3SO.mo new file mode 100644 index 0000000..1dd13e5 --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialConverters/SI3SO.mo @@ -0,0 +1,12 @@ +within BusinessSimulation.Interfaces.PartialConverters; + +partial block SI3SO "Converter with three inputs and single output" + extends SO; + Connectors.RealInput u1 "Input 1" annotation(Placement(visible = true, transformation(origin = {-145, 60}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, 50}, extent = {{-10, 10}, {10, -10}}, rotation = 0))); + Connectors.RealInput u3 "Input 3" annotation(Placement(visible = true, transformation(origin = {-145, -60}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, -50}, extent = {{-10, 10}, {10, -10}}, rotation = 0))); + Connectors.RealInput u2 "Input 2" annotation(Placement(visible = true, transformation(origin = {-145, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, 0}, extent = {{-10, 10}, {10, -10}}, rotation = 0))); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial block extending the →SO partial converter class with one Real output connector and three Real input connectors.

+"), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end SI3SO; diff --git a/BusinessSimulation/Interfaces/PartialConverters/SIBooleanSO.mo b/BusinessSimulation/Interfaces/PartialConverters/SIBooleanSO.mo new file mode 100644 index 0000000..84f3b97 --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialConverters/SIBooleanSO.mo @@ -0,0 +1,9 @@ +within BusinessSimulation.Interfaces.PartialConverters; + +partial block SIBooleanSO "Generic converter with real input and boolean output" + extends BooleanSO; + Connectors.RealInput u "Input" annotation(Placement(visible = true, transformation(origin = {-145, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, 0}, extent = {{-10, 10}, {10, -10}}, rotation = 0))); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial block extending from →BooleanSO with a Real input and a Boolean output converter.

"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end SIBooleanSO; diff --git a/BusinessSimulation/Interfaces/PartialConverters/SISO.mo b/BusinessSimulation/Interfaces/PartialConverters/SISO.mo new file mode 100644 index 0000000..a344a83 --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialConverters/SISO.mo @@ -0,0 +1,9 @@ +within BusinessSimulation.Interfaces.PartialConverters; + +partial block SISO "Converter with single input and single output" + extends SO; + Connectors.RealInput u "Input" annotation(Placement(visible = true, transformation(origin = {-145, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-80, 0}, extent = {{-10, 10}, {10, -10}}, rotation = 0))); + annotation(Documentation(info = " +

Partial block extending the →SO partial converter class with one Real output connector and a single Real input connector.

+"), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end SISO; diff --git a/BusinessSimulation/Interfaces/PartialConverters/SO.mo b/BusinessSimulation/Interfaces/PartialConverters/SO.mo new file mode 100644 index 0000000..3ebbdac --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialConverters/SO.mo @@ -0,0 +1,9 @@ +within BusinessSimulation.Interfaces.PartialConverters; + +partial block SO "Generic converter for signals" + extends Basics.BaseConverter; + RealOutput y annotation(Placement(visible = true, transformation(origin = {160.268, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {80, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial block extending the →BaseConverter class with one Real output connector.

"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end SO; diff --git a/BusinessSimulation/Interfaces/PartialConverters/SmoothSISO.mo b/BusinessSimulation/Interfaces/PartialConverters/SmoothSISO.mo new file mode 100644 index 0000000..6bfc219 --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialConverters/SmoothSISO.mo @@ -0,0 +1,10 @@ +within BusinessSimulation.Interfaces.PartialConverters; + +partial block SmoothSISO "Smooth-like converter" + extends Basics.GenericSmooth; + Connectors.RealInput u "Input" annotation(Placement(visible = true, transformation(origin = {-145, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-93.624, 0}, extent = {{-10, 10}, {10, -10}}, rotation = 0))); + replaceable RealOutput y annotation(Placement(visible = true, transformation(origin = {160, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {100, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial block extending from →GenericSmooth with a Real input and a Real output connector.

"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end SmoothSISO; diff --git a/BusinessSimulation/Interfaces/PartialConverters/package.mo b/BusinessSimulation/Interfaces/PartialConverters/package.mo new file mode 100644 index 0000000..345e087 --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialConverters/package.mo @@ -0,0 +1,12 @@ +within BusinessSimulation.Interfaces; + +package PartialConverters "Partial converter classes" + extends Icons.VariantsPackage; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This package contains partial classes to build →Converters.

+
+
+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+"), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end PartialConverters; diff --git a/BusinessSimulation/Interfaces/PartialConverters/package.order b/BusinessSimulation/Interfaces/PartialConverters/package.order new file mode 100644 index 0000000..7be10b1 --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialConverters/package.order @@ -0,0 +1,22 @@ +SO +SISO +SI2SO +SI3SO +MO +MISO +MIMO +MIMO_nin +BooleanSO +BooleanSISO +BooleanSIRealSO +BooleanMISO +SIBooleanSO +SI2BooleanSO +BooleanSI2SO +SmoothSISO +InformationSource_SO +InformationSource_MO +InformationProcessing_SO +InformationProcessing_MO +Policy_SO +Policy_MO diff --git a/BusinessSimulation/Interfaces/PartialFlows/BidirectionalFlow.mo b/BusinessSimulation/Interfaces/PartialFlows/BidirectionalFlow.mo new file mode 100644 index 0000000..5703c61 --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialFlows/BidirectionalFlow.mo @@ -0,0 +1,41 @@ +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, portA.stopInflow, portA.stopOutflow); + pre(useB_rate) = Functions.constrainedRateBoolean(B_rate, 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, portA.stopInflow, portA.stopOutflow); + useB_rate = Functions.constrainedRateBoolean(B_rate, 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; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial model extending from the →GenericFlow base class. This is a generic class for bi-directional flow components where the value for the rate at port A (A_rate) can be set by an equation.

+

Notes

+ +"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end BidirectionalFlow; diff --git a/BusinessSimulation/Interfaces/PartialFlows/Interaction.mo b/BusinessSimulation/Interfaces/PartialFlows/Interaction.mo new file mode 100644 index 0000000..5302a79 --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialFlows/Interaction.mo @@ -0,0 +1,38 @@ +within BusinessSimulation.Interfaces.PartialFlows; + +partial model Interaction "Describes two separate flows to or from sinks or sources" + import BusinessSimulation.Units.Rate; + extends Basics.GenericFlow; + extends Basics.Interaction4SO; + extends Icons.Interaction; +protected + // positive rates will fill the conected stock (think of the rates as A's and B's inflow!) + // indicated rates (may be overriden by stock restrictions) + Rate A_rate "Indicated rate for portA"; + Rate B_rate "Indicated rate for portB"; + // acutal rates + Rate setA_rate "Rate to be used for portA meeting the constraints imposed by the stock"; + Rate setB_rate "Rate to be used for portB meeting the constraints imposed by the stock"; +equation + // Children of this class need to procvide eplicit equations for A_rate and B_rate + // make sure that stock constraints are met + // positive values for A_rate and/or B_rate mean, that the connected stock will be filled + setA_rate = Functions.constrainedRate(-A_rate, portA.stopInflow, portA.stopOutflow); + setB_rate = Functions.constrainedRate(-B_rate, portB.stopInflow, portB.stopOutflow); + // set flow to zero if constraints are not met + portA.rate = setA_rate; + portB.rate = setB_rate; + // report the rate of flow at Port A + y_A = -portA.rate; + y1_A = -portA.rate; + y_B = -portB.rate; + y1_B = -portB.rate; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial model extending from the →GenericFlow base class. This is a generic class for interactional flow components where the values for the rates at port A (A_rate) and B (B_rate) can be set by equations. Positive rates will fill the connected stocks, while negative rates will drain them.

+

Notes

+ +"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Interaction; diff --git a/BusinessSimulation/Interfaces/PartialFlows/UnidirectionalFlow.mo b/BusinessSimulation/Interfaces/PartialFlows/UnidirectionalFlow.mo new file mode 100644 index 0000000..069e13e --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialFlows/UnidirectionalFlow.mo @@ -0,0 +1,42 @@ +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, portA.stopInflow, portA.stopOutflow) and A_rate > 0; + pre(useB_rate) = Functions.constrainedRateBoolean(B_rate, 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, portA.stopInflow, portA.stopOutflow) and A_rate > 0; + useB_rate = Functions.constrainedRateBoolean(B_rate, 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; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial model extending from the →GenericFlow base class. This is a generic class for unidirectional flow components where the value for the rate at port A (A_rate) can be set by an equation. The rate has to be positive; negative values will cause a warning.

+

Notes

+ + +"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end UnidirectionalFlow; diff --git a/BusinessSimulation/Interfaces/PartialFlows/package.mo b/BusinessSimulation/Interfaces/PartialFlows/package.mo new file mode 100644 index 0000000..8fec43b --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialFlows/package.mo @@ -0,0 +1,11 @@ +within BusinessSimulation.Interfaces; + +package PartialFlows "Partial models for flow elements" + extends Icons.VariantsPackage; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This package contains partial classes to build →Flows.

+

+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+"), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end PartialFlows; diff --git a/BusinessSimulation/Interfaces/PartialFlows/package.order b/BusinessSimulation/Interfaces/PartialFlows/package.order new file mode 100644 index 0000000..5e972e8 --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialFlows/package.order @@ -0,0 +1,3 @@ +UnidirectionalFlow +BidirectionalFlow +Interaction diff --git a/BusinessSimulation/Interfaces/PartialSourcesOrSinks/Sink.mo b/BusinessSimulation/Interfaces/PartialSourcesOrSinks/Sink.mo new file mode 100644 index 0000000..798f9db --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialSourcesOrSinks/Sink.mo @@ -0,0 +1,24 @@ +within BusinessSimulation.Interfaces.PartialSourcesOrSinks; + +partial model Sink "Outflow to a stock with infinity capacity" + extends Basics.GenericSourceOrSink; + extends Icons.Sink; +protected + // a positive rate should drain the stock (which here matches Modelica's rule for flows) + OutputType rate(min = 0); +equation + // observe stock signals and constraints + assert(rate >= 0, "Rate must be positive and will be set to zero", level = AssertionLevel.warning); + massPort.rate = Functions.constrainedRate(max(rate, 0), massPort.stopInflow, massPort.stopOutflow); + // report current rate of flow via output connectors + // so that it may be used directly as exogenous rate by another sink element (e.g. positive rate!) + y = massPort.rate; + y1 = massPort.rate; + y2 = massPort.rate; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial model extending from the →GenericSourceOrSink base class. This partial class can be used to model Sink components using equations to assign a value to the Real variable rate.

+

Notes

+

Only positive values should be assigned to rate and accordingly negative values will cause a warning.

+"), __Wolfram(itemFlippingEnabled = true), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Sink; diff --git a/BusinessSimulation/Interfaces/PartialSourcesOrSinks/Source.mo b/BusinessSimulation/Interfaces/PartialSourcesOrSinks/Source.mo new file mode 100644 index 0000000..2ec0cc7 --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialSourcesOrSinks/Source.mo @@ -0,0 +1,25 @@ +within BusinessSimulation.Interfaces.PartialSourcesOrSinks; + +partial model Source "Inflow from a stock with infinite capacity" + extends Basics.GenericSourceOrSink; + extends Icons.Source; +protected + // a positive rate will fill the stock - the elements rate should thus be negative following Modelica's rule for rates + OutputType rate(min = 0); +equation + assert(rate >= 0, "Rate must be positive", level = AssertionLevel.warning); + // switch signs for setting the rate in accordance with Modelica's rule for rates + // observe stock signals and constraints + massPort.rate = Functions.constrainedRate(-max(rate, 0), massPort.stopInflow, massPort.stopOutflow); + // report current rate of flow via output connectors + // so that it may be used directly as exogenous rate by another source element (e.g. positive rate) + y = -massPort.rate; + y1 = -massPort.rate; + y2 = -massPort.rate; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial model extending from the →GenericSourceOrSink base class. This partial class can be used to model Source components using equations to assign a value to the Real variable rate.

+

Notes

+

Only positive values should be assigned to rate and accordingly negative values will cause a warning.

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {0, 128, 0}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-100, -100}, {100, 100}}), Line(visible = true, origin = {21.584, -10}, points = {{-48.416, 0}, {48.416, 0}}, color = {0, 128, 0}, thickness = 5), Line(visible = true, origin = {19.213, 8.274}, points = {{-46.013, 0}, {46.013, 0}}, color = {0, 128, 0}, thickness = 5), Rectangle(visible = true, origin = {-59.838, 0}, lineColor = {255, 0, 0}, fillColor = {255, 255, 255}, lineThickness = 2.5, extent = {{-32.838, -32.117}, {32.838, 32.117}}), Polygon(visible = true, origin = {72.114, -0.25}, rotation = -450, lineColor = {0, 128, 0}, fillColor = {0, 128, 0}, fillPattern = FillPattern.Solid, points = {{-22.295, -7.943}, {22.191, -7.943}, {0.104, 15.886}}), Ellipse(visible = true, origin = {21.899, 0}, lineColor = {0, 128, 0}, fillColor = {0, 128, 0}, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-15.107, -15.107}, {15.107, 15.107}}), Text(visible = true, origin = {22.487, 1}, textColor = {255, 255, 255}, extent = {{-16.513, -12.307}, {16.513, 12.307}}, textString = "X", textStyle = {TextStyle.Bold}), Line(visible = true, origin = {-59.639, -1.461}, points = {{-19.013, -1.251}, {-19.013, 5.61}, {-13.146, 10.097}, {-4.518, 6.3}, {3.107, -1.637}, {9.976, -6.855}, {16.533, -6.855}, {19.639, -3.018}, {19.639, 4.92}, {13.107, 11.132}, {6.525, 8.716}, {3.107, 3.145}, {-4.173, -6.855}, {-14.872, -8.539}, {-19.013, -1.251}, {-19.013, -1.251}}, color = {255, 0, 0}, thickness = 3, smooth = Smooth.Bezier)}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Source; diff --git a/BusinessSimulation/Interfaces/PartialSourcesOrSinks/SourceOrSink.mo b/BusinessSimulation/Interfaces/PartialSourcesOrSinks/SourceOrSink.mo new file mode 100644 index 0000000..0c70c24 --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialSourcesOrSinks/SourceOrSink.mo @@ -0,0 +1,23 @@ +within BusinessSimulation.Interfaces.PartialSourcesOrSinks; + +partial model SourceOrSink "Source or sink with regard to a connected stock" + extends Basics.GenericSourceOrSink; + extends Icons.SourceOrSink; +protected + // positive rate should fill the connected stock stock; negative rate should drain it + OutputType rate; +equation + // switch signs in accordance with Modelica's rule for rates + // observe constraining signals from stock + massPort.rate = Functions.constrainedRate(-rate, massPort.stopInflow, massPort.stopOutflow); + // report current rate of flow via output connectors so that it can be used as exogenous input for another source or sink (e.g. switch signs!) + y = -massPort.rate; + y1 = -massPort.rate; + y2 = -massPort.rate; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Partial model extending from the →GenericSourceOrSink base class. This partial class can be used to model SourceOrSink components using equations to assign a value to the Real variable rate.

+

Notes

+

A positive value for rate will fill the connected stock; the reported rate (y, y1, y2) will follow this convention.

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end SourceOrSink; diff --git a/BusinessSimulation/Interfaces/PartialSourcesOrSinks/package.mo b/BusinessSimulation/Interfaces/PartialSourcesOrSinks/package.mo new file mode 100644 index 0000000..ae8aa6c --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialSourcesOrSinks/package.mo @@ -0,0 +1,11 @@ +within BusinessSimulation.Interfaces; + +package PartialSourcesOrSinks "Partial models for sources or sinks" + extends Icons.VariantsPackage; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This package contains partial classes to build →SourcesOrSinks components.

+

+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+"), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end PartialSourcesOrSinks; diff --git a/BusinessSimulation/Interfaces/PartialSourcesOrSinks/package.order b/BusinessSimulation/Interfaces/PartialSourcesOrSinks/package.order new file mode 100644 index 0000000..3a2a166 --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialSourcesOrSinks/package.order @@ -0,0 +1,3 @@ +Source +Sink +SourceOrSink diff --git a/BusinessSimulation/Interfaces/PartialStocks/BasicStock.mo b/BusinessSimulation/Interfaces/PartialStocks/BasicStock.mo new file mode 100644 index 0000000..015d07c --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialStocks/BasicStock.mo @@ -0,0 +1,49 @@ +within BusinessSimulation.Interfaces.PartialStocks; + +partial model BasicStock "Unrestricted reservoir to store information" + import BusinessSimulation.Constants.inf; + import BusinessSimulation.Types.InitializationOptions; + extends Icons.Stock; + extends Interfaces.Basics.GenericStock(hasStockInfoOutput = false, y.start = initialValue, init = modelSettings.init); + parameter OutputType initialValue(min = minValue, max = maxValue) = 0 "Initial level (should be different from 0 to find non-trivial steady state solution)"; + parameter OutputType maxValue = inf "Maximum admissable value"; + parameter OutputType minValue = -inf "Minimum admissable value"; + parameter Boolean useAssert = false "= true, if leaving the admissable range is to cause an error or warning" annotation(Evaluate = true, Dialog(tab = "Advanced")); + parameter Boolean causeError = true "= true, if leaving the admissable range is to cause an error instead of simply a warning" annotation(Evaluate = true, Dialog(tab = "Advanced")); + outer ModelSettings modelSettings; +protected + Sensors.StockInfo stockInfoSensor if hasStockInfoOutput annotation(Placement(visible = true, transformation(origin = {0, -60}, extent = {{-10, 10}, {10, -10}}, rotation = 0))); + OutputType x(start = initialValue, min = minValue, max = maxValue) "State variable" annotation(Dialog(enable = false, tab = "Initialization")); + Converters.Special.RangeAssert rangeControl(maxValue = maxValue, minValue = minValue, causeError = causeError) if useAssert "Use assert() to check admissable values" annotation(Placement(visible = true, transformation(origin = {70, 70}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); +initial equation + // initialize the stock by finding a valid initial value, by using a given initialValue, or by trying to find a steady state solution + if init == InitializationOptions.FixedValue then + x = initialValue; + elseif init == InitializationOptions.SteadyState then + der(x) = 0; + end if; +equation + // rate of change for the stock + der(x) = inflow.rate + outflow.rate; + // ports shall have level information for stock + inflow.stock = x; + outflow.stock = x; + // children of this class need to set the boolean flags for inflow and outflow ports: + // inflow.stopInflow = true | false; + // outflow.stopInflow = true | false; + // inflow.stopOutflow = true | false; + // outflow.stopOutflow = ture | false; + // report current value of stock via output connectors + y = inflow.stock; + y1 = inflow.stock; + y2 = inflow.stock; + connect(inflow, stockInfoSensor.inPort) annotation(Line(visible = true, origin = {-71.5, -30}, points = {{-88.5, 30}, {11.5, 30}, {11.5, -30}, {65.5, -30}}, color = {128, 0, 128})); + connect(stockInfoSensor.outPort, outflow) annotation(Line(visible = true, origin = {71.5, -30}, points = {{-65.5, -30}, {-11.5, -30}, {-11.5, 30}, {88.5, 30}}, color = {128, 0, 128})); + connect(y, stockInfoSensor.levelInfo) annotation(Line(visible = true, origin = {80, 14}, points = {{80, 16}, {80, 26}, {-80, 26}, {-80, -68}}, color = {1, 37, 163})); + connect(stockInfoSensor.y_stockInfo, y_stockInfo) annotation(Line(visible = true, origin = {53.333, -75.333}, points = {{-53.333, 9.333}, {-53.333, -4.667}, {106.667, -4.667}}, color = {128, 0, 128})); + // issue warnings if values out of range + connect(y, rangeControl.u) annotation(Line(visible = true, origin = {119.6, 54}, points = {{40.4, -24}, {40.4, -4}, {-19.6, -4}, {-19.6, 16}, {-41.6, 16}}, color = {1, 37, 163})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This is the general, unrestricted reservoir of the System Dynamics methodology, it accumulates information transported by flow components connected to the StockPorts.

"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, -80}, textColor = {0, 0, 128}, extent = {{-100, -6}, {100, 6}}, textString = "%initialValue", fontName = "Lato")}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end BasicStock; diff --git a/BusinessSimulation/Interfaces/PartialStocks/package.mo b/BusinessSimulation/Interfaces/PartialStocks/package.mo new file mode 100644 index 0000000..e0669ce --- /dev/null +++ b/BusinessSimulation/Interfaces/PartialStocks/package.mo @@ -0,0 +1,11 @@ +within BusinessSimulation.Interfaces; + +package PartialStocks "Partial models for reservoir components (stocks or levels)" + extends Icons.VariantsPackage; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This package contains partial classes to build →Stocks.

+

+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+")); +end PartialStocks; diff --git a/BusinessSimulation/Interfaces/package.mo b/BusinessSimulation/Interfaces/package.mo new file mode 100644 index 0000000..65fc77b --- /dev/null +++ b/BusinessSimulation/Interfaces/package.mo @@ -0,0 +1,12 @@ +within BusinessSimulation; + +package Interfaces "Connectors and partial models for Business Simulations" + extends Icons.InterfacesPackage; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This package contains connectors and partial models (classes).

+
+
+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Interfaces; diff --git a/BusinessSimulation/Interfaces/package.order b/BusinessSimulation/Interfaces/package.order new file mode 100644 index 0000000..d8f06c7 --- /dev/null +++ b/BusinessSimulation/Interfaces/package.order @@ -0,0 +1,6 @@ +Connectors +Basics +PartialConverters +PartialSourcesOrSinks +PartialFlows +PartialStocks diff --git a/BusinessSimulation/ModelSettings.mo b/BusinessSimulation/ModelSettings.mo new file mode 100644 index 0000000..1221f73 --- /dev/null +++ b/BusinessSimulation/ModelSettings.mo @@ -0,0 +1,40 @@ +within BusinessSimulation; + +model ModelSettings "Setting important global variables within a model" + extends Icons.ConverterName; + // imports + import BusinessSimulation.Types.InitializationOptions; + import BusinessSimulation.Constants.small; + import BusinessSimulation.Units.Time; + import BusinessSimulation.Types.TimeBases; + // set model time by changing the rhs of the following definition + parameter TimeBases modelDisplayTimeBase = TimeBases.seconds "The model's time base with regard to input and output" annotation(Evaluate = true, Dialog(group = "Model Time Settings")); + // modelDisplayTimeBase is used to lookup unit strings in some components and thus must have constant variability in SystemModeler + parameter Time modelTimeHorizon(min = small) = 10 "The time horizon for the model (i.e. stopTime - startTime)" annotation(Dialog(group = "Model Time Settings")); + parameter Time modelStartTime(fixed = false) "Start time of the model (will be automatically determined)" annotation(Dialog(tab = "Initialization", enable = false)); + parameter Time modelStopTime(fixed = false) "Stop time of the model (will be determined from startTime and modelTimeHorizon)" annotation(Dialog(tab = "Initialization", enable = false)); + // inner constant String modelDisplayTimeUnit = BusinessSimulation.Constants.timeBaseUnits[modelDisplayTimeBase] "The global setting for 'displayUnit' of time vars" annotation(Evaluate = true); + parameter Time dt(min = 0) = 0.25 "Smallest possible interval of time for compatibility with conventional fixed-step System Dynamics models" annotation(Dialog(group = "Model Time Settings")); + parameter Time samplingPeriod(min = 0) = dt / 4 "Default sampling period for discrete model components (should be ≤ dt/4)" annotation(Evaluate = true, Dialog(group = "Model Time Settings")); + parameter Boolean gaming = false "= true, if gaming mode is to be activated" annotation(Evaluate = true, Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Dialog(group = "Model Input Settings")); + // file names for exogenous data + parameter String lookupDataFileURI = "LookupData.txt" "URI for the lookup data file" annotation(Dialog(group = "Data Sources")); + parameter String exogenousDataFileURI = "ExogenousData.txt" "URI for the exogenous data file" annotation(Dialog(group = "Data Sources")); + parameter String modelDisplayTimeUnit = BusinessSimulation.Constants.timeBaseUnits[modelDisplayTimeBase] "Unit string according to modelDisplayTimeBase choice" annotation(Evaluate = true, Dialog(enable = false, tab = "Initialization")); + // advanced options + parameter InitializationOptions init = BusinessSimulation.Types.InitializationOptions.FixedValue "Provide InitializationOptions (Free, FixedValue, SteadyState) as global default" annotation(Evaluate = true, Dialog(tab = "Advanced")); +initial equation + // store the model's startTime + modelStartTime = time; + modelStopTime = modelStartTime + abs(modelTimeHorizon); +equation + assert(dt > small, "dt must be greater than zero"); + assert(samplingPeriod > small, "samplingPeriod must be greater than zero"); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This class should be placed in the top level scope of any simulation model. It will automatically be assigned the prefex inner as it provides global parameters for the model.

+"), defaultComponentName = "modelSettings", defaultComponentPrefixes = "inner", missingInnerMessage = "No \"modelSettings\" component is defined.", Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {192, 192, 192}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 1, extent = {{-50, -50}, {50, 50}}), Bitmap(visible = true, fileName = "", imageSource = "/9j/4AAQSkZJRgABAQEAeAB4AAD/4QCCRXhpZgAASUkqAAgAAAADADEBAgA0AAAAMgAAADIBAgAUAAAAZgAAACqIBAABAAAAAgAAAAAAAABDcmVhdGVkIHdpdGggdGhlIFdvbGZyYW0gTGFuZ3VhZ2UgOiB3d3cud29sZnJhbS5jb20AMjAyMDoxMDowMSAxOTozMzo0MAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAJZAlkDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD3+iiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoopGZUUszBQO5OKAFoqL7TB/z2j/76FS0AFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFMkljiGZHVfqetPrJ1ZyZo04wFz+f/6qALD6pApIUO3oQMA1A+rOR8kSg+5zWdRQBbbUblmJDhR6BRUJupySTNJz6MRUVFACszOxZmLE9yc0lFFABW5p8zTWoLkllO3J71h1q6S5McqcYBB/P/8AVQBo0UUUAFFFFABRRRQAUUUUAFFVr26NrGpUAux4BqhFqkyH94FkH5GgDYoqnFqUEmAxKHj73T86tqyuoZWDA9wc0ALRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABWZq6/6ptvqCcfl/WtOqWqKWtAQOFYE/y/rQBjUUUUAFFFFABRRRQAVf0liJ3XPBXJH4//AF6oVb05it6gB4YEH8s/0oA26KKKACiiigAooooAKKKr30xhtWYHDH5RQBk30wmumYHKj5RVeiigAp0cjxPuRip9RTaKANCHVXUYlUP/ALQ4NaEN1DOBscZP8J4Nc/RQB01FYsGozRcP+8X/AGjz+dacF5DccI2G/utwaAJ6KKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigApCQoJJAA5JNQ3N3HbL8xy5GQo71j3N3Jct8xwgOQo7UAbiTRyHCSIx64DA0+udhmeCQOhwR+tbltcpcx7l4I+8vpQBNRRRQAUUUUAFFFFABVe9QvZSgY6Z59uasUyZDJDIgxllIGaAOcooooAKKKKACiiigAqezcpeREY+8Bz78VBTo38uVHxnawOKAOkopqOsiB0IKnoRTqACiiigAooooAKyNVl3TrGMfIOfqf8AIrWZgilmOABkmucdzJIznGWJJxQA2iiigAooooAKKKKACnwqWmjUMVJYAEdqZVzToPNud5+7Hz+Pb/PtQBtUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUU13WNC7kBR1JoAdWddakE+SAhj3bsPpVe8vmmYpESsY/Dd/9aqVACkliSSSTySaSiigAqW3uGtphIoB7EHuKiooA6RHWRA6EFT0Ip1ZGnXRjkELk7G4X2Na9ABRRRQAUUUySWOIZkdV+p60APorPm1VFOIlL/7R4FUZr6eYEM+1T/CvFAEBGCQCD7jvSUUUAFFFFABRRRQAUUUUAFSLPKihVldQOwYio6KAJ0vLhDkTP+Jz/OpE1K5U5LK3sV/wqpRQBopqzgfPEpPscVYj1SBvvbkOOcjI/SsaigDRv75JYhFESQeWOP0rOoooAKKKKACiiigAooooAK3bGEwWqhs7m+Yj0rKsYRNdKpGVHzGt6gAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigCOaZIIy7nAH61i3N3JckbsBR0UVNqnmfaV3fc2/L/X8f8A61UaACiiigAooooAKKKKACtnT7sTRiN2/eLxkn71Y1KCVIIJBHIIoA6WoJruGA4dxu/ujk1lSahcSIF3BfUrwTVWgC9canJJlYhsX17n/CqTMzsWZixPcnNJRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRSgZIBIHue1AGvpcWy2MnGXP6D/Jq9SKoRQqjAAwBS0AFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAV7y2FzAQPvryv+FYRBUkEEEcEGulqhqFmZf30Yy4HK+v/ANegDIooooAKKKKACiiigAooooAKKKQHKgkEE9j2oAWiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKAEIypAJBPcdqWiigC5a6g8ACPl4xwPUVrxSpMm+Ngy9K5ypIZ5IH3RsR6jsfrQB0VFVbW9S4AUkLL3X1+lWqACiiigAooqvc3cdsBuyWPRRQBLLKkKb5GCr0rNm1VicQoAPVupqlNM88hdzkn9KjoA3bS7W5TsJB1X+oqzXNo7RuHQkMOhFbtpci5hDcBxwwHagCeiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAyNQsxF++jGEJ5X0/+tVCulIDAggEHgg1hXlubecgA7Dyp9qAK9FFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAKCVIIJBHIIrVsr/AMw+VMRvP3W6Z9qyaKAOmorIs9Q8pRHNkoPut6f/AFqS51J5crDlE9f4qALd5fLCpSIhpD+O3/69ZDu0jl3JLHqTTaKACiiigAqSCZoJlkUnjqPUelR0UAdFDMk8YdDkH9KkrDsro28uGJ8pvvD0963KACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigArO1WRNix4Bk6g46CrN5dC1jBxl2+6Kw3dpHLuSWPUmgBtFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFIDkkc8cdKADPzAc5PPSloooAKKKKACiiigAooooAK1dMutw8hySRypJ7elZVKrFHDKcEHINAHS0VDazi4gDjr0YY6GpqACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoopskixRs7dFGaAHUVkHVZsnCRgdsg/41Zh1OKQ7ZAYz2JOR+dAF6ikVldQysGB7g5paACiiigAqOaZIIy7nAH608kKCSQAOSTWJfXP2mb5T+7XheP1oAhmmeeQu5yT+lR0UUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUU5EaRwiAlj0ArXs7FYVDygNIfx2//AF6ADTrZ4I2Z+C+Pl9Ku0UUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABWXqlyS32degwWP9K0pJFijZ26KM1zskjSyM7dWOaAG0UUUASRTSQtmNyp/nWhDquTiZAP9pe34Vl0UAdHHLHKMxurf +Q9KfXNAlSCCQRyCKtJqNyildwbjALDkf596ALWp3W0eQhIJ5Yg9vSsqlZi7lmOSTkmkoAKKKKACiiigAooooAKKKTnceBj1zQAtFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFG7d83rz0x+lFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABU1tayXTEKCFBwzEcD/ABqzY2HnIJZgyqcEJ3P1rWACgAAADgAUARQWsVuuEXnux6mpqKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAztVmwiwgnJ+Y/T/P8qyqmupjPcu+cjOF+lQ0AFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAhOBk59OBmloooAKKKKACiiigAooooAKKKKACiiigAooo3bufw6YoAVlKsQcZHoc0lFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUqttcNgHBzg9DSUUAdKrB1DKcgjINLWdpc+6NoT1Xlfp/n+daNABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFVr+XyrR+mW+UZ9//AK2as1latIfMjj5wBu69f84/WgDOooooAKKKKACiiigAooooAKKKKACkOdpwQD2JGaWigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoopScgdOPagBKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAkhlMMyyDqp6etdCCGAIIIPIIrmq2dMmMluUJyUOPw7f1oAu0UUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABWbqFnJJKZolB4+YA8/56VpUUAc0ysjFWUqR2IxSV0UsMcy4kQMP5VnzaUQCYXz/st/jQBm0VJLBLCf3kbL2z2/Oo6ACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigApSMAdOfekooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKt6fMYrpVJwr/Kf6VUpQSpBBII5BFAHS0UyKQSxJIMfMM8HOKczKilmYKB3JxQAtFQtd26qSZkwPQ5qF9Ttlxgs/+6On50AXKKzn1ZAfkiYj3OKhOqzZOEjA7ZB/xoA16Kr2l2LpWO3aVPIzmrFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFACEBgQQCDwQaqzafBKCVXY3qv+FW6KAMK6spLY55ZP7wH8/Sq1bepOFsmBz8xAH8/6ViUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFCjJAJA56+lFLztHPGTgZoASigAAAAYAooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAUMwUqGIB6jPWkoooAKKKKACiiigC7pcm26284dSMe/X/ABrZrn7Rit3EQcHcB+fFdBQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAZurPxFGCO5I/l/WsurmpuGvMDPyqAf5/wBap0AFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFDYK42k9iPWilGR8wOCD1zzQAHGTgkjtmkoooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAK6UEMAQQQeQRXNV0Fowa0iIORtA/LigCaiiigAooooAKKKKACiiigAooooAKKKKACiiigDBvXD3spGeuOfbiq9S3P8Ax9Tf75/nUVABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABSg4IIxx6jNJQMlgMgDB5NABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAVu6f/wAeMf4/zNYVbGlf8erf75/kKAL1FFFABRRRQAUUUUAFFFFABRSMyopZmCgdycVE13bqpJmTA9DmgCaiqj6lbKMhmb2C/wCNRtq0QU7Y3J9DgUAX6Ky21dip2wgH1LZqCXUZ5E25VPdMg0AVSSxJJJJ5JNJRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFJgYA5496WgAoopQcHoD9aAEooo5z7UAFFJnIBBGP50rBg2DwQeQRQAUUYOMkjBPFJzgcD35oAWjtj360DknJA9KMA4yOnSgAoo9eKDgEYyR/KgAooHzEgdvXiigAoo5z7UUAFFG5doXjduPOfyGKO+c/hQAUUUUAFFFFABRRSEAkE9jkUALRRRQADnOOcDJ9hRSgkAgE88H3pKACiiigAooooAKKKKACiiigAoopVVnYKqliewGaAEoqUWs5IAhk59VIqX+z7r/nl/48P8aAKtFXv7Kn/vx/mf8KmGkDIzMSO+F/8Ar0AZdbGlf8erf75/kKBpUAIJaQ+xI5/SriIsaBEACjoBQA6iiigAooooAKKKKACmTOY4ZHGMqpIzT6ZMhkhkQYyykDNAHPO7SOXcksepNNoooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigBScnt+ApKKKADAznHNLubOdxzjGc9ulJRQAUUUUAFLk4xk4HOKSigAooooAKKKKACiiigApQQA2RkkcHPSkooAQkKpJIAHJJ7UtFFABRRRQAUUUUAKTkknHPoMUlFFACg8HgHP6UhwcHaMgYzRRQAoJByCR24pKKKAAAAAAYAooooAKKKKACiiigAooooAKKKKACiiigAooooAK2tOjRbRHCje2ct36//WrFrdsARYxggjqefqaALNFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFAHM0VJOoSeRVGAGIA/Go6ACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACikJwRwTn9KWgAooooAKKKKACkz8xGR06UtOAAUE5OcjANADaKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACuhtv+PWH/cH8q56ulACgAAADgAUALRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQBhX4AvpAAB0PH0FVqv6spE6NjgrgH8f/r1QoAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAopAACSAATyfeloAKKKKACiiigAooooAKRscZK44/PP/wCqlpAck8jjt6UALRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQBNaKWu4gBk7gfy5roKxtLj3XW7nCKTn36f41s0AFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFAGfqyAwxvzkNj8//ANVZNdBdRGa1kjXqRx/OsQ2s4JBhk49FJoAioqwllcuMiJvx4/nUq6XcMoJKKfQmgClRWkNIOBmYA98L/wDXqb+yoP78n5j/AAoAx6K3Dp1qQQIyPcMeKyLiLyLh485APH0oAiooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigApwZTtDDCjqV602k4bcDgjpigBaKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKALNndm1c/KCrY3ev4VsxTxTD93Ird8d/yrnaUEqQQSCOQRQB0tFYkOoTxEBm3r6N/jV6HU4ZCA4MZPryPzoAu0UgIYAggg8giloAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigArL1aLmOUZ/un+Y/rWpUF3D59s6ADd1X60AYFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFA475oooAKKVhtYjnHbIxxSUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQBJFNJC2Y3Kn+daVvqauQsyhCf4h0/wDrVk0+KMyzJGM/MccDOKAOjooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigDCvoRBdMFxtb5gPSq1bWowebb7x96Pn8O/8An2rFoAKKKKACiiigApBnaMkE9yBilooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACikIBIJAJHI9qWgAooooAUksSSSSeSTSUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAVe0uLfcmTnCD9T/k1Rrc0+Ly7Rc5y/zH/P0xQBaooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigArAvIPs9yyD7p5X6VtzTxwJukYD0Hc/SsK4na4mMjcZ6DPQUARUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUgGCTzzz1oAWiiigAooooAKKKKACiiigAoopcHGcHA4zQAlFFFABRRRQAUUUUAS20JuJ1jGcHkn0FdDWdpcG2Npj1bhfp/n+VaNABRRRQAUUUUAFFFFABRRRQAUUUU +AFFFFABRRRQAUUUjMqKWZgoHcnFAC1Tur9IPlTDv6Z4H1/wqpd6i0mUhyq5+9nk/4VQoAfLK8z75GLN0plFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUASQQtPMsag89T6D1roI41ijVF6KMVWsbT7PHlwPMbr7D0q3QBWlsLeXHybD6pxVCbTJYxujIkHcAYP5VsUUAc0QVJBBBHBBpK6KWCKYfvI1btnv8AnWdNpTA5hcEejdaAM6nRxtLIqL1Y4p7W06Z3ROAOp28VoaZa7R57ggnhQR29aANBVCKFUYAGAKWiigAooooAKKKKACiiigAooooAKKKKACiiigAooooARmCKWY4AGSaw7u7a5fuIx0X+prbdBJGyHOGBBxXOyRtFIyN1U4oAbRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABWlptpki4cAj+Ae/rUFjafaJMuD5a9fc+lbQAUAAAAcACgBaKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKo6lbebH5yj50HPP8NXqKAOZoq7qFp5MnmIAI2PQdjVKgAooooAKKKKACiilVWdgqqWJ7AZoAbkbgMjJ5xS1al0+eKLzCFIHJAOSKq0AFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFT2tv9pnCZIXqxHpUFS287W8wkXnHUZ6igDfRFjQIgAUdAKdTUdZEDoQVPQinUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFADZI1ljZG6MMVg3Ns9tJtbkH7retdBUNzbJcx7W4I+63pQBz9FOdGjco4IYdQabQAUUVbtLFrkb2JWP17n6UAR29rJcuAoIXuxHArZgtYrdcIvPdj1NSIixoEQAKOgFOoAKzbzThgyQA56lP8ACtKigDmaK27uxW5O9SFk9ex+tY0kbxPtdSp9DQA2iiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKAL1heGJxFIw8s9z/Ca2K5mtTT7wFVgkOCOFJ7+1AGlRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAVru0W5TsJB0b+hrFMUglMRRt4/hAya6OigDNtdM2sHnIOOdg/rWiAFAAAAHAApaKACiiigAooooAKint47hdsi5x0PcVLRQBh3NjJbZb70f94VVrpqw7+OOO6Kx8DGSPQ0AVaKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACilALEAAkngAUhDK+0jGM5z1BoAKKKKACiiigAooooAKUEqQQSCOQRSUUAbdjd/aUKvjzF6+/vVuuetpjbzrIM4HBHqK6GgAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigBGYIpZjgAZJrnZZDLM8hz8xzyc4rW1OYx24QHBc4/Dv/SsagAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACip4rOebBWMgHHLcCr0OlKBmZyT6L0oAy1VnYKqliewGau2+mSSYaU7F9O5/wAK1IoY4VxGgUfzqSgCKG2itxiNQD3Y9TUF7ZLOpdBiUDjnGfrVyigDmiCpIIII4INJWjqNmEzPEqqp++BxyT1rOoAKKKKACiiigAopQCxAAJJ4AFa1np4iIklwX6heymgCOy09g6zTcY5Ve+fetOiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiq19ceRbnBw7cL/jQBk3k/2i5Zx90cL9KgoooAKKKKACiiigAooooAkhheeQIgyT+lXH0mQH5JEI98ip9Ki2wNIc/OePoP8mr9AGC9lcoMmJvw5/lUDKyMVZSpHYjFdLRQBzNFdE0ETsWaJGJ7lQaY9lbPjMKjH93j+VAGBRW7/Z9r/wA8v/Hj/jWTd2/2afYGyCMj6UAQUUUUAFFFFABRRRQAVs6dDGLVJNoLkk5I5HasatrTHLWmDj5WIH8/60AXKKKKACiiigAooooAQgMCCAQeCDWFd2xtptuSVPKmt6ori3W5iMbEjuCOxoA56ipJoXgkKOMEfrUdABUkMEk77Y1J9T2H1qxa6e84DvlIzyPU1sRxpEu1FCj0FAENrZpaqcHc56tirFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABWRqzEzoueAuQPx/wDrVr1WurJLohixVwMA9f0oAwqKnns5rfl1yv8AeXkVBQAUUUUAFFFFABSqpdwqjJJwBSVe0uLfcmTnCD9T/k0AayII41QZwoAGadRRQAUUUUAFFFFABWVqyYljfPVSMfT/APXWrWdqyExxPxgEj8//ANVAGVRRRQAUUUUAFFFFABWppDErKueAQQP8/Ssur+ksRO654K5I/H/69AGvRRRQAUUUUAFFFFABRRRQBBdWy3UYUnaQchsZqO30+KAhjl3HIJ6D8Kt0UAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFU59Ohl5T923+yOPyq5RQBhy2FxFj5N49U5qrXTVDNawzg70GT/EODQBz9FaUuknOYpB9H/wAapS200IzJGwHr1H50ARVvWUPkWqLg7j8zZ9TWXY2xnnUsp8teSccH2rcoAKKKKACiiigAooooAKp6mha0yMfKwJ/l/WrlV71C9lKBjpnn25oAwaKKKACiiigAooooAKs2BAvoySB1HP0NVqltv+PqH/fH86AOhooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigApsieZE6ZxuUjNOooA5mituXToZpWkJcFuSFxj+VM/sqD+/J+Y/woAx6K20022UYKs3uW/wqRLK2TOIVOf73P86AMCnpDJIMpG7DpkKTXQpHHHnYirnrtGKdQBiJptyxwVVfct/hVy103yZFkkcMR/CBxmr9FABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQB/9k= +", extent = {{-37.404, -37.404}, {37.404, 37.404}}), Ellipse(visible = true, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-20, -20}, {20, 20}}), Text(visible = true, textColor = {128, 128, 128}, extent = {{-54.133, -12}, {54.133, 12}}, textString = "SETTINGS", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end ModelSettings; diff --git a/BusinessSimulation/MoleculesOfStructure/Actuators/Diffusion.mo b/BusinessSimulation/MoleculesOfStructure/Actuators/Diffusion.mo new file mode 100644 index 0000000..dfebab4 --- /dev/null +++ b/BusinessSimulation/MoleculesOfStructure/Actuators/Diffusion.mo @@ -0,0 +1,142 @@ +within BusinessSimulation.MoleculesOfStructure.Actuators; + +model Diffusion "Social diffusion via direct contacts and/or a basic conversion rate" + extends Icons.SubsystemActuator; + import BusinessSimulation.Units.{Rate,People}; + Interfaces.Connectors.FlowPort portA "Port connected to stock of potential adopters" annotation(Placement(visible = true, transformation(origin = {-180, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-100, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.FlowPort portB "Port connected to stock of adopters" annotation(Placement(visible = true, transformation(origin = {180, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {100, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + DataOutPort dataOut "Expandable connector for output" annotation(Placement(visible = true, transformation(origin = {180, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {50, 104}, extent = {{-10, -10}, {10, 10}}, rotation = -270))); + DataInPort dataIn if not (hasConstantOtherAdopters and hasConstantOtherPopulation and hasConstantContactRate and hasConstantFractionalAdoptionRate and hasConstantAdoptionFraction) "Expandable connector for input" annotation(Placement(visible = true, transformation(origin = {-175, 90}, extent = {{-10, -10}, {10, 10}}, rotation = -360), iconTransformation(origin = {-50, 100}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + parameter People otherAdopters = 0 "Other adopters involved in influencing potential adopters" annotation(Dialog(enable = hasConstantOtherAdopters)); + parameter People otherPopulation = 0 "Other potential contacts that are neighter adopters or potential adopters" annotation(Dialog(enable = hasConstantOtherPopulation)); + parameter Rate contactRate = 0 "Social contacts per person per period for adopters" annotation(Dialog(enable = hasConstantContactRate)); + parameter Rate fractionalAdoptionRate = 0 "Basic conversion rate independent from social contacts" annotation(Dialog(enable = hasConstantFractionalAdoptionRate)); + parameter Real adoptionFraction = 0 "Fraction of social contacts that will result in adoption" annotation(Dialog(enable = hasConstantAdoptionFraction)); + parameter Boolean hasConstantOtherAdopters = false "= true, if other adopters are given by the parameter and not by the continuous input" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean hasConstantOtherPopulation = false "= true, if other population is given by the parameter and not by the continuous input" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean hasConstantContactRate = false "= true, if the rate of social contacts is given by the parameter and not by the continuous input" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean hasConstantFractionalAdoptionRate = false "= true, if the fractional adoption rate is given by the parameter and not by the continuous input" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean hasConstantAdoptionFraction = false "= true, if true the adoption fraction is given by the parameter and not by the continuous input" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean nextStageIsInfluencing = true "= true, if true the next stage (adopters) are influencing potential adopters" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + + expandable connector DataOutPort "Output connector" + extends Icons.DataOutPort; + import BusinessSimulation.Units.Rate; + Rate conversionRate "Rate of conversion from social interaction"; + Rate adoptionRate "Rate of adoption independent of social interaction"; + Rate totalAdoptionRate "Total rate of adoption as a sum of conversion and independent adoption"; + end DataOutPort; + + expandable connector DataInPort "Input connector" + extends Icons.DataInPort; + import BusinessSimulation.Units.{People,Rate}; + People otherPopulation "Other potential contacts that are neighter adopters or potential adopters"; + People otherAdopters "Other adopters involved in influencing potential adopters"; + Rate fractionalAdoptionRate "Basic adoption rate independent from social contacts"; + Rate adoptionFraction "Fraction of social contacts with potential adopters that will result in adoption"; + Rate contactRate "Social contacts per person per period for adopters"; + end DataInPort; +protected + Converters.Add_2 totalAdopters "Sum of adopters and other adopters" annotation(Placement(visible = true, transformation(origin = {100, 45}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Converters.Add_3 totalPotentialContacts "Total population with regard to potential contacts for adopters" annotation(Placement(visible = true, transformation(origin = {-130, 30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Add_2 adjustedTotalAdopters "Depending on whether they influence or not the next stage (adopters) has to be added" annotation(Placement(visible = true, transformation(origin = {51.737, 15}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Converters.Gain adoptersNotInfluencing(c = 0) if not nextStageIsInfluencing annotation(Placement(visible = true, transformation(origin = {160, 27.723}, extent = {{-10, -10}, {10, 10}}, rotation = -270))); + Converters.PassThrough adoptersInfluencing if nextStageIsInfluencing annotation(Placement(visible = true, transformation(origin = {140, 27.723}, extent = {{-10, -10}, {10, 10}}, rotation = -270))); + Converters.ConstantConverter doNotAddAdopters(value = 0) if nextStageIsInfluencing "Do not add adopters to popoulation as they are already included" annotation(Placement(visible = true, transformation(origin = {105, -20}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Converters.PassThrough addAdoptersToPopulation if not nextStageIsInfluencing "Adopters are not influencing and thus have to be added to potential contacts" annotation(Placement(visible = true, transformation(origin = {105, 15}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Sensors.FlowPortSensor potentialAdopters "Potential Adopters as given by stock connected to port A" annotation(Placement(visible = true, transformation(origin = {-150, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Sensors.FlowPortSensor adopters "Level of adopters as given by stock connected to port B" annotation(Placement(visible = true, transformation(origin = {140, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Flows.Unidirectional.Transition converting "Conversion of potential adopters to adopters" annotation(Placement(visible = true, transformation(origin = {-0, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ConstantConverter parOtherPopulation(value = otherPopulation) if hasConstantOtherPopulation "Constant opther population (optional)" annotation(Placement(visible = true, transformation(origin = {-145, 70}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.PassThrough u_otherPopulation if not hasConstantOtherPopulation "Continuous input of other population (neither adopter nor potential adopter)" annotation(Placement(visible = true, transformation(origin = {-160, 70}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.Division potAdoptConcentration "Concentration of potential adopters" annotation(Placement(visible = true, transformation(origin = {-86.592, 50}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.PassThrough u_ContactRate if not hasConstantContactRate "Rate of social contacts for adopters" annotation(Placement(visible = true, transformation(origin = {90, 70}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.ConstantConverterRate parContactRate(value = contactRate) if hasConstantContactRate "Social contact rate for adopters (people per people per period)" annotation(Placement(visible = true, transformation(origin = {108.491, 75}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.Product_2 contactsAdopters "Contacts with adopters per period" annotation(Placement(visible = true, transformation(origin = {50, 50}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Converters.Product_2 contactsWithPotAdopt "Contacts of adopters with potential adopters" annotation(Placement(visible = true, transformation(origin = {-10, 30}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.PassThrough u_AdoptionFraction if not hasConstantAdoptionFraction "Conversion propability for interaction of potential adopters with adopters" annotation(Placement(visible = true, transformation(origin = {-0, 70}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.Product_2 conversionRate "Rate of conversion" annotation(Placement(visible = true, transformation(origin = {-5, -5}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.PassThrough u_FractAdoptRate if not hasConstantFractionalAdoptionRate "Continuous fractional adoption rate" annotation(Placement(visible = true, transformation(origin = {-50, 70}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Flows.Unidirectional.ProportionalTransition adopting(fractionalRate = fractionalAdoptionRate, hasConstantRate = hasConstantFractionalAdoptionRate) "Conversion independent from social contacts" annotation(Placement(visible = true, transformation(origin = {-45, -70}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ConstantConverter parAdoptionFraction(value = adoptionFraction) if hasConstantAdoptionFraction "Constant adoption fraction (optional)" annotation(Placement(visible = true, transformation(origin = {20, 75}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.Add_2 totalAdoptionRate annotation(Placement(visible = true, transformation(origin = {55, -55}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ConstantConverter parOtherAdopters(value = otherAdopters) if hasConstantOtherAdopters "Constant opther adopters (optional)" annotation(Placement(visible = true, transformation(origin = {160, 80}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.PassThrough u_otherAdopters if not hasConstantOtherAdopters "Continuous input of other adopters envolved in influencing potential adopters" annotation(Placement(visible = true, transformation(origin = {140, 70}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.ConstantConverterRate parFractAdoptRate(value = fractionalAdoptionRate) if hasConstantFractionalAdoptionRate "Constant fractinal adoption rate (optional)" annotation(Placement(visible = true, transformation(origin = {-30, 70}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); +equation + connect(portA, potentialAdopters.flowPort) annotation(Line(visible = true, origin = {-165, 0}, points = {{-15, 0}, {15, -0}}, color = {128, 0, 128})); + connect(portA, converting.portA) annotation(Line(visible = true, origin = {-107.641, -40}, points = {{-72.359, 40}, {-42.359, 40}, {-42.359, 0}, {97.641, 0}}, color = {128, 0, 128})); + connect(converting.portB, portB) annotation(Line(visible = true, origin = {109.157, -26.667}, points = {{-99.157, -13.333}, {30.843, -13.333}, {30.843, 26.667}, {70.843, 26.667}}, color = {128, 0, 128})); + connect(adopters.flowPort, portB) annotation(Line(visible = true, origin = {160, -0}, points = {{-20, 0}, {20, -0}}, color = {128, 0, 128})); + connect(potentialAdopters.stock, potAdoptConcentration.u1) annotation(Line(visible = true, origin = {-131.498, 40.333}, points = {{-18.453, -29.333}, {-18.453, 14.667}, {36.906, 14.667}}, color = {1, 37, 163})); + connect(u_ContactRate.y, contactsAdopters.u1) annotation(Line(visible = true, origin = {79.333, 57.546}, points = {{10.667, 5.092}, {10.667, -2.546}, {-21.333, -2.546}}, color = {1, 37, 163})); + connect(parContactRate.y, contactsAdopters.u1) annotation(Line(visible = true, origin = {91.661, 60}, points = {{16.83, 10}, {16.83, -5}, {-33.661, -5}}, color = {1, 37, 163})); + connect(potAdoptConcentration.y, contactsWithPotAdopt.u2) annotation(Line(visible = true, origin = {-36.41, 46}, points = {{-42.819, 4}, {21.41, 4}, {21.41, -8}}, color = {1, 37, 163})); + connect(contactsAdopters.y, contactsWithPotAdopt.u1) annotation(Line(visible = true, origin = {10.879, 46}, points = {{31.758, 4}, {-15.879, 4}, {-15.879, -8}}, color = {1, 37, 163})); + connect(contactsWithPotAdopt.y, conversionRate.u2) annotation(Line(visible = true, origin = {-10, 12.5}, points = {{0, 9.5}, {0, -9.5}}, color = {1, 37, 163})); + connect(u_FractAdoptRate.y, adopting.u) annotation(Line(visible = true, origin = {-50, 1.319}, points = {{0, 61.319}, {0, -61.319}}, color = {1, 37, 163})); + connect(adopting.portA, portA) annotation(Line(visible = true, origin = {-83.75, -35.596}, points = {{28.75, -34.404}, {-66.25, -34.404}, {-66.25, 35.596}, {-96.25, 35.596}}, color = {128, 0, 128})); + connect(adopting.portB, portB) annotation(Line(visible = true, origin = {91.25, -35}, points = {{-126.25, -35}, {48.75, -35}, {48.75, 35}, {88.75, 35}}, color = {128, 0, 128})); + connect(u_AdoptionFraction.y, conversionRate.u1) annotation(Line(visible = true, origin = {0, 32.5}, points = {{0, 29.5}, {0, -29.5}}, color = {1, 37, 163})); + connect(parAdoptionFraction.y, conversionRate.u1) annotation(Line(visible = true, origin = {10, 48.131}, points = {{10, 20.869}, {10, 9.131}, {-10, 9.131}, {-10, -45.131}}, color = {1, 37, 163})); + connect(conversionRate.y, converting.u) annotation(Line(visible = true, origin = {-5, -21.5}, points = {{0, 8.5}, {0, -8.5}}, color = {1, 37, 163})); + connect(converting.y1, totalAdoptionRate.u1) annotation(Line(visible = true, origin = {22.125, -47.5}, points = {{-11.625, 2.5}, {-6.625, 2.5}, {-6.625, -2.5}, {24.875, -2.5}}, color = {1, 37, 163})); + connect(u_otherAdopters.y, totalAdopters.u1) annotation(Line(visible = true, origin = {129.333, 54}, points = {{10.667, 8}, {10.667, -4}, {-21.333, -4}}, color = {1, 37, 163})); + connect(parOtherAdopters.y, totalAdopters.u1) annotation(Line(visible = true, origin = {142.667, 58.333}, points = {{17.333, 16.667}, {17.333, -8.333}, {-34.667, -8.333}}, color = {1, 37, 163})); + connect(totalAdopters.y, contactsAdopters.u2) annotation(Line(visible = true, origin = {75, 45}, points = {{17, 0}, {-17, 0}}, color = {1, 37, 163})); + connect(potentialAdopters.stock, totalPotentialContacts.u2) annotation(Line(visible = true, origin = {-145.967, 23.667}, points = {{-3.984, -12.667}, {-3.984, 6.333}, {7.967, 6.333}}, color = {1, 37, 163})); + connect(totalPotentialContacts.y, potAdoptConcentration.u2) annotation(Line(visible = true, origin = {-111.648, 37.5}, points = {{-10.352, -7.5}, {-3.352, -7.5}, {-3.352, 7.5}, {17.056, 7.5}}, color = {1, 37, 163})); + connect(u_otherPopulation.y, totalPotentialContacts.u1) annotation(Line(visible = true, origin = {-152.667, 44}, points = {{-7.333, 18}, {-7.333, -9}, {14.667, -9}}, color = {1, 37, 163})); + connect(parOtherPopulation.y, totalPotentialContacts.u1) annotation(Line(visible = true, origin = {-142.667, 45}, points = {{-2.333, 20}, {-2.333, -10}, {4.667, -10}}, color = {1, 37, 163})); + connect(adjustedTotalAdopters.y, totalPotentialContacts.u3) annotation(Line(visible = true, origin = {-96.857, 20}, points = {{140.594, -5}, {-49.725, -5}, {-49.725, 5}, {-41.143, 5}}, color = {1, 37, 163})); + connect(totalAdopters.y, adjustedTotalAdopters.u1) annotation(Line(visible = true, origin = {77.934, 32.5}, points = {{14.066, 12.5}, {2.066, 12.5}, {2.066, -12.5}, {-18.197, -12.5}}, color = {1, 37, 163})); + connect(adopters.stock, adoptersNotInfluencing.u) annotation(Line(visible = true, origin = {150.024, 14.431}, points = {{-9.976, -3.431}, {-9.976, -0.931}, {9.976, -0.931}, {9.976, 5.292}}, color = {1, 37, 163})); + connect(adopters.stock, adoptersInfluencing.u) annotation(Line(visible = true, origin = {140.024, 14.431}, points = {{0.024, -3.431}, {0.024, -0.931}, {-0.024, -0.931}, {-0.024, 5.292}}, color = {1, 37, 163})); + connect(adoptersInfluencing.y, totalAdopters.u2) annotation(Line(visible = true, origin = {127.6, 39.689}, points = {{12.4, -3.966}, {12.4, 0.311}, {-19.6, 0.311}}, color = {1, 37, 163})); + connect(adoptersNotInfluencing.y, totalAdopters.u2) annotation(Line(visible = true, origin = {143.933, 41.6}, points = {{16.067, -5.877}, {16.067, -1.6}, {-35.933, -1.6}}, color = {1, 37, 163})); + connect(addAdoptersToPopulation.y, adjustedTotalAdopters.u2) annotation(Line(visible = true, origin = {84.184, 12.5}, points = {{12.816, 2.5}, {5.816, 2.5}, {5.816, -2.5}, {-24.447, -2.5}}, color = {1, 37, 163})); + connect(addAdoptersToPopulation.u, adopters.stock) annotation(Line(visible = true, origin = {131.033, 13.667}, points = {{-18.033, 1.333}, {9.016, 1.333}, {9.016, -2.667}}, color = {1, 37, 163})); + connect(doNotAddAdopters.y, adjustedTotalAdopters.u2) annotation(Line(visible = true, origin = {79.934, -5}, points = {{20.066, -15}, {0.066, -15}, {0.066, 15}, {-20.197, 15}}, color = {1, 37, 163})); + connect(u_otherPopulation.u, dataIn.otherPopulation) annotation(Line(visible = true, origin = {-140, 92}, points = {{-20, -14}, {-20, -2}, {-35, -2}, {-35, -2}}, color = {1, 37, 163})); + connect(dataIn.fractionalAdoptionRate, u_FractAdoptRate.u) annotation(Line(visible = true, origin = {-85, 92}, points = {{-90, -2}, {-90, -2}, {35, -2}, {35, -14}}, color = {0, 0, 128})); + connect(dataIn.adoptionFraction, u_AdoptionFraction.u) annotation(Line(visible = true, origin = {-60, 92}, points = {{-115, -2}, {-115, -2}, {60, -2}, {60, -14}}, color = {0, 0, 128})); + connect(dataIn.contactRate, u_ContactRate.u) annotation(Line(visible = true, origin = {-15, 92}, points = {{-160, -2}, {-160, -2}, {105, -2}, {105, -14}}, color = {0, 0, 128})); + connect(dataIn.otherAdopters, u_otherAdopters.u) annotation(Line(visible = true, origin = {10, 92}, points = {{-185, -2}, {-185, -2}, {130, -2}, {130, -14}}, color = {0, 0, 128})); + connect(adopting.y1, dataOut.adoptionRate) annotation(Line(visible = true, origin = {120.632, -57.901}, points = {{-155.132, -17.099}, {39.368, -17.099}, {39.368, 17.901}, {59.368, 17.901}}, color = {1, 37, 163})); + connect(totalAdoptionRate.y, dataOut.totalAdoptionRate) annotation(Line(visible = true, origin = {140.594, -47.5}, points = {{-77.594, -7.5}, {19.406, -7.5}, {19.406, 7.5}, {39.406, 7.5}}, color = {1, 37, 163})); + connect(converting.y1, dataOut.conversionRate) annotation(Line(visible = true, origin = {123.511, -42.5}, points = {{-113.011, -2.5}, {36.489, -2.5}, {36.489, 2.5}, {56.489, 2.5}}, color = {1, 37, 163})); + connect(parFractAdoptRate.y, adopting.u) annotation(Line(visible = true, origin = {-40, 18.75}, points = {{10, 46.25}, {10, 16.25}, {-10, 16.25}, {-10, -78.75}}, color = {1, 37, 163})); + connect(adopting.y1, totalAdoptionRate.u2) annotation(Line(visible = true, origin = {-6.875, -67.5}, points = {{-27.625, -7.5}, {-13.125, -7.5}, {-13.125, 7.5}, {53.875, 7.5}}, color = {1, 37, 163})); + annotation(Diagram(coordinateSystem(extent = {{-180, -105}, {180, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This is more or less the classical Bass diffusion model [5] that explains how new products get adopted in a population:  Potential adopters turn into adopters being affected either by advertising or promotion (i.e. as innovators) or by social interaction (\"word of mouth\") with adopters (i.e. as imitators).

+

The basic model for diffusion can also be used to model the spread of infectious diseases (→SIR). Since the disease is ultimately spread by contact with an infected person, the fractionalAdoptionRate in this case should be zero.

+

While the structure in principle folllows Sterman's implementation [3, chapter 9], the component has been put in a more general form. We have to distinguish the following subgroups that make up the total population of potential contacts for social interaction:

+

+

Depending upon the structural parameter nextStageIsInfluencing we may choose to take the converted adopters out of the group of influencers, e.g. a freshly converted adopter may not yet be entusiastic enough, while more elaborate epidemic models like the SEIR model distinguish an exposed stage, that is not yet infectious.

+

Implementation

+

The behavior of the component is exactly specified by the following equations:

+
+
totalPopulation = potentialAdopters + otherPopulation + adopters + otherAdopters
+adoptionRate = potentialAdopters · fractionalAdoptionRate
+conversionRate = potentialAdopters·(otherAdopters [+ adopters])·adoptionFraction·contactRate / totalPopulation
+totalAdoptionRate = adoptionRate + conversionRate +

+

Notes

+ +"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {-86.207, 0}, points = {{0, 0}, {37.207, 0}}, color = {0, 128, 0}, thickness = 5, arrowSize = 10), Bitmap(visible = true, fileName = "", imageSource = "iVBORw0KGgoAAAANSUhEUgAAAW0AAAFjCAYAAAD2C1pSAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFxEAABcRAcom8z8AAEFcSURBVHhe7Z0JlCRVlf7fKO6OoCiHWXBBEcZB5Sgc2RRENh1QRlBZhmHpymxtgVEQHYFDIyooy8GW7lrBniOI2mA72CAM2FZnVQsCMsDAoIgsgogMDAicEfkjL/7fjbot0VE3MyOrMiJfRHy/c76Ttbz3It67934RlRUZ4QgJBX+me1l0vtvcj7nt/Kjb24+4Q/y4Ozoac6fg+3Ohb+F3V0LX4Osb8XorXu+A7oV+i+8fwesT0NPoE8lr/P3Mz38LSbs7tJ/0vwa6El/LuF/X7RwNHQztjZ9tF+8P9kt3kRBC6gNMcUO/zL0NhrgvDPEoGPKZ+Ppi6Hp8/5AYbaiS/Yv3U/ZX9lv2X+aB+eD3G+oUCSGkfIiJwdR2jEZdE2fLX4e5rQ7dlOcrNfXVMt943jJ/mjkhJDSiEfd6GNSBMKzToVXQ3WlDq7NkPXRdTpd1kvXSpSOEkHyJFrvnyRmkH3fHwpBW4Ov70iZFdRcMXNZtBV6Pjc/Isa66xIQQMnf8N93L8Of+h2AuZ0HTMJhn0gZEzV+yrvH6yjrLemPdNQSEENIZGMh20OdhIKstg6GKkax/HAfEQ0NDCCEw6XH3t9GIOxzmcAH0oGUg1GAlcZH4xHFCvDR0hJC6gLO4N0LHQdOWSVBhS+Km8XujhpQQUjX8sNsSRf45nLFdYxlBKML+PQDdDMnbM/LPulF8/WW8HgsdhjPNffwytyO+fgfmtLUfcVv489zr8P1f+XPdxvj6L6MV7oUyZ3mV7+Ofy++lnbSXftJ/1O0Qjyfjzoz/JWxrRLcrb0/IfjyQ3L/QhP2TDwh9VuIbB5oQUl5gUmLUJ6Cor7MKfhDCvtyHfZJ/al4Qm+S4a+B1z/igssS9SHc9KGS/9KC3p+6vmLvsv8wjmCtoJM7YpxMk7rrrhJDQiRa7DVC4h6GAr7IKuyhhH+Rj5VdB5+DsdgG+f1e01L1cd7NSyLxkfvE8Zb4yb8zfWpeipPtwmOSD7iYhJCRQqDujUEdQqE+kCzhvYZvyAZKLoGNwRrobtInuVq2RdYjXQ9ZlZn0K/+ARtin3XpG3fHbW3SKEDIpoudsURSn/kLopXax5Cdv6E0xgLV7Pwvcf8cvcZro7JAOyXvG6yTXZM+v4p+T65inJE+g4yRvdHUJIEeDP8Leg+IatwsxD2NaPoROw3Z2iFe75uhukD8h6yrrG64t1ttY/D0n+SB7pbhBC8gCFtgP0LasI+yls4xc4C1yKr/er6vvQoSLrLesu6y9xSMYlD0k+SV7p5gkh/cCPu71QxKusouuXULiX4sxrEbb1Zt0sCQCJRxwXxMeKW7+E8S+D9tbNEkLmAgr2oyikKavI5iuM63EgWInXw/A9byFaAiROyIl/Rswkbj4Zz34JOTEleaebJIRkAWdWci3wLVZRzUcY8xkUpdzE/xDelKjcxDfzkjhKPBFXK97zkeSf5KFujhCSJv4Ah1wJMubusYpoPsK48oiuQ6Pl7sW6OVIhJK4SX+hKK/7zEXJHHtF2XKgffCKkcOJreUfdqSi4R62imasw3p14PQVnS1vopkgNkHgjn74A/SqdE/OR5Gecp7wGn9SV+J4YM5+ee9YqkrkKhXUhxny/bobUGMkDyQcrT+Yqydc4b5G/uhlCqg+SfiGK6XdWUcxFGOvX0PF+wr1KN0HIn5G8iPMDeWLlz1wk+St5rJsgpJogyXeBWlYRzEUonFtZOKQX9IThViuf5iLJZ8lrHZ6QahAtdZsiscespJ+LMNZa6EAdnpCekfyRPLLyay6K8xt5rsMTUl6QzJ+GnrQSvVfhDOmHGIvvV5O+IfkEXW7lW6+SPIc+rUMTUi78iPsAEvgGK7l7Fcz62xhvJx2akL4j+SV5ZuVfr5K8l/zXoQkJm2jYbY7k78t/7DHOqB92W+vQhOSO5JvknZWPvSquA9SDDk1IeCBJT8JZxrwu4cMYf8AYZ+Dr1+qwhBSO/4bbTPJQ8jGdo71I6kHqQoclJAz8uDsAiXm7lbS9CGOcilfeB4QEg+Sj5qWZs1kl9SF1osMSMhj8EvcaJOPFVpL2qBXQVjosIcEh+al5auVvZkm9SN3osIQUB5JvX+h+KzGzCv3/C6/76ZCEBI/kq+atmdNZJHUj9aNDEpI/SLjTrGTMKj/mnsbrv+pwhJQOyV/NYzPHs0jqSIcjJB+QaFsh0eb1SCgk+nK88p+MpPRIHms+m7meRVpPfGuQ9B8k1xFI0Dn/Jx19r/UTbg8djpDKIHkt+W3lfRbFdTXuDtfhCJkf8YNX5/ERdJj9Y9DROhwhlUXyXPLdqoMsiuuMD44m8wGJtDMSac5PkEECL/Pnuo11OEIqj+S75L1VD1kk9YYzd376l/QOkuczVlJlEZJ2NT92TuqMfix+tVUfWYT+n9GhCOmMPknmEiuRsgh9F+tQhNQeqQerTrJI6pBPyiEdwdH9Q0iUB6wE6ib0uwsJtpcORQhRpC7wl+tdVt10E/r9RupShyLkOWC6p1tJk0VIrAv9Be4VOhQhJIXUh9SJVT9ZJPWpQxGChBpz37ASJYvQ9ygdhhDSBakXq46ySOpUhyF1xX/TvQxH8MusBOkmJNB10YR7pw5FCMkIam5b6HqrrrpJ6lXqVocidSK+7/UcH1KAxFmiwxBC5ojUkVVf3RQbPu/TXS/8uNsege/5ydTo85gfcQfpMISQeSL1JHVl1VsnSf36Ybe9DkOqDM6uP4iAP2UlQiehzw+jEfd6HYYQ0iekruL6Muquk6SOpZ51GFJFcFRvWMHvJvQ7WYcghOSE1JlVf90E8x7SIUiVwBH5RCvgnYRk+C1v8kRIccQ3n0LdWfXYSVLfOgSpAkiCnv/hgSS42Z/nttQhCCEFIXUn9WfVZSdJnesQpMwg+N+xAtxJCP5V0bB7pQ5BCCkYqb+4Do367CT0+bYOQcqGPz9+fmPPDyyAyV+gQxBCBozUo1WnnSR1L/WvQ5Ay4Ifd1gjcbVZAOwkJcrYOQQgJBKlLq147SepffECHICGDQG2JgM3lGuzP6RCEkMCQ+rTqtpPEB8QPdAgSIn7E/Q2Oyv9tBbCTENwjdAhCSKBInVr120niB+ILOgQJCQRoQwT1unTQOgkBfdJPuA/oEISQwJF6lbq16rmd1Bc21CFICESL3fMQmJ6ekoH2d0Hb6hCEkJIgdSv1a9V1O8X+AJ/QIcigQUAutQLVTjhSX4PX12p3QkjJkPrVOjZr3JL4hHYngwSB6+nG6mj/79Fy92LtTggpKVLHcT0bdd5O4hfanQwCHDlHrcB00L9pV0JIRZC6TtV5R4lvaFdSJFj4s6yAtBPaX6JdCSEVQ+rbqvt2Ev/QrqQIsOinpIPQSfiT6ErtSgipKFLnVv130CnaleQJAvMZY/HbCkfUn+D1pdqdEFJRpM7hD2uT9d9N4ifaneQBDPjj1sK3E9rf4ofdJtqdEFJxpN5hxD3dIVB8RbuTfoKF/SdrwdsJ7e+Kzq/ec+SiycM28lNDB/hW4yg/1VwMLcfXV+D1Juj+aKoZyWv8/czPl/uphV+caT90QDTZfLUORUglkbqP69/whXYSf9HupB9gQfe1FrqdcKR9yE+4t2n3UuOv+fRLfGtoN+gkP9W4HOb7qBjzXIX+j8dmvqZxcjTd2D36WZNvHZWUaLnbyI+4A6CjUCOLkffLoSvw9U3Q/XEt4DX+Xn4+8/svxu3RD7+v7AFc6h9zfSjpC92EddpXu5P5gMWUi+gzLz4W/v+QkDtp99ISTS7YFSY9se7sOS9hGw/KdmR7umkSKP5s9xI/7nZDjp8EXY66eNSqgazCGI9jjCtQL/KYr92hSh3AMbcdxQ+Sc+4k8Rm/1L1Ou5O5goXs6UboftjtpV1LCc6C94+mmyssg81bOEBcgm1/RHeFBEI04naF+UxA8dlzXkKtPSjbke3ppksP5rOnNdd2Er/RrmQu4KziTGth2wkLvr92LR1+amgfGPYFOOt9xjLUooTtP+unmxfh6/1018iAkHxGXq9I53kRgtnJdc+VOIDrOprztCS+o11JL2ChD7UWtJ2QZIdp11LhJxe8CWb9/bR5hiDZLz95JG8kXzAwjX2Q/xcgp5+xcr0oYR+ehS7C16U/gIs/pOfXSeI/2pVkQf+J8EdrMS0hIJ/UrqXCTzcW+qnm7ZZhhiLfat6Fs+9jdJdJjvil7k3I5e9bOT5oyX75kj8JRnzCmpsl8Z+qXMxQCFjc662FtITFLd2j86PrFm0atRpfgWE/ZRllaMIZt4dxn+N/soj/pMkJ5PFC6HYrx0MR9u8u1GapD+DiF9bcLIkPaTfSCSzUhLWAbbRCu5UGv6a5AwzwO5Y5hq74bZzphbzKpI9Ey92m0Yj7CvL+KSO/gxP208P4zvHnlfcqC8wj8/8JxI+0G7FAMhxlLZwltP2FX+JeoV1LgV7G96BliGUR/jp4DNpbp0TmAQxhB+Txd6z8Dl3Y9++X9SoT8Q3xD2teljDXo7UrSYKFeY+1YO3kh927tWspwFnq/jDsX1pGWDZhHvf56cbBOjUyB+LL+Mbcg1Zul0Wo2cegUh7AxT+sObWT+JN2JQIWRZ7veEd6odoJbUv1j8dosrE7TPsGywDLKt9q3uLXNN6vUyQ9ALPeH/qlldtlE+ZxH+qxlAdw8RFrTpbQVuLF50yuAwtycXqR2gltx7VbKfBrm9vCsH9kGV/p1Wqu8ZND2+tUSQaQw7vD6G5I53WZhZq8BXMq5QFc/MSakyXxKe1Wb7AQJ1kLZAltf6rdSoFfs3CL+FOGluFVRJjfSj819GadMukA8ndbP+J+ZOV26TXq1vhhV8oDuPiKOSdD4lfarZ5gATLfCAptn4Leql1LgW81V1lGVzXJPHXKpA0w6y2Qvz09XaVswtn2Sj/u +SncAF18Rf7HmZAlt63ljKUxe3sf+XXpB2gltS3XrRD/VWGQZXFUl89WpEwMY2iorr6smmadOuVSIv1jzsaS+Vb/3tzHx4fRitBMS4QztVgr8NfFH06+1zK2qkvnKvHUJSALk7yIrr6sqma9OvVSIz1jzsST+pd3qgZ9we1gLYQmL8x/arTT4VvMLlrFVXTJvXQKiINflo+nXWrldVcl8Zd66BKVC/MaakyXxMe1WfbAwN1qLkBaOfA/6ZW4z7VYK/NTCnfxU827L1KoumbfMX5eCAOT6F6zcrrpk3roEpUL8RnzHmlNa4mPardpgQbJ/9n/Y7aPdSgOMa9QytLpI5q9LUXtwJrYTCvtuK7erLpm3zF+XolSI71hzsiR+pt2qiR9xb7EmbglBX6zdSkM0ObSNZWR1E2/nOgNyeNTK7bpI5q9LUTrEf6w5WRJf027VAwtxqTXptHD0ulm7lAqcZZ5mmVjdJOugS1JbonG3jZXbdRPOWkt7ABcfsuaUlviadqkWSOLDrQlbwiKU7n4G0VjzBTCrn1gmVjfF64D10KWpJcjh06zcrptkHXRJSgdM+/3WnEzB37RbNcCkMl+TjXal+pj6OmBU77MMrK6S9dClqR3I4xcgj3HgsnO8TtJ1KO0BXPwoPSdL6m/VuXYbE8p0TTbaPewn3Ku0W6nwU41TLfOqq2Q9dGlqB/L4fVZ+11WyHro0pUP8SHzJmlda4nPardzItYzWBC1h0kParVREzv0FTKplmVddFa8H1kWXqFYgj0+18ruukvXQpSkl4kvWvCyJ32m38oIJZ7sme9Rdrl1Kh1wtYRlX3VXHq0jiA/iYa1k5XlfF61HyAzjmcLk1t7TE77RLOcFEs1+Tvay8D9H0UwsPskyr7pJ10SWqDXK1hJXfdVeZryIRxJ+seVkS39Nu5aLq12Qn8Wsax1mmVXfJuugS1QY/7g6ycrzuknXRJSot4lPW3CyV8tptTLDS12Qn8VONsyzTqrtkXXSJagPy/jgrz+suWRddolIjfmXNLy3xP+1SDrDT+6Un0U5YhNI/ssq3GhdZplV3ybroEtUGFOtZVp7XXbIuukSlRvzKmp8lnG3/o3YLHwQo013N0K6U12SngTlNWqZVd8m66BLVBuT0RVau112yLrpEpUd8y5pjWjD4a7VL2Phhd6g1gbQw8Yf9uW5j7VZqfKt5h2VadZefav5Cl6g2oFAnrXyvu2RddIlKj/iW+Jc1z7Qw70O1W7hgJ2+1dj4tTLqU12RbWIZFzUiXqDYgr++w8r3ugi9U6gAu/mXNMy20u027hAl28BPWjqeFdqu1SyXgmbYtWRddotpg5Ts1I12iyiA+Zs0zLfFF7RIe2Ll7rZ1OC+321C6VwE81+Z62oZq+p80zbUOyLrpElUF8zJprWuKL2iUssGPHWzucFtpV7jaGvHrEVi2vHuF72qaq9J52EvEza75piT9qlzDwS9yLEJRHrJ1NC+121G6Vgddp26rlddpjvHrEEkyrkgdw8TNrvmmJP4pParfBg4Bk+kABdvxC7VIp+IlIW7X8RCSv0zYl66JLVDnE16w5pyU+qV0GD3bmHmsn00K7t2qXSsF7j9iq5b1H+IlIU0EZVp8RX7PmnJb4pHYZLH7ELbB2MC3scGUf+Mq7/Nmq413+eO8RW1W490gnxN+seaclfqldBgf+NPhPa+fSQtDeoF0qRxTxftppxeuBddElqg28y5+tst/lrxvib9a80xK/1C6DAUeXD1s7lhbaTWiXygKT4pNrEpL10KWpFfEBnPfTXk/xetTgAC4+Z80/LfFN7VI82PiPrZ1KC38SvF27VJZosrG7ZV61FdZDl6Z2oC745JqEZD10aSqN+Jw1/7TEN7VLseDPgd2sHUoLO3ixdqk00c/4NPZ1itcB66FLUzuQ97un66Dmqs0BXPzOmP8siX9ql+LAnzzfs3YmLbTbRbtUHpjVaZaJ1U2yDroktQR5z6exq3QdanMAF79Lr4El8U/tUgyZ33QfdVdrl1oQTQ5tY5lY3VTHq0bSoEZOs2qibpJ10CWpDeJ71lqkJT6qXfIHGzwlvQOWsFMf0i61AWeZo5aR1UUyf12KWhONu22smqibqn7ViIX4nrUWhk7RLvmDU/uuN4ZCmxu0ea2IJps7w7jutgyt6pJ5+6mFO+lS1B6ccWW6dreqkvnrUtQO8T9rTZISH9Xm+eJH3AHWDszSqGtql9rhW80vWKZWdfnW0Bd0CQhAHewM47p7Vm3UQDJvP+FqewAX/7PWJS3xU+2SHwjGZdbGk8IR5Mmgbo5SMP6aRW/yU41rLGOrqmS+Mm9dAqKgXr5g1UjVJfPWJaglehO9J621SUr8VLvkgx92W1obTgs7cq52qS0wsUWWuVVVfk1jkU6dJMDZ5ptQvNdYdVJVyXxl3roEtUV80FqftMRXtUv/wU6cbm10libcO7VLrfGt5irL4KommadOmRjAxBaZdVJR4U9+HsCB+KC1PmmJr2qX/oPke9DaaFJoU7unlbTDr1m4hZ9qXmIZXVWE+a30U0Nv1imTNqAuVln1UjXJPHXKBESjbo21TkmJr2rz/oKjwT9YG5ylEXe4diHAr21uC2O72jK80qvVXOMnh7bXqZIO4OxzC9TQJWbNVEQwn5V+3PEAniAad4dba5WW+Kt26R8YdLm1saTQ5hFtThLIfTh8q3GDaXwllW81b/FrGu/XKZIMoD62hTJ98KJ0whmlH3Y8gBvgYNb1qV7ir9q8P0SL3fOw4Sz/Ca3d46WyAtPe3081fmkZYNmEedznpxsH69RID6BOdkctdb2Gt0xC3d+COfEA3gbxRWvdkor9FT6rXeYP/rT7qLWhtLBz79IuxCCaXLArDO9BywjLIj/VfAzaW6dE5gAKdH/ol1YNlU2Yx32oex7AOyC+aK1dWn7cfVS7zB8MuCK9gbSwY7dpc9IB+cSgbzUvtgwxdOGA8wPf+nihdyeLomgj7/1ivG6qP8oFbGMfbGMD/TZ3ohG3Kwyv6z/2QxZq/jGIB/AMiD9aa5jSCm0+P6Kl7uXYoDc2kFZxn6MvOb51+Ga+1TgbJvisZY4hyq9pLPWTCwq79lZMGkZ6DvQYvhZer7/KBWznHuhObOdwqBDzlk8Mwrgz3cozNGG/f4Azw+JvL1pSsGZd79cU+yz8VrvMncz//TyvfjeGmS8w7WNg3vdYJhmK8FfBA9DxRd0fG8b5LuhM6O7YqhV8/9faJBcw/m26KdnWj6AGvtxQf50bfpnbzI+4s2GCz1p1FaKwr0v9Un54phfEH621nCX4rXaZO3D/LB9bv06bkx7xk81tYdyTlmEOWrJfRV3SB4PcGUYpZ9b3x845m7zfHrldt/Nn8LMroCPw5Uu1WW6gzo5BHd1j1Vcowv49gP08Hl/X9gEX80F8Mr2maYnfavO5gUFemh7UEnbms9qFzJGZq0ua37XMs2hhPy7B2fXHiniuH0zxvdBS6MEZq7TB7zfRLrmA8e/QTc0Cv1sF/RO+fKE2zwUU7LaopUmrxgYt2S9e0jc/xCettTU095MEJFGmB/dGw25z7ULmQeTcX4hZ+qnG9ywzzVvY9kqcWR8UrfjI83WXcgMmuAc0Bj0yY42dQbuNtWsuYPxf6abagjYrIRzMolwPZihuubrku2atFSx4wCVQIQfwqiM+aa1xWuK72qV30HncGjQpJFdLm5M+opcHTuCs937LYPslbONB2Y5sTzedKzC8bWB8349dsAfQZxqa7KILoOU96IvQYtW6f3h2BW0n8ZLresUHcJgl6ivTY/36LWx7pR9xOIC73A/gdUL80lrvpNBmTJv3DgL3a2vQpNDmBG1OcsBf8+mX+NbQbjDWE6HLfavxqGW+WYX+j0NX+DWNk6Ppxu7Rz5q5v18rwOi2hXo265DBfK7GyzY6xdyILw8cdRPQ/VYN9kswiwdlO7I93TTpM1jjz1trn5T4rjbvDXTc1howLbR7h3YhBRBNHraRnxo6AMZ7FM7CF0PLYxOeat607qxcXuPvZ36+3E8t/OJM+6EDosnmq3WoQoCp7apnppVFD0a5m7c/271ELrND4Z+Iurscr49aNZlVGONxjHEFzqhPxvfyBPlCDuB1RvwyGYN2Ev/VLtmRxLAGSwpt7tHmhJjAzCpv2uvAPM/UaRdCtNxtBMM9ADoKRb4Y9bg8NuFRdxMUn5XLa/y9/Hzm91+M2888garQAziZATHoepUQ2pyozbODQE9bgyWFNnyIK8kEDG1v6Cb1t0qBeRX6oRxSbmDII5afJoU2U9o8G37YbWINZGg/7UIKQj6VGL89Im95zLw1MonXa/1U4x7o4Zm3RxoPz3yPn8vvW40L8PWZcb/JIwf6ISgY235VMW+aNZkL4pspHzXlz3ev0S7dwRn0x6xBkkIbL++xaReSE9Hk0Db6nvQ0jPjJ5D8V5yoZB7pBjFyeHq+bKhQYnZj3rWJ+Gdk1g8RAMwvbX3fliNzbJDNoLwed/aCBmrV8KjF+e0Te8ph562MSdXktXu/B68Napw/r9/LzSegCP+7OjPsN81PMgyD+30SGT8AiZh/TLt3BgF+3BkkKA/5Qm5M+49c23gtTPRWatky335o5U2+e5qcX7hGNFfNxdQGmJzeDWgitFjNsB37//7RLbmAzv5/ZWnuwH6vwIoY///tDzIFo3G2D2vwiam8ar11vlZxFMg50gxg5vh/IAbyOYM0vT8ciLbT5ujbvDpLiRmuQpNDmU9qc9IFocvEGMOkDYZ43WcZalLAPP49aQ4fL/uiu5Q5M8NUwxE9CLTHHNPj5U9o0N7CNJ3Vzs8Dvvg/JJyJfrM0LA3X2XuhUMWqrDvstGMW1MPDT/ITDAZwfV88LrPO/pNc+LfFhbd6Z6By3kTVAWtjodtqFzAO/+sjX+VbzUzDLlmWig5JvNdbiAHJsNLkw17vrJYEx/hX0L9BPZuxyBnz/f9okN7CNP+jm/gx+djF0IL4s9G2QaLHbAPV1IIr2Jqv2ihK2 +/3N5fKDsj+4a6RP+vGyXVIsfa5f2IFBdnwWJNk9oczJH4jPrGbMO+qEIsn8w8KOKPPOGUW4GHQddp+aZe75hG3/UbT0DfRvaX39VGH6pex1q61Mw7K6fmitS2J+12K9jYeCFHcDrANb1cWu9kxI/1ubtQaPTrM5JYWNXaHMyB2CC8uixyyyTDFWyv7LfOoVCgIe+GOb5KSifp1UnUMOWt0F6/1DDPInPrGfMOuiHIsj+yTXePPPuD4j5D611Tkr8WJu3J9Mj30fdSdqc9ICfXvh2P9X8GvS4ZYyhS/Y73n/MQ6dUCGLe+mVuYBu5f6LRAka4P+qp6+2PQ5Lsr+y3ToHMEfFRa33XE/xYm9vIzWEw0J/MzgmhzXu1C8mInxraB2er8XXUZZfMQ+ajUyNzAGesb/fj7mswv65/Ioco2e94/zEPnRLpEfFRa22Tiv2400270OA9Vsek0MZjkFzvK1wloslFL4fJnYwz1McsAyyxfh+1GqfIvVB0qiQjftjtgzqKr6Muu2QeMh+dGukB8dHYT411TUp8WbvMBkfNLJehTGtz0gW/ZsHf+VZz3DC8ysi3Gt/wUwveplMmHYiftzriTkYNPWbVVon1e+iUTFc6kPUQP02t5SyJL2vz2WCA861OKX1Fm5MORJPNrXCG/XPL6Kom/BVx56A/Hh86fpn7O9RX1/vTl1l+zH0D8+QBvAewbl9Jr2Na4svafDZY9BusTklhgIO1OWmDn27uizPs6y2Dq6ow31uiNc2P6BKQBKibrVA3P0/XUhWFed7Jj8dnx4+7g6x1TEp8WZvPBgv+tNUpKQakM/HlfK3GzZaxVV3yl4VvDR2iS0EAampf6HqrlqoqmMwteOUBPAMw7b9Pr19a4svafH3EjK0OSSEYf9TmxMBPLTwIxnW7ZWh1EQ5Yd/mp5hG6JLUG9SLPerzZqqWqC0bzcz/ieADPgPiqtYZJmSfLWOSDrcZJyRmDNicp5G55MOy+3IWv7MI6PCO3gdWlqSUwrINQL7dbdVQXwYzuwhrwAN4F8VVr/ZISf9bmz4FfdH9DfMydp81Jgvg97Jr80zGrsB734C+PWho3amVn1Epf7sJXdmEdnsEBrNYH8G7AkM+z1i4ptPmqNn8OLO4VVuOk0PEYbU4UPz20vZ9qTlnGVXf5VuOnfs3Qu3WpagFqRN7DrsU/HbMK3nIPjbs94qvWuiUl/qzNnwMdH7Aaryc+pXk9/NrGG3FG+T3LsKgZ+VbzUj819GZdskrjx932qKMps3ZqLqzLT/2wq9UBPCsw5F2sNUtK/FmbzyBPUrAaztKwe6V2qT3+p0e/AmfYo5ZRUesLB7ax6Ormhrp0lQRF9UYU3/fMuqFiYY0uxYGtFgfwXhBftdYrrfWeFIY/Xd5iNUoKC/47bU6Abw2dZBkUZUvWS5eucvgl7hWoj1Grbqj1hQPbGF4rfQCfC+Kv6bVKS3xam8cdstxD+1ptXnv8muaHcfYY9H2wQ5NvNR6q6j8mURvd79ZG/VmyXrp0RBF/tdYqKfFpbY4OY+4oq1FS6HCRNq818v6sbzWvtoyJ6iwY9ySM+7mzhQqAuvgw6ifo+2CHJqzXQ36c/5hMIv5qrVVS4tPaPDbts61GSWHQL2nzWoMz7HMsQ6KyCQe8ZbqUpUfen0VdXG3VC9VZ8JzJ9f7crzlYjy9b65SU+LQ2jzustBolhQRdoM1ri28tXICzxactM6Kyy083P6lLWmpQN+dYtUJlEzylMgfw+YKD/5C1RkmhzUptHnfo+gBRLPBu2ryWyH2j+T52fxTfW3xy0aa6tKUEZ4kLUDdd79VDdRbWsBIH8PmCdXiftT5JiU9r8/gTXHI/XLPhOsG036DNawn+rP+qZUDU3IS/WJbo0paOaLnbCGfZfB+7D4IRPRYtdaU+gPeDaNhtbq1PSr+PG/sJ9yrjl+sJCfps3Lim+NbQXjg75Fl2HwXTfrSsjyyD0XzVqhNqbsJ6lvYA3k/EZ631SUr8Ov5nivXLpLCo9+q4tSP6WfMFfqrxLct4qPkJB8Lv+l8e/SJd6lKAetmLZ9n9FdbzUaxr7R9ZJj5rrU9SfsRtIU/U2NH65XoadT/TcWuH/PPRMhyqP8LZdkOXOnhQCy9AYX1rVn1Q8xaM+7t+iSvVAbzfiM9aa5MU8m8HOSX/oPXLpNDwSh23VkSTizfA2eCdltlQ/VG8vlhnXfKgwdngAqs+qP4IZ5GlOYDngfistS5Joc2+YtpHWr9MCg0v1HFrhZ9qLLKMhuqvZJ11yYMlWuw2QB3cadUH1R/F64t11iWvHeKz1rokhTZHSMPjrV8mhTZf03Frg9zgyLcaP7JMhuqv4nUO/IZSOLlZZNUG1V/JOuuS1w7xWWtNkhK/loZd/xOONrW7VwD+bD/CMhgqH8l669IHB2pgQ5jJj9J1QfVfus61vKGU+Gx6PdISv5aG51u/TAptPq7j1gK9YuQHlrlQ+Sheb6y7hiAokP9HWHVB5SNZb136WiE+a61HUuLX0vBS65dJ+Zo9dcK3mh+zjIXKV7LuGoJgQP6/AGd/P0jXBJWfdL2DPIDnifhsei3SEr8W0562frmeJur1xBqYxyrLVKh8JeuuIQgG1MfHzJqgcpWsu4agNojPWmuRlPi1JGX3JwGPue103MoTrR3aBubxP5apUPkqXnesv4YiCJD7q6yaoPKVrLuGoDaIz1prkZT4tTS82fplUjhtf7uOW3lgHMdbhkIVI1l/DcXAicbdNqiP/7FqgspX8bpj/TUUtUB81lqLpMSv5Uw7y5Ojt9JxK4+fal5lmQlVjGT9NRQDB7XR9XJYKj/J+msoagHmvFV6DdISv5bEvNv6ZVJ1ucOfn164h2UkVLGSOGhIBgrOaq6y6oEqRrL+GopaID5rrUNS4teSmL+xfpkUTtv/RsetNH6qcYZlIlSxkjhoSAaGn3B7WLVAFSuJg4ak8ojPWmuQlPi1nGk/bP0ypVfruJUGZsHbrwYgP9W8X0MyMFAcZxh1QBUsiYOGpPJgvq9Ozz8t8Wsx7SesXyblz3N/qeNWFhj2LpaBUIORbw0N9ElJMAvefjUAwZ8GfgAvCvFZaw2SEr+W5Pyj9cuk6nDLRJj2Zy3zoAYjv6ZxooamcFATu1h1QA1GviaPOhSfteaflPi1nJKbv0xKx6w0vtVYaZkHNRjhIHqZhqZwUBifteqAGowQj4EdwIvGmn9amc60oxXuhTpmJfGtT2zmW80HLPOgBiPE43/96iO31BAVCv4EXWnWATUQIR4DO4AXSeYzbb6njcWaWniAZRzUgNUaOlxDVBh+mdsMhfGAVQfUYASP+l8/7AZyAC+S7O9p8+oReT/7HNM0qIEKcZnQEBWGH+9+0x5qABpxhR/AiwbzzHj1CK/Thmk3r7RMgxqsfKuxVkNUGKiHc6waoAYrmFXhB/Ci6eU67Vp/IjKa/sQrcUb3G8s0qMEKpv2ov+rIv9ZQFQKKoutz+qjihbgUfgAvmuyfiKz5vUf8mqF3W4ZBBaLJxu4aqtyJht0rs/zlSRUvxOVRf64r9ABeNJhnxnuP1PwufzjL/oRpFlQQ8msax2iocscPu3db+U8Fo8IO4INAfNaY83oSv5Yz7VrfTxumvdQyCyoM+TXNUQ1V7qAWPmHlPxWGEJ/CDuCDQHzWmndS4teSqLV+ck3Uaq6xzIIKQ36qOaWhyh0UzVIz/6kgBK8q7AA+CHp5ck2tnxGJM+1nLLOgwpDER0OVO9GoW2PlPxWG4FWFHcAHgfisNe+kxK/FtGv7NHa/ZuEWllFQYUnipCHLFZxpP2PlPxWGJD4aqkoiPmvNOynxa2n4VeuXSaHNSTpupYimF+5qmQQVmBAnDVlu4CxnCyv3qbAkcdKQVQ7xWWvOSYlfS8Ouj1RCm6/puJXCt4YOMU2CCkoSJw1ZbkQj3d9PpAIQ4qQhqxzis+acExK/loZHWL9MCm0u1HErheftWEshiZOGLDf8uDvEyn0qLEmcNGSVQ3zWmnNSfswdKQ33tX6ZFNpcqeNWCj/dWGKZBBWWJE4astxAMfB2rCWQxElDVjnEZ605J4X5f1Aa7mD9cj2Nup/puJXCt5qrLJOgwpLESUOWG6iDJWbuU0FJ4qQhqxzis9ack/LL3I6Z/gGDhbpXx60Ucg2wZRJUWCriWm2cwayycp8KSxInDVnlEJ+15pyUH3dvlqdOv8r6ZVJYqGd13ErhW40bLJOgwpLESUOWG8jxKSv3qbAkcdKQVQ7xWWvOSYlfx43xze/Tv5ylYbd53LhC4M/u2yyToMKSxElDlhsomBvMvKeCksRJQ1YpstzhD/q9NkeHUXeT0WA9oc37tHll8FONX1kmQYUliZOGLDeQ37dZeU+FJYmThqxSwLR3s+ablPi0No8Ttusz8dBmSJtXBpzB8bmQJZDESUOWG8jvX1l5T4UliZOGrFLAtBdY800Kf2Ws1OboMObOtholhTZf1uaVQW6yb5kEFZYkThqy3IAZ8LmQJZDESUNWKTCvL1nzTUp8WpvHpn2U1SgpDHqRNq8MMIM/WCZBhSWJk4YsN1ADj1p5T4UliZOGrFKIv1rzTUp8WpvHHf7BapQU2lyrzSuDZRBUmNKQ5QYK4g9W3lNhSeKkIasU4q/WfJMSn9bm6DDi3mI1SgodfqfNK4NlDlSY0pDlhpXzVJjSkFUK8VdrrkmJT2tzdDjbvcRqNEvD7pXapRJY5kCFKQ1Zbpj5TgUpDVllEF+15pmW+LR2mQFO3/UfMfjTZBdtXgksc6DClIYsN6x8p8KUhqwyZLnDpPizNn8OGPIVVuOk0LFSz2izzIEKUxqy3LDynQpTGrLKIL5qzTMp8Wdt/hzomOVhCOdp80pgmQMVpjRkuWHlOxWmNGSVAYZ8njXPlL6izZ8Dhnyw0XA9oc312rwSWOZAhSkNWW5Y+U6FKQ1ZZRBfteaZlPizNn8OP+y2thonhSPCH7V5JbDMgQpTGrLcsPKdClMassogvmrNMynxZ22+ +PnDzp60OSflx9/favPRY5kCFKQ1Zbli5ToUpDVklyHSyDF/W5rOB43e90xlM+yBtXnosc6DClIYsN6xcp8KUhqwSyNse1hyTEl/W5rPBAOdbnVKa/YZ4SbHMgQpTGrLcMPKcClQaskqA+XwlPb+0xJe1+Wz8iPsXq1NSGGBam5ceyxyoMKUhyw0r16kwpSGrBOKn1hyTEl/W5rPBAO+xOiWFNj5a4V6oXUqNZQ5UmNKQ5YaV61SY0pCVHvHR2E+NOSYlvqxdZoNBno8Gf7I6JoU279UupcYyBypMachyw8pzKkxpyEqP+Kg1v6RiP4YvaxebaNStsTonhYFO0ualxjIHKkxpyHLDynMqTGnISo/4qDW/9QQ/1ubtwUCnmZ0T8tZHKkuIZQ5UmNKQ5YaV51SY0pCVHvFRa35JiR9r8/agUZZ7az+hzUuNZQ5UmNKQ5YaV51SY0pCVHpj249b8khI/1ubtic5xG1md08IGt9MupcUyBypMachyw8pxKkxpyEqN+Kc1t1mCH2uXzsDdbzQHSAhtPqXNS4tlDlSY0pDlhpXjVJjSkJUamHaWy6tv1ObdwYBftwZJCgP+UJuXFsscqDClIcsNK8epMKUhKzXw2MutuSUlPqzNuwND/pg1SFJo42c9SaFkWOZAhSkNWW5YOU6FKQ1ZaRHfhCE/a80tKfFh7dIdf757jTWIof20SymxzIEKUxqy3DBymwpUGrLSgjnsl56TJT/sNtEu2cCRYMoaKCkcCUa1eSmxzIEKUxqy3LDymwpTGrLSAm8dseaVFLy199uFYOATrcGSQpt7tHkpscyBClMastyw8psKUxqy0iK+ac0rKfFfbZ4dOP221mBpod07tEvpsMyBClMastywcpsKUxqyUiJ+ac0pLfFf7dIb6Phra8CkcET4vDYvHZY5UGFKQ5YbVm5TYUpDVkrEL605JSW+q817BxsYswZNCm1a2rx0WOZAhSkNWW5YuU2FKQ1ZKRG/tOaUFEx7XJv3Djp/2Bp0lobd5tqlVFjmQIUpDVlumHlNBSkNWekQn7Tmk5b4rnbpHQzw0vSAlnD0+Kx2KRWWOVBhSkOWG1ZeU2FKQ1Y6xCet+Rh6qXaZG3D9y4xB1xN25jptXiosc6DClIYsN6y8psKUhqx0iE9a80lK/Fabz51o3B1uDZ6WP6/NI94DxjIHKkxpyHLDymkqTGnISoX4ozWXWYLfape5Ey11L4f7d30kDnSKdikNljlQYUpDlhtGPlOBSkNWKrDfp6TnkVbss/Bb7TI/MOCK9AbSwgZv0+alwTIHKkxpyHLDymkqTGnISoX4ozWXlFZo8/njx91HjQ3MEnbsXdqlFFjmQIUpDVluWPlMhSkNWWkQX7TmkZYfcR/VLvMnWuye58fck9aGksLOnaVdSoFlDlSY0pDlhpXPVJjSkJUG8UVrHknF/gqf1S79ARtebm0sKWz4EW1eCixzoMKUhiw3rHymwpSGrDTAOx+x5pGU+Ks27x8YtOuzI2P147+fBWGZAxWmNGS5YeYyFaQ0ZKUgGsl49V2WZ0HOBZxJP2htcD1leeR7IFjmQIUpDVlumLlMBSkNWSmAZ05ac0hKfFWb9x8cDU63NjpLE+6d2iVoLHOgwpSGLDfMPKaClIYseMQHrf1PS3xVu/QfP+y2tDaaFnbiXO0SNJY5UGFKQ5YbVh5TYUpDFjzig9b+pyW+ql3yATuS5WPtT/ol7kXaJVgsc6DClIYsN6w8psKUhixoxP/EB639T0r8VLvkhx9xB1gbn6VR19QuwWKZAxWmNGS5YeYwFaQ0ZEEj/mfte1rip9olX3AEudfagaTQ5gZtHiyWOVBhSkOWG1YOU2FKQxY04n/WviclPqrN8wcb7Po5epEfdx/SLkFimQMVpjRkuWHlLxWmNGTBIr5n7beh4u7XhJ16g7EDs+RH3dXaJUgsc6DClIYsN6z8pcKUhixYxPes/U5LfFS7FANO7b9n7UhaaLeLdgkOyxyoMKUhyw0rd6kwpSELEvE7a5/TEv/ULsWBo8Ru1s6khaPOxdolOCxzoMKUhiw3rNylwpSGLEjE76x9Tkv8U7sUC3bwx9YOpeVH3Nu1S1BY5kCFKQ1Zblh5S4UpDVlwiM9Z+5uW+KZ2KR5sPNODf9FuQrsEhWUOVJjSkOWGlbdUmNKQBYf4nLW/aYlvapfB4Mfcf1o7llbhb7pnwDIHKkxpyHLDylkqTGnIgiLzxRnwS+0yOPAnwQJr59LC0WVUuwSDZQ5UmNKQ5YaVs1SY0pAFhfibta9piV9ql8GCHb7H2sG00O6t2iUILHOgwpSGLDesfKXClIYsGMTXrP1MS3xSuwwe7Mxx1k6mhT8NLtQuQWCZAxWmNGS5YeUrFaY0ZMEgvmbtZ1rik9pl8OjNUbo+nUGEdjtqt4FjmQMVpjRkuWHlKhWmNGRBIH5m7WNa4o/B3UQPR5HjrZ1NC+0u1S4DxzIHKkxpyHLDylUqTGnIgkD8zNrHtMQftUtYYMe63khKhHZ7apeBYpkDFaY0ZLlh5SkVpjRkA0d8zNq/tMQXtUt4YOc+Ye10Wmi3WrsMFMscqDClIcsNK0+pMKUhGzjiY9b+pSW+qF3CBDt4m7XjaaHdkHYZGJY5UGFKQ5YbVo5SYUpDNlDEv6x9S8uPuVu1S7hgJw+1dj4tTPphf67bWLsNBMscqDClIcsNK0epMKUhGxjiW+Jf1r6l5YfdodotbGDc11oTSAsTH9cuA8EyBypMachyw8pPKkxpyAaG+Ja1X2mh3bXaJXz8iPtHaxKWYPDv126FY5kDFaY0ZLlh5SYVpjRkA0H8ytqnNtpPu5UDHGWyXQoz5m7WLoVjmQMVpjRkuWHlJhWmNGQDQfzK2qe0xP+0S3nA2fZbrMlYwgQXa7dCscyBClMastyw8pIKUxqywhGfsvbHkvifdisXOCqdaE3Ikl/m3qbdCsMyBypMachyw8pJKkxpyApF/MnaF0vie9qtnODodKM1sbQw0cu1S2FY5kCFKQ1Zblg5SYUpDVmhwMcut/YlLfE77VJe/ITbw5qcJUy40Gu3LXOgwpSGLDesfKTClIasMMSXrP2wJH6n3coNJj1sTTAttHsYk36VdssdyxyoMKUhyw0rH6kwpSErBPEj8SVrP9ISn9Nu5QcT2hAT+l16kpbQrrBrty1zoMKUhiw3rFykwpSGrBDEj6x9SEv9bUPtVg2icXd4eqLt5Au6dtsyBypMachyw8pDKkxpyHIHRry3tX1T8DftVi2wCEFdu22ZAxWmNGS5YeUhFaY0ZLkjPmRtPy3xNe1SPUK7dtsyBypMachyw8pBKkxpyHJF/MfatqXSXpOdFbmG0Zq4JT/s9tFuhOSKlX9UmNKQ5Yb4jrVdS+Jn2q3a4CiW9drtB/0yt5l2I4SQXBG/Ed+x/Cgt8THtVn16vHb7P7QbIYTkiviN5UOWKnNNdlawOJmu3RbhyHeGdiOEkFwQn7H8x5L4l3arD5h45mu3RWj7T9qVEEL6iviL5TuW1LeqdU12VjD5fdML0k5o+xT0Vu1KCCF9QXxF/MXyHUviW9q1nmABTrIWxhLa/lS7EUJIXxBfsfzGkviVdqs3WIiLrQWyhLYDfUQZIaQ6iJ9YPmNJfEq7ESyIvL/9y/QitRPaflK7EkLInBAfsfzFEtregdd6vo/dDizKe9IL1Ul+2L1buxJCSE+If1i+0k7iT9qVJMHCHG0tmCU/5n7hl7hXaFdCCMmE+Ib4h+UrltD2KO1KLGDcE9bCtdEK7UYIIZkQ30j5SFuJH2k30gks1PXWAlrCUbAen/0nhMwb8QvLRyyJD2k30g0/4d6Gxf2jtZCWsLj8xyQhpCPiE5Z/WBL/ER/SriQLWLRDrcVsJwTkMO1KCCHrIf5g+UY7if9oV9ILftydaS1oO2Gh99euhBASI75g+UU7ie9oVzIXsOBXWQvbTjii7qldCSE1xw+7vSyfaCfxG+1K5opf6l6HhXzIWmBLMO3/Q/sdtTshpKb4EbeT+IHlE5bUZ16r3cl8wMJnvrGUSBaf/0QgpL7oxQyZT/ZE4jPanfQDLGjmWyeK0P6u6Hy3uXYnhNQEqfu4/g1faCfxF+1O+gkW9uPWgrcTjrQ3+2G3iXYnhFQcqXf4xC2WH7ST+Ip2J3kAI/6MtfDthPZr8fpS7U4IqShS5zDgnyTrv5vET7Q7yRMs9inpxe8kBOZK7UoIqShS51b9d9Ap2pUUAY6oZxlBaCu0v0S7EkIqhtS3VfftJP6hXUmRYOFHrYB00L9pV0JIRZC6TtV5R4lvaFcyCPAn0YVWYNoJ7f89Wu5erN0JISVF6jiuZ6PO20n8QruTQYIj56VWgNoJgbsGr7yInpCSIvWrdWzWuCXxCe1OBk202D0PAVltBaqd0P4uaFsdghBSEqRupX6tum6n2B/gEzoECQEERp4zeV06WJ2EI/WTfsJ9QIcghASO1KvUrVXP7aS+wOc7hogfcX+DgP53OmjdhKAeoUMQQgJF6tSq304SPxBf0CFIiPhhtyWC+2srgJ2EPp/TIQghgSH1adVtJ4kPiB/oECRkEKitEbDbrEB2Eo7KZ+sQhJBAkLq06rWTpP7FB3QIUgb8+e41CNyPrYB2EhLkAh2CEDJgpB6tOu0kqXupfx2ClA0E8NtWYDsJfa6Kht0rdQhCSMFI/cV1aNRnJ8Hkv6NDkDKD4C+xAtxJCP7N/jy+H0ZI0UjdSf1ZddlJUuc6BKkCSILMj85fJyTBb/2E20OHIITkjNSb1J1Vj50k9a1DkCqBZBiyAt5NfsSdrEMQQnJC6syqv25Cv4YOQaoIjsgfhHk/ZQW/k9Dnh9GIe70OQwjpE1JXcX0ZdddJUsdSzzoMqTJ+2G2PgM/lWu7HcFQ/SIchhMwTqSepK6veOknq14+77XUYUgei4fg5ctdbCdFN6Md/eBAyT6SOrPrqJpxd3yD1q8OQOuG/6V6GxLnMSoxuEsOHeMMpQnokmnDvhPH2dJ+gdZJ6 +lbrVoUhdQQJ9w0qQLELfo3QYQkgXpF6sOsoiqVMdhpD4T7XTrUTJIiTThf4C9wodihCSQupD6sSqnyyS+tShCHkOP+I+hMT6jZU03YR+d/lht5cORQhRpC5guj3d/3qd0O8BqUsdipDZIME2QaL09JDQpNB3sQ5FSO2RerDqJIukDqUedShCOoOj+2esRMoiJNtq9N9JhyKkdkj+Sx1Y9ZFF+Mv1MzoUIdnxE0i8MXeLlVRZhKRd5s91G+twhFQeyXfJe6seskjrbWcdjpDeiVa45yORxtLJlVVI4Mego3U4QiqL5Lnku1UHWRTXGepNhyNkfkTj7nAk1R+sZMsi9L2WN58iVSS+yRPy28r7LJK6gtnzkX+k/yDBtkJy9fxghaSQoMvx+lodkpDSInms+WzmehZpPW2lQxKSD0i009LJ14uQ6E/j9V91OEJKh+Sv5rGZ41kkdaTDEZI/SLh9ofutZMwq9P8vvO6nQxISPJKvmrdmTmeR1I3Ujw5JSHH4JfFzKC+2ErNHrYD4JyIJFslPzVMrfzNL6kXqRoclZDD4cXcAkvF2K0l7EcY4Fa8b6rCEDBzJR81LM2ezSupD6kSHJSQMkJgn+TH3rJW0WYUx/oAxzvDfcJvpsIQUDnJR/sl4huRjOkd7kdSD1IUOS0h46H2653xjnKQwzqgfdlvr0ITkjuSb5J2Vj70qrgPe95qUBT/iPoCzjBusZO5VSP5v82PxJE/0Y+fftvKvV0neS/7r0ISUCyTwp6EnreTuVRjncuj9OjQh80byCWbd8/MZLUmeQ5/WoQkpL9FStymSec4fhU8LY62FDtThCekZyR/JIyu/5qI4v5HnOjwh1QCJvQvUspJ+LsIZ0q0Yb6EOT0hXJF8kb6x8mosknyWvdXhCqokWzu+sIpiLMNavoeP9hHuVboKQPyN5EecH8sTKn7lI8pcnDKRW+PPcXyLpz4HmdYlgWiimCzEm3/cm696v7suVTOsk+RrnLfJXN0NIvdAn5ZyKQnjUKpK5CmP+CvqCH3Fb6KZIDZB4I/6nIJ/uTOfEfCT5GecpnyRDyAx+iXsRiuI46F6raOYjFNyV0KHRcvdi3RypEBJXiS9y50or/vMRxr0nzkvkp26OEJIGZ0sNFMqcn5jTThjzGRThxX7cHeK/6V6mmyMlROIXx1Hiibha8Z6PJP8kD3VzhJAsoCg/iqKcsopqvkJRemgltvHP+J73OykBEifE7DDkxEqJXzKe/RLGnZK8000SQuYCCmlv6DKryPoljH8pzqwWoWDfrJslASDxiOOC+Fhx65dwIFiFbe2lmyWE9AMU7g7Qt6yi66ewjV+giJfi6/2ipe7lunlSALLesu6y/hKHZFzykOST5JVunhCSBzjzegsKbdgqwjyEbf0YOgHb3YkPXu0v8YOjZ+77cYKss7X+eUjyR/JId4MQUgTRcrcpik+uOLnJKsw8hG39CWeBa/F6Fr7/iF/GW8j2gqxXvG5YP13HPyXXN09JnkDHSd7o7hBCBgWKcmeYwAiK8ol0seYtbPNu6CLoGD/sduO1vDPE1+DLesi6zKzP3db65Sls8wnJC3y9s+4WISQkosVuAxSqXGFwVbqAixT24beyD9A5+DN8Ab5/V1XfH5d5yfziec58yvUqmb+1LkVJ9+EwyQfdTUJI6Pjz3JYo3BNQwNdZhT0IYV/uwz5N4/UCvH7Jj8fXpO+JM9ItQ/0AR/zBJ9k/2c+Z/f2S7r/M4z5rnoOQxBn7dILEXXedEFJWYtMZc5+FrrEKPhRh/x6Abob5rMb3K/C1vOXzJehY6DCY5j54lato3oE5bY2z2y1gUq/D93/lz3Ubyz0xohXuhTJneZXv45/L76WdtJ95Oss7/DK3o453GHQstvVlvMpTW2S7q+P9wP4k9y80Yf+uwT5/TuIbB5oQUj1Q5G+E5B+Y05YRUGFL4qbxe6OGlBBSF3Cm+bfRiDscZ2wXQA9aJkENVhIXiU8cJ8RLQ0cIITDxMbcd9HmcxcnbE6aJUPlL1j+OA+KhoSGEkM7ENyUacR+CgZwFyT/d+n5jIio+k34mXl9ZZ1lv3syLENIPosXueTCYHWEux8JsVuA1mCsnyiSsoazbCj8e//NzR1lXXWJCCMmXaMS9HsZzIAz8dGgVVPgHSEKWrIeuy+myTrJeunSEEBIGMKsN4zPIUdfEn/tfh2HJ+7MPpQ2tSpL5xfPEfON5y/x5y1tCSJkRE/PL3NtgbvvC1I7y4+5MfC038b8+dFNXU74+3l/Zb9l/mQfmg9/TnAkh9cOf6V4Wne82hyFuB0OUe4gfDB0NU5RnHsoZ+7fwKo9Okw+U3IjXW/F6B3QvJB+bfwSvT0BPx0aL1/j7mZ//FpJ2d2g/6X8NdCW+ltuTnhtvZ9wdjbPlQ/D93vjddvH+YL90FwkZMM79f17GKO6N9frOAAAAAElFTkSuQmCC +", extent = {{-50, -70}, {50, 70}}), Line(visible = true, origin = {50, 0}, points = {{0, 0}, {30, 0}}, color = {0, 128, 0}, thickness = 5, arrowSize = 10), Text(visible = true, origin = {0, 75}, textColor = {76, 112, 136}, extent = {{-100, -12}, {100, 12}}, textString = "Diffusion", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Line(visible = true, origin = {0, 25.792}, points = {{-7.285, 0}, {7.285, 0}}, color = {128, 128, 128}, thickness = 1, arrow = {Arrow.Filled, Arrow.Filled}), Polygon(visible = true, origin = {81, 0}, rotation = -90, lineColor = {0, 128, 0}, fillColor = {0, 128, 0}, fillPattern = FillPattern.Solid, points = {{0, 9}, {5, -5}, {-5, -5}}), Text(visible = true, origin = {-73.452, 37.479}, textColor = {76, 112, 136}, extent = {{-13.452, -20}, {13.452, 20}}, textString = "A"), Text(visible = true, origin = {73.452, -43.134}, textColor = {76, 112, 136}, extent = {{-13.452, -20}, {13.452, 20}}, textString = "B")})); +end Diffusion; diff --git a/BusinessSimulation/MoleculesOfStructure/Actuators/package.mo b/BusinessSimulation/MoleculesOfStructure/Actuators/package.mo new file mode 100644 index 0000000..b80a204 --- /dev/null +++ b/BusinessSimulation/MoleculesOfStructure/Actuators/package.mo @@ -0,0 +1,12 @@ +within BusinessSimulation.MoleculesOfStructure; + +package Actuators "Subsystems that will only have flow ports to pull or push physical entities from other subsystems" + extends Icons.Package; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Actuators in general are systems that push and/or pull physical entities (\"mass\") to and from other systems while receiving and/or transmitting information (usually regarding the material process). Examples would be a mining company extracting resources from the ground and delivering raw materials to producers or a temporary employment agency sending workers to companies in need of temporary reinforcements of their labor force. Note, that in the latter example the flow of workers will be controlled by that subsystem, e.g. temporary workers will be sent and retracted by order of the employment agency.

+

On a lower level, we may think of processes modeled as a subsystem, e.g. the diffusion of a new product via word of mouth.

+

+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, origin = {0, 5}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, lineThickness = 7, extent = {{-62.764, -53.47}, {62.764, 53.47}}), Rectangle(visible = true, origin = {-62.781, 4.645}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 7, extent = {{-10.968, -11.451}, {10.968, 11.451}}), Rectangle(visible = true, origin = {62.219, 4.645}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 7, extent = {{-10.968, -11.451}, {10.968, 11.451}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Actuators; diff --git a/BusinessSimulation/MoleculesOfStructure/Blocks/EffectOfFatigue.mo b/BusinessSimulation/MoleculesOfStructure/Blocks/EffectOfFatigue.mo new file mode 100644 index 0000000..4861b23 --- /dev/null +++ b/BusinessSimulation/MoleculesOfStructure/Blocks/EffectOfFatigue.mo @@ -0,0 +1,64 @@ +within BusinessSimulation.MoleculesOfStructure.Blocks; + +block EffectOfFatigue "Modeling the influence of excessive workloads on productivity or quality" + import BusinessSimulation.Types.InitializationOptions; + import BusinessSimulation.Constants.inf; + import BusinessSimulation.Units.{Time,Rate}; + extends Icons.SubsystemBlock; + Interfaces.Connectors.RealInput u "Input of workload" annotation(Placement(visible = true, transformation(origin = {-145, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-100, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealInput u_ref if not hasConstantReference "Input for the reference workload (optional)" annotation(Placement(visible = true, transformation(origin = {-145, 60}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {0, 100}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Interfaces.Connectors.RealOutput y "Effect on Productivity given as a multiplier" annotation(Placement(visible = true, transformation(origin = {160, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {104, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + parameter Time timeToGetFatigued(min = 0) "Time constant for the exponential smooth of overtime in periods"; + parameter Rate referenceWorkload(min = 0.1) = 1 "Constant reference workload (optinal)" annotation(Dialog(enable = hasConstantReference)); + parameter Integer delayOrder(min = 1) = 1 "Delay order of the smooth for workload" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Real effectMax(min = 1) = 1.1 "The upper bound for the effect of less work than normal on PDY (MAX >= 1)"; + parameter Real effectMin(min = 0, max = 1) = 0 "The lower bound for the effect of fatigue on PDY (MIN >= 0)"; + parameter Real steepness(min = 0) = 10 "High values indicate a steep gradient for the lookup curve (JanoschoekNegative.growthRate)"; + parameter Boolean hasConstantReference = true "= true, if the reference workload is given by a constant parameter" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean clipEffect = false "= true, if the maximum effect is to be 1.0" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Real initialFatigue = 1 "Initial Output (fatigue.initialValue)" annotation(Dialog(enable = not init == InitializationOptions.SteadyState)); + parameter InitializationOptions init = modelSettings.init "Provide InitializationOptions (Free, FixedValue, SteadyState)" annotation(Evaluate = true, Dialog(tab = "Advanced")); + parameter Boolean strict = true "= true, if strict limits with noEvent(..) (clippedEffect.strict)" annotation(Evaluate = true, Dialog(enable = clipEffect, tab = "Advanced")); + outer ModelSettings modelSettings; +protected + Converters.DmnlInput normalizedWorkload(hasConstantReference = false) "Workload divided by the normal workload" annotation(Placement(visible = true, transformation(origin = {-90, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ConstantConverter parRef(value = referenceWorkload, redeclare replaceable type OutputType = Units.Rate) if hasConstantReference "Constant reference value for the workload (optional)" annotation(Placement(visible = true, transformation(origin = {-110, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Lookup.JanoschekNegative effectOnOutcome(lowerBound = effectMin, upperBound = effectMax, growthRate = steepness) "The multiplicative effect of fatigue on productivity or quality" annotation(Placement(visible = true, transformation(origin = {-10, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.DiscreteDelay.SmoothN fatigue(initialValue = initialFatigue, delayTime = timeToGetFatigued, n = delayOrder, hasConstantDelayTime = true) "Fatigue is an n-th order smooth of overtime" annotation(Placement(visible = true, transformation(origin = {-50, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Clip clippedEffect(minValue = -inf, maxValue = 1, redeclare replaceable type OutputType = Units.Dimensionless, hasConstantLimits = true, strict = strict) if clipEffect "Clip Effect to only allow values within the closed unit interval" annotation(Placement(visible = true, transformation(origin = {50, -30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.PassThrough unchangedEffect if not clipEffect "Leave the effect unchanged" annotation(Placement(visible = true, transformation(origin = {50, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + assert(effectMin < effectMax, "The lower bound for the effect must be smaller than the upper bound", level = AssertionLevel.warning); + assert(effectMax > 1, "The upper bound for the lookup must be above 1—use clipEffect to constrict the effect", level = AssertionLevel.warning); + assert(steepness > 0, "Steepness should by greater than zero", level = AssertionLevel.warning); + connect(fatigue.y, effectOnOutcome.u) annotation(Line(visible = true, origin = {-29, 0}, points = {{-11, 0}, {11, 0}}, color = {0, 0, 127})); + connect(normalizedWorkload.y, fatigue.u) annotation(Line(visible = true, origin = {-70.681, 0}, points = {{-11.319, 0}, {11.319, 0}}, color = {1, 37, 163})); + connect(u, normalizedWorkload.u) annotation(Line(visible = true, origin = {-121.5, -0}, points = {{-23.5, -0}, {23.5, 0}}, color = {0, 0, 128})); + connect(parRef.y, normalizedWorkload.u_reference) annotation(Line(visible = true, origin = {-94.667, 29.333}, points = {{-9.333, 10.667}, {4.667, 10.667}, {4.667, -21.333}}, color = {1, 37, 163})); + connect(u_ref, normalizedWorkload.u_reference) annotation(Line(visible = true, origin = {-108.333, 42.667}, points = {{-36.667, 17.333}, {18.333, 17.333}, {18.333, -34.667}}, color = {0, 0, 128})); + connect(effectOnOutcome.y, unchangedEffect.u) annotation(Line(visible = true, origin = {20, 0}, points = {{-22, 0}, {22, 0}}, color = {1, 37, 163})); + connect(unchangedEffect.y, y) annotation(Line(visible = true, origin = {109, 0}, points = {{-51, 0}, {51, 0}}, color = {1, 37, 163})); + connect(effectOnOutcome.y, clippedEffect.u) annotation(Line(visible = true, origin = {20, -15}, points = {{-22, 15}, {0, 15}, {0, -15}, {22, -15}}, color = {1, 37, 163})); + connect(clippedEffect.y, y) annotation(Line(visible = true, origin = {94.5, -15}, points = {{-36.5, -15}, {-14.5, -15}, {-14.5, 15}, {65.5, 15}}, color = {1, 37, 163})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Fatigue is modeled as a smooth of the normalized input u which is indicating the current workload with regard to capital equipment or workers. The current workload will be normalized by dividing the input u by a constant or a variable reference workload (referenceWorkload or u_ref, respectively). The timeToGetFatigued describes the time constant for the smooth and indicates the lag between beginning to work at an excessive level and the onset of the full effect on productivity (or quality).

+

Janoscheks growth curve is used to model the nonlinear effect of a prolonged work intensity. It describes a negatively sloping s-shaped curve that will pass through the reference point (1,1). The upper bound of the effect (effectMax) must be given slightly above 1.0 as the curve will collapse in all other cases. If the effect is to be clipped at 1.0 then the parameter clipEffect should be set to true.

+

Notes

+ +

See also

+

+SmoothN, +JanoschekNegative +

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, 75}, textColor = {0, 0, 128}, extent = {{-100, -12}, {100, 12}}, textString = "Effect of Fatigue", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {3.406, -40}, textColor = {0, 0, 128}, extent = {{-53.406, -6}, {53.406, 6}}, textString = "Fatigue", fontName = "Lato", textStyle = {TextStyle.Bold}), Line(visible = true, origin = {-9.184, -30}, points = {{-46.394, 0}, {77.285, 0}}, color = {128, 128, 128}, thickness = 1), Line(visible = true, origin = {-55.548, 15.857}, rotation = -270, points = {{-45.857, 0}, {34.143, 0}}, color = {128, 128, 128}, thickness = 1), Text(visible = true, origin = {-64.078, 47.363}, textColor = {0, 0, 128}, extent = {{-9.128, -6}, {9.128, 6}}, textString = "y", fontName = "Lato", textStyle = {TextStyle.Bold}), Line(visible = true, origin = {-16.063, -7.873}, points = {{-39.523, 20.125}, {14.222, 20.125}, {32.628, -20.736}, {77.803, -20.736}}, color = {0, 0, 128}, thickness = 3, smooth = Smooth.Bezier), Line(visible = true, origin = {2.099, -2.709}, points = {{-56.948, 1.709}, {-2.099, 1.709}}, color = {128, 128, 128}, pattern = LinePattern.Dot, thickness = 1), Line(visible = true, origin = {1.314, -32.099}, rotation = -90, points = {{-32.099, 1.709}, {-2.099, 1.709}}, color = {128, 128, 128}, pattern = LinePattern.Dot, thickness = 1), Ellipse(visible = true, origin = {3.097, -1}, lineColor = {255, 0, 0}, fillColor = {255, 0, 0}, fillPattern = FillPattern.Solid, extent = {{-3, -3}, {3, 3}}), Ellipse(visible = true, origin = {-55.199, -1}, lineColor = {128, 128, 128}, fillColor = {128, 128, 128}, fillPattern = FillPattern.Solid, extent = {{-2, -2}, {2, 2}}), Ellipse(visible = true, origin = {3.097, -30}, lineColor = {128, 128, 128}, fillColor = {128, 128, 128}, fillPattern = FillPattern.Solid, extent = {{-2, -2}, {2, 2}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end EffectOfFatigue; diff --git a/BusinessSimulation/MoleculesOfStructure/Blocks/package.mo b/BusinessSimulation/MoleculesOfStructure/Blocks/package.mo new file mode 100644 index 0000000..230bcb3 --- /dev/null +++ b/BusinessSimulation/MoleculesOfStructure/Blocks/package.mo @@ -0,0 +1,16 @@ +within BusinessSimulation.MoleculesOfStructure; + +package Blocks "Subsystems with input and output connectors only (Control and/or information processing)" + extends Icons.Package; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Blocks are information processing systems or (on a lower level of aggregation) processes with information inputs and outputs only. Typical examples will be management seen as a subsystem of a company receiving information from production systems, processing them and sending out information according to decision making policies. On a lower level a simple transformation of information may be modeled as a block.

+

Notes

+ +
+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, origin = {0, 5}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, lineThickness = 7, extent = {{-62.764, -53.47}, {62.764, 53.47}}), Polygon(visible = true, origin = {-38.443, -27.68}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, points = {{-58, 46}, {-29.557, 31.762}, {-58, 17.68}, {-58, 46}}), Polygon(visible = true, origin = {126.557, -27.68}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, points = {{-58, 46}, {-29.557, 31.762}, {-58, 17.68}, {-58, 46}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Blocks; diff --git a/BusinessSimulation/MoleculesOfStructure/Incubators/Account.mo b/BusinessSimulation/MoleculesOfStructure/Incubators/Account.mo new file mode 100644 index 0000000..bb34931 --- /dev/null +++ b/BusinessSimulation/MoleculesOfStructure/Incubators/Account.mo @@ -0,0 +1,83 @@ +within BusinessSimulation.MoleculesOfStructure.Incubators; + +model Account "Basic model of an account with optional interest" + import BusinessSimulation.Types.InitializationOptions; + import BusinessSimulation.Units.Rate; + import BusinessSimulation.Units.Money; + extends Icons.SubsystemIncubator; + extends Interfaces.Basics.OutputTypeChoice(redeclare replaceable type OutputType = Money); + Interfaces.Connectors.StockPort inflow "Increasing the balance of the account" annotation(Placement(visible = true, transformation(origin = {-150, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-100, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.StockPort outflow "Decreasing the balance of the account" annotation(Placement(visible = true, transformation(origin = {150, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {100, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealInput u_plus if hasRateInputs "Rate of inflow increasing the account (or net rate of flow)" annotation(Placement(visible = true, transformation(origin = {-145, 60}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-50, 100}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Interfaces.Connectors.RealInput u_minus if not hasNetRateInput and hasRateInputs "Rate of outflow decreasing the account" annotation(Placement(visible = true, transformation(origin = {-145, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {50, 100}, extent = {{-10, -10}, {10, 10}}, rotation = -810))); + Interfaces.Connectors.RealInput u_interestPlus if withInterest and not hasConstantInterest "Fractional interest rate for positive balances (optional)" annotation(Placement(visible = true, transformation(origin = {-145, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-100, 50}, extent = {{-10, -10}, {10, 10}}, rotation = -1080))); + Interfaces.Connectors.RealInput u_interestMinus if withInterest and not hasConstantInterest "Fractional interest rate for negative balances (optional)" annotation(Placement(visible = true, transformation(origin = {-145, -60}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {100, 50}, extent = {{-10, -10}, {10, 10}}, rotation = -900))); + RealOutput y_intEarned if withInterest "Interest earned (optional)" annotation(Placement(visible = true, transformation(origin = {161.973, -50}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-105, -50}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + RealOutput y_intPaid if withInterest "Interest paid (optional)" annotation(Placement(visible = true, transformation(origin = {161.742, -35}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {105, -50}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + RealOutput y "Balance of the account (e.g. amount in the stock)" annotation(Placement(visible = true, transformation(origin = {162.01, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {0, 104}, extent = {{-10, -10}, {10, 10}}, rotation = -270))); + parameter OutputType initialBalance = 0 "Initial balance of the account"; + parameter Rate interestRatePlus "Constant fractional interest rate for positive balances (optional)" annotation(Dialog(enable = withInterest and hasConstantInterest)); + parameter Rate interestRateMinus "Constant fractional interest rate for negative balances (optional)" annotation(Dialog(enable = withInterest and hasConstantInterest)); + parameter Boolean hasRateInputs = true "= true, if there can transaction rates increasing/decreasing the balance of the account can be given via input connectors" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean hasNetRateInput = false "= true, if the rate of flow is given a net rate (u_plus only)" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean withInterest = false "= true, if positive and negative balances lead to interest earned or paid" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean hasConstantInterest = true "= true, if the optional interest rates are given as constant parameters" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter InitializationOptions init = modelSettings.init "Provide InitializationOptions (Free, FixedValue, SteadyState) (accountBalance.init)" annotation(Evaluate = true, Dialog(tab = "Advanced")); + parameter Boolean strict = true "= true, if strict limits with noEvent(..) (positiveBalance.strict)" annotation(Evaluate = true, Dialog(tab = "Advanced")); + outer ModelSettings modelSettings; +protected + Stocks.InformationLevel accountBalance(hasStockInfoOutput = false, useAssert = false, causeError = false, initialValue = initialBalance, init = init) "Balance of the account" annotation(Placement(visible = true, transformation(origin = {-0, 20}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + SourcesOrSinks.ExogenousChange netFlow if hasRateInputs "Net flow to or from the account" annotation(Placement(visible = true, transformation(origin = {-50, 20}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Gain negativeRate(c = -1) if not hasNetRateInput and hasRateInputs "The rate of decrease is turned into a negative rate" annotation(Placement(visible = true, transformation(origin = {-110, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Add_2 netRate if not hasNetRateInput and hasRateInputs "Net rate of flow" annotation(Placement(visible = true, transformation(origin = {-80, 45}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.PassThrough netRateInput if hasNetRateInput and hasRateInputs "Input u_plus net rate of flow" annotation(Placement(visible = true, transformation(origin = {-80, 80}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ConstantConverterRate interestPlus(value = interestRatePlus) if withInterest and hasConstantInterest "Constant rate of interest for positive balances" annotation(Placement(visible = true, transformation(origin = {-120, -50}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ConstantConverterRate interestMinus(value = interestRateMinus) if withInterest and hasConstantInterest "Constant rate of interest for negative balances" annotation(Placement(visible = true, transformation(origin = {-120, -80}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ZeroIfNegative positiveBalance(strict = strict) if withInterest "Positive balance or zero" annotation(Placement(visible = true, transformation(origin = {-50, -10}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Converters.ZeroIfNegative negativeBalance(strict = strict) if withInterest "Negative balance or zero" annotation(Placement(visible = true, transformation(origin = {60, 15}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Gain invertedBalance(c = -1) if withInterest annotation(Placement(visible = true, transformation(origin = {30, 15}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Product_2 rateDecline if withInterest "Rate of decline" annotation(Placement(visible = true, transformation(origin = {70, -10}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + SourcesOrSinks.Decline interestPaid if withInterest "Interest decreasing the balance" annotation(Placement(visible = true, transformation(origin = {40, -30}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + SourcesOrSinks.Growth interestEarned if withInterest "Interest payments increasing the balance" annotation(Placement(visible = true, transformation(origin = {-36.649, -45}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Product_2 rateIncrease if withInterest "Rate of decline" annotation(Placement(visible = true, transformation(origin = {-80, -25}, extent = {{-10, -10}, {10, 10}}, rotation = 360))); +equation + connect(u_minus, negativeRate.u) annotation(Line(visible = true, origin = {-131.5, 40}, points = {{-13.5, 0}, {13.5, 0}}, color = {0, 0, 128})); + connect(negativeRate.y, netRate.u2) annotation(Line(visible = true, origin = {-95, 40}, points = {{-7, 0}, {7, 0}}, color = {1, 37, 163})); + connect(u_plus, netRate.u1) annotation(Line(visible = true, origin = {-108.25, 55}, points = {{-36.75, 5}, {8.25, 5}, {8.25, -5}, {20.25, -5}}, color = {0, 0, 128})); + connect(u_plus, netRateInput.u) annotation(Line(visible = true, origin = {-108.25, 70}, points = {{-36.75, -10}, {8.25, -10}, {8.25, 10}, {20.25, 10}}, color = {0, 0, 128})); + connect(netRateInput.y, netFlow.u) annotation(Line(visible = true, origin = {-60.667, 63.333}, points = {{-11.333, 16.667}, {5.667, 16.667}, {5.667, -33.333}}, color = {1, 37, 163})); + connect(netRate.y, netFlow.u) annotation(Line(visible = true, origin = {-60.667, 40}, points = {{-11.333, 5}, {5.667, 5}, {5.667, -10}}, color = {1, 37, 163})); + connect(netFlow.massPort, accountBalance.inflow) annotation(Line(visible = true, origin = {-25, 10}, points = {{-15, 10}, {0, 10}, {0, 10}, {15, 10}}, color = {128, 0, 128})); + connect(accountBalance.y, y) annotation(Line(visible = true, origin = {57.337, 36.8}, points = {{-52.337, -6.4}, {-52.337, 3.2}, {104.673, 3.2}}, color = {1, 37, 163})); + connect(accountBalance.y2, positiveBalance.u) annotation(Line(visible = true, origin = {-20.875, 2.5}, points = {{10.375, 12.5}, {5.375, 12.5}, {5.375, -12.5}, {-21.125, -12.5}}, color = {1, 37, 163})); + connect(accountBalance.y1, invertedBalance.u) annotation(Line(visible = true, origin = {16.25, 15}, points = {{-5.75, 0}, {5.75, 0}}, color = {1, 37, 163})); + connect(invertedBalance.y, negativeBalance.u) annotation(Line(visible = true, origin = {45, 15}, points = {{-7, 0}, {7, -0}}, color = {1, 37, 163})); + connect(interestPaid.massPort, accountBalance.outflow) annotation(Line(visible = true, origin = {15, -10}, points = {{15, -20}, {0, -20}, {0, 30}, {-5, 30}}, color = {128, 0, 128})); + connect(rateDecline.y, interestPaid.u) annotation(Line(visible = true, origin = {50.667, -13.333}, points = {{11.333, 3.333}, {-5.667, 3.333}, {-5.667, -6.667}}, color = {1, 37, 163})); + connect(negativeBalance.y, rateDecline.u1) annotation(Line(visible = true, origin = {82, 5}, points = {{-14, 10}, {8, 10}, {8, -10}, {-4, -10}}, color = {1, 37, 163})); + connect(interestMinus.y, rateDecline.u2) annotation(Line(visible = true, origin = {46, -47.5}, points = {{-160, -32.5}, {54, -32.5}, {54, 32.5}, {32, 32.5}}, color = {1, 37, 163})); + connect(u_interestMinus, rateDecline.u2) annotation(Line(visible = true, origin = {33.25, -37.5}, points = {{-178.25, -22.5}, {66.75, -22.5}, {66.75, 22.5}, {44.75, 22.5}}, color = {0, 0, 128})); + connect(interestPlus.y, rateIncrease.u2) annotation(Line(visible = true, origin = {-100.5, -40}, points = {{-13.5, -10}, {0.5, -10}, {0.5, 10}, {12.5, 10}}, color = {1, 37, 163})); + connect(positiveBalance.y, rateIncrease.u1) annotation(Line(visible = true, origin = {-86.5, -15}, points = {{28.5, 5}, {-13.5, 5}, {-13.5, -5}, {-1.5, -5}}, color = {1, 37, 163})); + connect(u_interestPlus, rateIncrease.u2) annotation(Line(visible = true, origin = {-108.25, -35}, points = {{-36.75, -5}, {8.25, -5}, {8.25, 5}, {20.25, 5}}, color = {0, 0, 128})); + connect(rateIncrease.y, interestEarned.u) annotation(Line(visible = true, origin = {-51.766, -28.333}, points = {{-20.234, 3.333}, {10.117, 3.333}, {10.117, -6.667}}, color = {1, 37, 163})); + connect(interestEarned.massPort, accountBalance.inflow) annotation(Line(visible = true, origin = {-19.162, -12.5}, points = {{-7.487, -32.5}, {-0.838, -32.5}, {-0.838, 32.5}, {9.162, 32.5}}, color = {128, 0, 128})); + connect(accountBalance.outflow, outflow) annotation(Line(visible = true, origin = {47.5, 10}, points = {{-37.5, 10}, {-32.5, 10}, {-32.5, -10}, {102.5, -10}}, color = {128, 0, 128})); + connect(inflow, accountBalance.inflow) annotation(Line(visible = true, origin = {-50, 10}, points = {{-100, -10}, {30, -10}, {30, 10}, {40, 10}}, color = {128, 0, 128})); + connect(interestPaid.y2, y_intPaid) annotation(Line(visible = true, origin = {106.121, -35}, points = {{-55.621, 0}, {55.621, 0}}, color = {1, 37, 163})); + connect(interestEarned.y1, y_intEarned) annotation(Line(visible = true, origin = {67.912, -50}, points = {{-94.061, 0}, {94.061, 0}}, color = {1, 37, 163})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output y reports the balance of an account that is increased or decreased by flows connected to the stock ports or at given rates (u_plus and u_minus respectively) if hasRateInputs = true. When there are interest payments (withInterest = true) positive and negative balances of the account will lead to interest earned and interest paid, respectively. The associated fractional rates can be given either as constants or as variable inputs.

+

Notes

+ +

See also

+

+Reservoir +

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {-37.335, -106.294}, points = {{47.335, 101.43}, {57.335, 87.889}, {47.335, 79.179}}, color = {192, 192, 192}, thickness = 2, smooth = Smooth.Bezier), Text(visible = true, origin = {0, 75}, textColor = {76, 112, 136}, extent = {{-100, -12}, {100, 12}}, textString = "Account", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Line(visible = true, origin = {5.84, -0.234}, points = {{0, 0}, {28.109, 0}}, color = {0, 128, 0}, thickness = 5), Ellipse(visible = true, origin = {19.978, 0}, lineColor = {0, 128, 0}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 0.5, extent = {{-4.138, -4.138}, {4.138, 4.138}}), Rectangle(visible = true, lineColor = {255, 0, 0}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 3, extent = {{-10, -10}, {10, 10}}), Polygon(visible = true, origin = {34.453, -0.275}, lineColor = {0, 128, 0}, fillColor = {0, 128, 0}, fillPattern = FillPattern.Solid, points = {{-2.773, 3.823}, {-2.773, -3.863}, {5.547, 0.041}}), Line(visible = true, origin = {-46.16, -0.234}, points = {{0, 0}, {28.109, 0}}, color = {0, 128, 0}, thickness = 5), Ellipse(visible = true, origin = {-32.022, 0}, lineColor = {0, 128, 0}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 0.5, extent = {{-4.138, -4.138}, {4.138, 4.138}}), Polygon(visible = true, origin = {-17.547, -0.275}, lineColor = {0, 128, 0}, fillColor = {0, 128, 0}, fillPattern = FillPattern.Solid, points = {{-2.773, 3.823}, {-2.773, -3.863}, {5.547, 0.041}}), Line(visible = true, origin = {0, -48.109}, rotation = -270, points = {{0, 0}, {28.109, 0}}, color = {192, 192, 192}, thickness = 5), Ellipse(visible = true, origin = {0, -32.008}, rotation = -270, lineColor = {192, 192, 192}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 0.5, extent = {{-4.138, -4.138}, {4.138, 4.138}}), Polygon(visible = true, origin = {0.149, -18.15}, rotation = -270, lineColor = {192, 192, 192}, fillColor = {192, 192, 192}, fillPattern = FillPattern.Solid, points = {{-2.773, 3.823}, {-2.773, -3.863}, {5.547, 0.041}}), Polygon(visible = true, origin = {0.02, -48.613}, rotation = -450, lineColor = {192, 192, 192}, fillColor = {192, 192, 192}, fillPattern = FillPattern.Solid, points = {{-2.773, 3.823}, {-2.773, -3.863}, {5.547, 0.041}}), Polygon(visible = true, origin = {7.966, -28.246}, rotation = -153.312, lineColor = {192, 192, 192}, fillColor = {192, 192, 192}, fillPattern = FillPattern.Solid, points = {{-2.773, 2.672}, {-2.773, -2.623}, {3.945, -0.02}}), Text(visible = true, origin = {-42.691, -60.518}, textColor = {192, 192, 192}, extent = {{-35.466, -6}, {35.466, 6}}, textString = "interestRate", fontName = "Lato", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {-32.399, 14}, textColor = {0, 128, 0}, extent = {{-9.174, -6}, {9.174, 6}}, textString = "+", fontName = "Lato Black"), Text(visible = true, origin = {20, 14}, textColor = {0, 128, 0}, extent = {{-9.174, -6}, {9.174, 6}}, textString = "–", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Line(visible = true, origin = {-80.11, 43.016}, rotation = -8.77, points = {{71.259, -85.862}, {74.2, -75.29}, {81.612, -69.18}}, color = {192, 192, 192}, thickness = 2, smooth = Smooth.Bezier), Polygon(visible = true, origin = {-8.034, -36.411}, rotation = -153.312, lineColor = {192, 192, 192}, fillColor = {192, 192, 192}, fillPattern = FillPattern.Solid, points = {{2.773, -2.672}, {2.773, 2.623}, {-3.945, 0.02}})}), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Account; diff --git a/BusinessSimulation/MoleculesOfStructure/Incubators/package.mo b/BusinessSimulation/MoleculesOfStructure/Incubators/package.mo new file mode 100644 index 0000000..77d4bfa --- /dev/null +++ b/BusinessSimulation/MoleculesOfStructure/Incubators/package.mo @@ -0,0 +1,12 @@ +within BusinessSimulation.MoleculesOfStructure; + +package Incubators "Subssystems with stock ports only receiving and providing physical entities usually in a modified form" + extends Icons.Package; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Incubators are subsystems that can be seen as more aggregate versions of a stocks/reservoirs. They receive physical entities from other systems or provide entities to be \"withdrawn\". Entities stored in an incubator will typically be transformed while they are stored within the system.

+

An account which allows physical deposits and withdrawals (e.g. a checking account) can be seen as a basic example: While money is stored in the account, interest payments are received increasing the balance of the account.

+

+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, origin = {0, 5}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, lineThickness = 7, extent = {{-62.764, -53.47}, {62.764, 53.47}}), Rectangle(visible = true, origin = {-62.781, 4.645}, lineColor = {255, 255, 255}, fillColor = {76, 112, 136}, fillPattern = FillPattern.Solid, lineThickness = 7, extent = {{-10.968, -11.451}, {10.968, 11.451}}), Rectangle(visible = true, origin = {62.219, 4.645}, lineColor = {255, 255, 255}, fillColor = {76, 112, 136}, fillPattern = FillPattern.Solid, lineThickness = 7, extent = {{-10.968, -11.451}, {10.968, 11.451}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Incubators; diff --git a/BusinessSimulation/MoleculesOfStructure/InformationProcessing/AggregatePerformance.mo b/BusinessSimulation/MoleculesOfStructure/InformationProcessing/AggregatePerformance.mo new file mode 100644 index 0000000..6dfb374 --- /dev/null +++ b/BusinessSimulation/MoleculesOfStructure/InformationProcessing/AggregatePerformance.mo @@ -0,0 +1,46 @@ +within BusinessSimulation.MoleculesOfStructure.InformationProcessing; + +model AggregatePerformance "Aggregate the information received from a set of performance indicators" + import BusinessSimulation.Types.AggregateFunctions; + extends Interfaces.PartialConverters.InformationProcessing_SO(redeclare replaceable type OutputType = Units.Dimensionless); + Interfaces.Connectors.RealMultiInput[nin] u "Vector of performance indicator inputs" annotation(Placement(visible = true, transformation(origin = {-145, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-110, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealMultiInput[nin] u_weights if useWeights and not hasConstantWeights "Vector of weights (optional)" annotation(Placement(visible = true, transformation(origin = {-145, 60}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {0, 110}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + parameter Integer nin(min = 1) = 2 "Number of performance indicator inputs (length of input vector)" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter AggregateFunctions func = BusinessSimulation.Types.AggregateFunctions.arithmeticMean "Function to apply for aggregation" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Real[:] weights = ones(nin) "Constant weights to be used for performance inputs" annotation(Dialog(enable = useWeights and hasConstantWeights)); + parameter Boolean useWeights = false "= true, if the output is to be a weighted arithmetic mean" annotation(Dialog(group = "Structural Parameters")); + parameter Boolean hasConstantWeights = true "= true, if the weights are constant" annotation(Dialog(group = "Structural Parameters", enable = useWeights)); +protected + Converters.Vector.ConstantConverter parWeights(value = weights) if hasConstantWeights and useWeights "Constant weights" annotation(Placement(visible = true, transformation(origin = {-90, 80}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Vector.ArithmeticMean arithAvgPerformance(useWeights = useWeights, hasConstantWeights = false, nin = nin, redeclare replaceable type OutputType = Units.Dimensionless) if func == AggregateFunctions.arithmeticMean "(Weighted) arithmetic mean" annotation(Placement(visible = true, transformation(origin = {-20, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Vector.GeometricMean geomAvgPerformance(nin = nin, useWeights = useWeights, hasConstantWeights = false, redeclare replaceable type OutputType = Units.Dimensionless) if func == AggregateFunctions.geometricMean "(Weighted) geometric mean" annotation(Placement(visible = true, transformation(origin = {-20, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Vector.Max maximumPerformance(nin = nin, redeclare replaceable type OutputType = Units.Dimensionless) if func == AggregateFunctions.maximum "Maximum of the performance inputs" annotation(Placement(visible = true, transformation(origin = {-20, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Vector.Min minimumPerformance(nin = nin, redeclare replaceable type OutputType = Units.Dimensionless) if func == AggregateFunctions.minimum "Minimum of the performance inputs" annotation(Placement(visible = true, transformation(origin = {-20, -80}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(parWeights.y, geomAvgPerformance.u_weights) annotation(Line(visible = true, origin = {-41.333, 69.333}, points = {{-42.667, 10.667}, {21.333, 10.667}, {21.333, -21.333}}, color = {1, 37, 163})); + connect(u_weights, geomAvgPerformance.u_weights) annotation(Line(visible = true, origin = {-61.667, 56}, points = {{-83.333, 4}, {41.667, 4}, {41.667, -8}}, color = {0, 0, 128})); + connect(u, arithAvgPerformance.u) annotation(Line(visible = true, origin = {-86.5, 0}, points = {{-58.5, 0}, {58.5, 0}}, color = {0, 0, 128})); + connect(u, geomAvgPerformance.u) annotation(Line(visible = true, origin = {-83.25, 20}, points = {{-61.75, -20}, {3.25, -20}, {3.25, 20}, {55.25, 20}}, color = {0, 0, 128})); + connect(u, maximumPerformance.u) annotation(Line(visible = true, origin = {-83.25, -20}, points = {{-61.75, 20}, {3.25, 20}, {3.25, -20}, {55.25, -20}}, color = {0, 0, 128})); + connect(u, minimumPerformance.u) annotation(Line(visible = true, origin = {-83.25, -40}, points = {{-61.75, 40}, {3.25, 40}, {3.25, -40}, {55.25, -40}}, color = {0, 0, 128})); + connect(geomAvgPerformance.y, y) annotation(Line(visible = true, origin = {67, 20}, points = {{-79, 20}, {-7, 20}, {-7, -20}, {93, -20}}, color = {1, 37, 163})); + connect(arithAvgPerformance.y, y) annotation(Line(visible = true, origin = {74, 0}, points = {{-86, 0}, {86, 0}}, color = {1, 37, 163})); + connect(maximumPerformance.y, y) annotation(Line(visible = true, origin = {67, -20}, points = {{-79, -20}, {-7, -20}, {-7, 20}, {93, 20}}, color = {1, 37, 163})); + connect(minimumPerformance.y, y) annotation(Line(visible = true, origin = {67, -40}, points = {{-79, -40}, {-7, -40}, {-7, 40}, {93, 40}}, color = {1, 37, 163})); + connect(parWeights.y, arithAvgPerformance.u_weights) annotation(Line(visible = true, origin = {-40.8, 41.6}, points = {{-43.2, 38.4}, {0.8, 38.4}, {0.8, -21.6}, {20.8, -21.6}, {20.8, -33.6}}, color = {1, 37, 163})); + connect(u_weights, arithAvgPerformance.u_weights) annotation(Line(visible = true, origin = {-47, 33.6}, points = {{-98, 26.4}, {7, 26.4}, {7, -13.6}, {27, -13.6}, {27, -25.6}}, color = {0, 0, 128})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output y is given by applying an aggregate function (e.g. →Min, →GeometricMean, →ArithmeticMean, →Max) to a set of performance indicator inputs u. Optionally a vector of weights can be given as constant weights or external input u_weights, so that weighted averages can be used.

+

Notes

+ +

See also

+

BasicOrientation, +PerformanceIndicator +

+"), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, -25}, textColor = {0, 0, 128}, extent = {{-96.456, -12}, {96.456, 12}}, textString = "Performance", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, textColor = {0, 0, 128}, extent = {{-96.456, -12}, {96.456, 12}}, textString = "Aggregate", fontName = "Lato Black", textStyle = {TextStyle.Bold})})); +end AggregatePerformance; diff --git a/BusinessSimulation/MoleculesOfStructure/InformationProcessing/BasicOrientation.mo b/BusinessSimulation/MoleculesOfStructure/InformationProcessing/BasicOrientation.mo new file mode 100644 index 0000000..741e16b --- /dev/null +++ b/BusinessSimulation/MoleculesOfStructure/InformationProcessing/BasicOrientation.mo @@ -0,0 +1,83 @@ +within BusinessSimulation.MoleculesOfStructure.InformationProcessing; + +model BasicOrientation "Assessing a system's performance and sustainability according to basic orientors" + import BusinessSimulation.Types.{BasicOrientors,AggregateFunctions}; + extends Icons.InformationProcessing; + Interfaces.Connectors.RealMultiInput u_weights[nPerf] if not hasConstantWeights "Weights to be used for performance measurement" annotation(Placement(visible = true, transformation(origin = {-145, 60}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {0, 110}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Interfaces.Connectors.RealMultiInput u[BasicOrientors] "Basic orientors to monitor a system's sustainability" annotation(Placement(visible = true, transformation(origin = {-145, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-110, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealInput u_psy if hasSentinentBeings "Psychological needs indicator (optional)" annotation(Placement(visible = true, transformation(origin = {-145, -60}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-110, 50}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealOutput y_perf(final unit = "1") "Aggregate performance score for the monitored system" annotation(Placement(visible = true, transformation(origin = {160, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {110, 50}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealOutput y_sus(final unit = "1") "Aggregate degree of sustainability for the monitored system" annotation(Placement(visible = true, transformation(origin = {160, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {110, -50}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + parameter Real[:] weights = ones(nPerf) "Weights for calculating a weighted average performance score (default = equal weights)" annotation(Dialog(enable = hasConstantWeights)); + parameter Boolean hasSentinentBeings = false "= true, if the system comprises sentinent beings with psychological needs" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean hasConstantWeights = true "= true, if constant weights are to be used for performance aggregation" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter AggregateFunctions func = BusinessSimulation.Types.AggregateFunctions.arithmeticMean "Function to apply for aggregation (aggregatePerformance.func)"; +protected + constant Integer nOrientors = size(u, 1) "Number of basic orientors valid for any system"; + parameter Integer nPerf = if hasSentinentBeings then nOrientors + 1 else nOrientors "Number of orientors used for perfomance calculation" annotation(Evaluate = true, Dialog(group = "Initialization", enable = false)); + AggregatePerformance aggregatePerformance(useWeights = true, hasConstantWeights = false, nin = nPerf, func = func) annotation(Placement(visible = true, transformation(origin = {-20, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.PassThrough sustainabilityNonSentinent if not hasSentinentBeings "Sustainability score for systems without sentinent beings" annotation(Placement(visible = true, transformation(origin = {10, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Min sustainabilitySentinent if hasSentinentBeings "Sustainability score for systems with sentinent beings" annotation(Placement(visible = true, transformation(origin = {10, -65}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Vector.ConstantConverter parWeights(redeclare final type OutputType = Units.Dimensionless, final value = weights) if hasConstantWeights "Weights for performance score" annotation(Placement(visible = true, transformation(origin = {-120, 80}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Vector.Min basicSustainability(redeclare final type OutputType = Units.Dimensionless, nin = nOrientors) "Sustainability score according to basic orientors" annotation(Placement(visible = true, transformation(origin = {-50, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(u, basicSustainability.u) annotation(Line(visible = true, origin = {-101.5, -40}, points = {{-43.5, 0}, {43.5, 0}}, color = {0, 0, 128})); + connect(basicSustainability.y, sustainabilityNonSentinent.u) annotation(Line(visible = true, origin = {-20, -40}, points = {{-22, 0}, {22, 0}}, color = {1, 37, 163})); + connect(sustainabilityNonSentinent.y, y_sus) annotation(Line(visible = true, origin = {89, -40}, points = {{-71, 0}, {71, 0}}, color = {1, 37, 163})); + connect(u_psy, sustainabilitySentinent.u1) annotation(Line(visible = true, origin = {-71.5, -60}, points = {{-73.5, 0}, {73.5, 0}}, color = {0, 0, 128})); + connect(sustainabilitySentinent.y, y_sus) annotation(Line(visible = true, origin = {74.5, -52.5}, points = {{-56.5, -12.5}, {-14.5, -12.5}, {-14.5, 12.5}, {85.5, 12.5}}, color = {1, 37, 163})); + connect(basicSustainability.y, sustainabilitySentinent.u2) annotation(Line(visible = true, origin = {-27.5, -55}, points = {{-14.5, 15}, {-7.5, 15}, {-7.5, -15}, {29.5, -15}}, color = {1, 37, 163})); + connect(u, aggregatePerformance.u[1:6]) annotation(Line(visible = true, origin = {-94, 0}, points = {{-51, -40}, {-6, -40}, {-6, 40}, {63, 40}}, color = {0, 0, 128})); + connect(u_psy, aggregatePerformance.u[7]) annotation(Line(visible = true, origin = {-84, -10}, points = {{-61, -50}, {4, -50}, {4, 50}, {53, 50}}, color = {0, 0, 128})); + connect(parWeights.y, aggregatePerformance.u_weights) annotation(Line(visible = true, origin = {-51.333, 70.333}, points = {{-62.667, 9.667}, {31.333, 9.667}, {31.333, -19.333}}, color = {1, 37, 163})); + connect(aggregatePerformance.y, y_perf) annotation(Line(visible = true, origin = {75.5, 40}, points = {{-84.5, 0}, {84.5, 0}}, color = {1, 37, 163})); + connect(u_weights, aggregatePerformance.u_weights) annotation(Line(visible = true, origin = {-61.667, 57}, points = {{-83.333, 3}, {41.667, 3}, {41.667, -6}}, color = {0, 0, 128})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Basic Orientation will provide two outputs: an aggregate performance score (y_perf) and a score indicating the minimum sustainability (y_sus) according to a set of basic orientor inputs u.

+

While a system is free to emphasize certain orientors over others (i.e. freedom in the choice of weights according to preferences/strategies), no system can excape the pressures put upon it from its environment and other systems therein. In a much cited report to the Balaton Group Hartmut Bossel [22] identified six basic orientors, that will guide a (living) systems evolution in order to maintain viability [10, p. 185]:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Basic OrientorDescription
EXISTENCEThe system must be compatible with, and able to exist in the normal environmental state. The information, energy, and material inputs necessary to sustain the system must be available.
EFFECTIVENESSThe system should on balance (over the long-term) be effective (not necessarily efficient) in its efforts to secure scarce resources (information, matter, energy) from, and to exert influence on its environment. 
FREEDOM OF ACTIONThe system must have the ability to cope in various ways with the challanges posed by environmental variety. 
SECURITYThe system must be able to protect itself from the detrimental effects of environmental variability, i.e. variable, fluctuating, and unpredictable conditions outside the normal environmental state. 
ADAPTABILITYThe system should be able to learn, adapt, and self-organize in order to generate more appropriate responses to challenges posed by environmental change.
COEXISTENCEThe system must be able to modify its behavior to account for behavior and interestes (orientors) of other (actor) systems in its environment. 
+

Each of the six basic dimensions highlights a necessary aspect of viability, that cannot be compensated by a good score in another dimension. Accordingly, the sustainability score according to the inputs for the basic orientors will be aggregated using the min operator. fo further details, see [10, Chapter 4].

+

Notes

+ +

See also

+

+AggregatePerformance, +PerformanceIndicatorDmnlInput

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {0, 0, 128}, extent = {{-96.456, -12}, {96.456, 12}}, textString = "Basic", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {0, -25}, textColor = {0, 0, 128}, extent = {{-96.456, -12}, {96.456, 12}}, textString = "Orientation", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end BasicOrientation; diff --git a/BusinessSimulation/MoleculesOfStructure/InformationProcessing/FinancialReporting.mo b/BusinessSimulation/MoleculesOfStructure/InformationProcessing/FinancialReporting.mo new file mode 100644 index 0000000..7cead3f --- /dev/null +++ b/BusinessSimulation/MoleculesOfStructure/InformationProcessing/FinancialReporting.mo @@ -0,0 +1,36 @@ +within BusinessSimulation.MoleculesOfStructure.InformationProcessing; + +model FinancialReporting "Periodic reporting of a financial flow for the past accounting period" + import BusinessSimulation.Units.Time; + extends Interfaces.PartialConverters.InformationProcessing_SO; + Interfaces.Connectors.RealInput u "Actual rate of financial flow" annotation(Placement(visible = true, transformation(origin = {-145, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-113.106, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + // parameter + parameter Time reportingPeriod = 1 "Accounting period"; + parameter Time offsetFirstReporting = reportingPeriod "The first report will be issued at startTime + offsetFirstRporting"; + parameter Real initialValue = 0 "Initial reported value (value to be reported until the first reporting date)"; +protected + Converters.Gap gap annotation(Placement(visible = true, transformation(origin = {70, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.DiscreteDelay.Sampler previousValue(samplingPeriod = reportingPeriod, offsetStartTime = offsetFirstReporting, initialValue = 0) "Reported flow for the previous reporting period" annotation(Placement(visible = true, transformation(origin = {20, -20}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.DiscreteDelay.Sampler currentValue(samplingPeriod = reportingPeriod, offsetStartTime = offsetFirstReporting, initialValue = initialValue) "Reported actual flow at the end of each reporting period" annotation(Placement(visible = true, transformation(origin = {20, 20}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.DiscreteDelay.DelayFixed delayedAccountingFlow(delayTime = reportingPeriod, initialValue = 0, hasConstantDelayTime = true, hasExogenousHistory = false, init = BusinessSimulation.Types.InitializationOptions.FixedValue) "Accounting flow delayed for one accounting period" annotation(Placement(visible = true, transformation(origin = {-90, -20}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + SourcesOrSinks.ExogenousChange cumulating_previous "Previous flow" annotation(Placement(visible = true, transformation(origin = {-60, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Stocks.InformationLevel accruedPreviousFlow(initialValue = 0, init = BusinessSimulation.Types.InitializationOptions.FixedValue, redeclare replaceable type OutputType = OutputType) "Cumulative value for the delayed flow" annotation(Placement(visible = true, transformation(origin = {-10, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + SourcesOrSinks.ExogenousChange cumulating_actual "Current flow" annotation(Placement(visible = true, transformation(origin = {-60, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Stocks.InformationLevel accruedFlow(init = BusinessSimulation.Types.InitializationOptions.FixedValue, redeclare replaceable type OutputType = OutputType) "Cumulative flow for the reporting period" annotation(Placement(visible = true, transformation(origin = {-10, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(u, delayedAccountingFlow.u) annotation(Line(visible = true, origin = {-113.588, -10}, points = {{-31.412, 10}, {5.841, 10}, {5.841, -10}, {14.226, -10}}, color = {0, 0, 127})); + connect(delayedAccountingFlow.y, cumulating_previous.u) annotation(Line(visible = true, origin = {-70.155, -23.333}, points = {{-10.311, 3.333}, {5.155, 3.333}, {5.155, -6.667}}, color = {0, 0, 127})); + connect(u, cumulating_actual.u) annotation(Line(visible = true, origin = {-96.158, 7.3}, points = {{-48.842, -7.3}, {-18.364, -7.3}, {-18.364, 12.7}, {31.158, 12.7}, {31.158, 2.7}}, color = {0, 0, 127})); + connect(cumulating_actual.massPort, accruedFlow.inflow) annotation(Line(visible = true, origin = {-35, 0}, points = {{-15, 0}, {15, 0}}, color = {128, 0, 128})); + connect(accruedFlow.y, currentValue.u) annotation(Line(visible = true, origin = {0.213, 16.8}, points = {{-5.213, -6.4}, {-5.213, 3.2}, {10.425, 3.2}}, color = {0, 0, 127})); + connect(accruedPreviousFlow.y, previousValue.u) annotation(Line(visible = true, origin = {0.213, -23.2}, points = {{-5.213, -6.4}, {-5.213, 3.2}, {10.425, 3.2}}, color = {0, 0, 127})); + connect(cumulating_previous.massPort, accruedPreviousFlow.inflow) annotation(Line(visible = true, origin = {-35, -40}, points = {{-15, 0}, {15, 0}}, color = {128, 0, 128})); + connect(currentValue.y, gap.u1) annotation(Line(visible = true, origin = {43.091, 12.5}, points = {{-13.557, 7.5}, {-3.091, 7.5}, {-3.091, -7.5}, {18.909, -7.5}}, color = {0, 0, 127})); + connect(previousValue.y, gap.u2) annotation(Line(visible = true, origin = {43.091, -12.5}, points = {{-13.557, -7.5}, {-3.091, -7.5}, {-3.091, 7.5}, {18.909, 7.5}}, color = {0, 0, 127})); + connect(gap.y, y) annotation(Line(visible = true, origin = {88.681, 0}, points = {{-11.319, 0}, {71.319, 0}}, color = {0, 0, 127})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

In a continuous time simulation financial flows will show their current value at any time. While this is a clear advantage of a simulation—we will never know the true current rates in reality—we would often like to show the average flow with regard to a defined accounting period as it is typical for financial reporting (e.g. at the end of an acounting period the Finance Department will report a single value for the average revenue in the past period in monetary units per period).

+

The FinancialReporting component will report such an averaged flow by showing the difference between the actual flow and the flow delayed by exactly the length of the accounting period. This difference will be sampled at the end of any accounting period during the simulation time horizon. During the accounting period the last reported value will be kept constant.

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, -25}, textColor = {0, 0, 128}, extent = {{-96.456, -12}, {96.456, 12}}, textString = "Reporting", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, textColor = {0, 0, 128}, extent = {{-96.456, -12}, {96.456, 12}}, textString = "Financial", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -60}, {148.5, 40}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end FinancialReporting; diff --git a/BusinessSimulation/MoleculesOfStructure/InformationProcessing/PresentValue.mo b/BusinessSimulation/MoleculesOfStructure/InformationProcessing/PresentValue.mo new file mode 100644 index 0000000..c41dbb9 --- /dev/null +++ b/BusinessSimulation/MoleculesOfStructure/InformationProcessing/PresentValue.mo @@ -0,0 +1,37 @@ +within BusinessSimulation.MoleculesOfStructure.InformationProcessing; + +block PresentValue "Calculates the present value of a stream of cash flows" + import BusinessSimulation.Units.{Rate,Time}; + extends Interfaces.PartialConverters.InformationProcessing_SO; + Interfaces.Connectors.RealInput u "Cash stream input" annotation(Placement(visible = true, transformation(origin = {-145, 85}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-110, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealInput u_r if not hasConstantRate "Discount rate input" annotation(Placement(visible = true, transformation(origin = {-145, 20}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-110, -50}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + parameter Real initialValue = 0 "Initial PV at start time"; + parameter Rate rate = 0.05 "Constant discount rate per period (optional)" annotation(Dialog(enable = hasConstantRate)); + parameter Boolean hasConstantRate = false "If true the discount rate is a constant parameter" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean isCCR = true "If false the given rate is transformed to a continuously compounding rate" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); +protected + Converters.AccumulationFunction futureValueFactor(isCCR = isCCR, redeclare replaceable type OutputType = Units.Dimensionless) "Accumulation function a(t)" annotation(Placement(visible = true, transformation(origin = {-60, 20}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Division discountedStream "Discounted stream of cash flows" annotation(Placement(visible = true, transformation(origin = {0, 80}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Stocks.InformationLevel PV(initialValue = initialValue, init = BusinessSimulation.Types.InitializationOptions.FixedValue) "Present Value for stream of cash flows" annotation(Placement(visible = true, transformation(origin = {90, 5}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + SourcesOrSinks.Growth increasingPV "Present value is accumulation of discounted CF-stream" annotation(Placement(visible = true, transformation(origin = {50, 5}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ConstantConverterRate parRate(value = rate) if hasConstantRate "Discount rate" annotation(Placement(visible = true, transformation(origin = {-130, -10}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(increasingPV.massPort, PV.inflow) annotation(Line(visible = true, origin = {70, 5}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(PV.y1, y) annotation(Line(visible = true, origin = {112.625, 21.5}, points = {{-12.125, -21.5}, {7.375, -21.5}, {7.375, -21.5}, {47.375, -21.5}}, color = {0, 0, 127})); + connect(u_r, futureValueFactor.u) annotation(Line(visible = true, origin = {-106.5, 20}, points = {{-38.5, 0}, {38.5, 0}}, color = {0, 0, 128})); + connect(parRate.y, futureValueFactor.u) annotation(Line(visible = true, origin = {-98, 5}, points = {{-26, -15}, {-2, -15}, {-2, 15}, {30, 15}}, color = {1, 37, 163})); + connect(u, discountedStream.u1) annotation(Line(visible = true, origin = {-76.5, 85}, points = {{-68.5, 0}, {68.5, 0}}, color = {0, 0, 128})); + connect(futureValueFactor.y, discountedStream.u2) annotation(Line(visible = true, origin = {-25, 47.5}, points = {{-27, -27.5}, {-5, -27.5}, {-5, 27.5}, {17, 27.5}}, color = {1, 37, 163})); + connect(discountedStream.y, increasingPV.u) annotation(Line(visible = true, origin = {32.667, 58.333}, points = {{-24.667, 21.667}, {12.333, 21.667}, {12.333, -43.333}}, color = {1, 37, 163})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The PresentValue component will accumulate a discounted cash flow stream. The discount factor at any time is given by the accumulation function a(t) for a given interest rate, that may be either a constant (rate) or a variable input (u_r).

Acknowledgements

+

Additional information can be found on Jim Hines' Molecules of Structure website: →Present Value.

+

See also

+

+TimeValueOfMoney, +AccumulationFunction, +ForceOfInterest +

+"), Diagram(coordinateSystem(extent = {{-148.5, -35}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {0, 0, 128}, extent = {{-96.456, -12}, {96.456, 12}}, textString = "Present Value", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {0, -25}, textColor = {0, 0, 128}, extent = {{-96.456, -12}, {96.456, 12}}, textString = "PV", fontName = "Lato Black", textStyle = {TextStyle.Bold})})); +end PresentValue; diff --git a/BusinessSimulation/MoleculesOfStructure/InformationProcessing/ResidenceTime.mo b/BusinessSimulation/MoleculesOfStructure/InformationProcessing/ResidenceTime.mo new file mode 100644 index 0000000..0f422b8 --- /dev/null +++ b/BusinessSimulation/MoleculesOfStructure/InformationProcessing/ResidenceTime.mo @@ -0,0 +1,35 @@ +within BusinessSimulation.MoleculesOfStructure.InformationProcessing; + +block ResidenceTime "Calculate average time of residence or time needed for completion" + import BusinessSimulation.Constants.inf; + extends Icons.InformationProcessing; + parameter Real durationAtZeroRate = inf "Value for duration if the rateOfDepletion becomes zero"; + Interfaces.Connectors.RealInput u_level "Current level of work to do or simply level of stock being depleted by flow" annotation(Placement(visible = true, transformation(origin = {-145, 20}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-109.796, 50}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealInput u_rate "The rate at which the stock is drained or the tasks being completed" annotation(Placement(visible = true, transformation(origin = {-145, -20}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-110.231, -50}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealOutput y(quantity = "Time", unit = "s") "Time needed to complete work or drain stock" annotation(Placement(visible = true, transformation(origin = {160, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {112.58, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +protected + Converters.Division_Guarded residenceTime(outputIfZero = durationAtZeroRate, redeclare replaceable type OutputType = Units.Time) "Average time of residence in a stock that is being depleted" annotation(Placement(visible = true, transformation(origin = {0, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ZeroIfNegative currentLevel "Current amount that is being depleted" annotation(Placement(visible = true, transformation(origin = {-50, 20}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ZeroIfNegative rateOfDepletion(redeclare replaceable type OutputType = Units.Rate) "Rate of Depletion" annotation(Placement(visible = true, transformation(origin = {-50, -20}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(residenceTime.y, y) annotation(Line(visible = true, origin = {84, 0}, points = {{-76, 0}, {76, 0}}, color = {0, 0, 127})); + connect(u_level, currentLevel.u) annotation(Line(visible = true, origin = {-101.5, 20}, points = {{-43.5, 0}, {43.5, 0}}, color = {0, 0, 127})); + connect(currentLevel.y, residenceTime.u1) annotation(Line(visible = true, origin = {-21.909, 12.5}, points = {{-20.091, 7.5}, {1.909, 7.5}, {1.909, -7.5}, {13.909, -7.5}}, color = {0, 0, 127})); + connect(u_rate, rateOfDepletion.u) annotation(Line(visible = true, origin = {-101.5, -20}, points = {{-43.5, 0}, {43.5, 0}}, color = {0, 0, 127})); + connect(rateOfDepletion.y, residenceTime.u2) annotation(Line(visible = true, origin = {-21.909, -12.5}, points = {{-20.091, -7.5}, {1.909, -7.5}, {1.909, 7.5}, {13.909, 7.5}}, color = {0, 0, 127})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The Real output y is obtained by dividing the current amount in a material stocku_level by the (positive) rate of its outflow u_rate. According to Little's Law—a famous result from queueing theory—the output y will be equal to the mean time of residence in the stock if the system is in equilibrium.

+

Notes

+ +

Acknowledgements

+

Additional information can be found on Jim Hines' Molecules of Structure website: →Residence Time.

+

See also

+

+Decay
+

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {0, 0, 128}, extent = {{-96.456, -12}, {96.456, 12}}, textString = "Residence or", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {0, -25}, textColor = {0, 0, 128}, extent = {{-96.456, -12}, {96.456, 12}}, textString = "Completion Time", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end ResidenceTime; diff --git a/BusinessSimulation/MoleculesOfStructure/InformationProcessing/TimeValueOfMoney.mo b/BusinessSimulation/MoleculesOfStructure/InformationProcessing/TimeValueOfMoney.mo new file mode 100644 index 0000000..e45a66b --- /dev/null +++ b/BusinessSimulation/MoleculesOfStructure/InformationProcessing/TimeValueOfMoney.mo @@ -0,0 +1,51 @@ +within BusinessSimulation.MoleculesOfStructure.InformationProcessing; + +block TimeValueOfMoney "Calculate the time value of money (TVM) using continuous compounding" + extends Interfaces.PartialConverters.InformationProcessing_SO; + import BusinessSimulation.Units.{Rate,Time}; + Interfaces.Connectors.RealInput u "Current value input" annotation(Placement(visible = true, transformation(origin = {-145, -5}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-110, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealInput u_T(quantity = "Time", unit = "s") if not hasConstantHorizon "Time horizon(T >0 → FV, T < 0 → PV)" annotation(Placement(visible = true, transformation(origin = {-145, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-110, -50}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealInput u_r(quantity = "Rate", unit = "1/s") if not hasConstantRate "Interest rate" annotation(Placement(visible = true, transformation(origin = {-145, 60}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-110, 50}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + parameter Rate rate "Constant compounding rate" annotation(Dialog(enable = hasConstantRate)); + parameter Time T "Constant time horizon (T >0 → FV, T < 0 → PV)" annotation(Dialog(enable = hasConstantHorizon)); + parameter Boolean hasConstantRate = false "= true, if the discount rate is given by the constant parameter" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean hasConstantHorizon = false "= true, if the time horizon is given by a constant parameter" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean isCCR = true "= true, the rate does not need conversion to a continuously compounding rate" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); +protected + Converters.Product_2 rate_x_T annotation(Placement(visible = true, transformation(origin = {-20, 35}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Exp timeValueFactor annotation(Placement(visible = true, transformation(origin = {10, 35}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Product_2 timeValue "Time value of money" annotation(Placement(visible = true, transformation(origin = {50, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ConstantConverterRate parConstantRate(value = rate) if hasConstantRate "Constant rate for compounding" annotation(Placement(visible = true, transformation(origin = {-120, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ForceOfInterest CCR if not isCCR "Continuously compounding rate" annotation(Placement(visible = true, transformation(origin = {-80, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.PassThrough unchangedRate if isCCR annotation(Placement(visible = true, transformation(origin = {-80, 80}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ConstantConverterTime parT(value = T) if hasConstantHorizon "Constant time into the future (time horizon)" annotation(Placement(visible = true, transformation(origin = {-120, -60}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(u_r, CCR.u) annotation(Line(visible = true, origin = {-110.547, 50}, points = {{-34.453, 10}, {10.547, 10}, {10.547, -10}, {22.547, -10}}, color = {1, 37, 163})); + connect(parConstantRate.y, CCR.u) annotation(Line(visible = true, origin = {-101.5, 40}, points = {{-13.5, 0}, {13.5, 0}}, color = {1, 37, 163})); + connect(u_r, unchangedRate.u) annotation(Line(visible = true, origin = {-112, 70}, points = {{-33, -10}, {12, -10}, {12, 10}, {24, 10}}, color = {1, 37, 163})); + connect(parConstantRate.y, unchangedRate.u) annotation(Line(visible = true, origin = {-103.25, 60}, points = {{-11.75, -20}, {-1.75, -20}, {-1.75, 20}, {15.25, 20}}, color = {1, 37, 163})); + connect(unchangedRate.y, rate_x_T.u1) annotation(Line(visible = true, origin = {-45.159, 62.5}, points = {{-27.478, 17.5}, {5.159, 17.5}, {5.159, -22.5}, {17.159, -22.5}}, color = {1, 37, 163})); + connect(rate_x_T.y, timeValueFactor.u) annotation(Line(visible = true, origin = {-5, 35}, points = {{-7, 0}, {7, 0}}, color = {1, 37, 163})); + connect(CCR.y, rate_x_T.u1) annotation(Line(visible = true, origin = {-50.319, 40}, points = {{-22.319, 0}, {22.319, 0}}, color = {1, 37, 163})); + connect(u, timeValue.u2) annotation(Line(visible = true, origin = {-51.5, -5}, points = {{-93.5, 0}, {93.5, 0}}, color = {1, 37, 163})); + connect(timeValueFactor.y, timeValue.u1) annotation(Line(visible = true, origin = {27.5, 20}, points = {{-9.5, 15}, {-2.5, 15}, {-2.5, -15}, {14.5, -15}}, color = {1, 37, 163})); + connect(timeValue.y, y) annotation(Line(visible = true, origin = {109, 0}, points = {{-51, 0}, {51, 0}}, color = {1, 37, 163})); + connect(u_T, rate_x_T.u2) annotation(Line(visible = true, origin = {-63.25, -5}, points = {{-81.75, -35}, {23.25, -35}, {23.25, 35}, {35.25, 35}}, color = {0, 0, 128})); + connect(parT.y, rate_x_T.u2) annotation(Line(visible = true, origin = {-55.5, -15}, points = {{-58.5, -45}, {15.5, -45}, {15.5, 45}, {27.5, 45}}, color = {1, 37, 163})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The Real output y indicates the nominal value of the input u at the end (Future Value) or the beginning (Present Value) of a horizon of length u_T using the interest rate u_r according to the formula:

+

\"y

+

The given rate is assumed to be a continuously compounding rate (aka force of interest). Using the switch isCCR automatic conversion of a discrete rate can be activated.

+

Notes

+ +

See also

+

+PresentValue, +ForceOfInterest, +AccumulationFunction +

+"), Diagram(coordinateSystem(extent = {{-148.5, -70}, {148.5, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {0, 0, 128}, extent = {{-96.456, -12}, {96.456, 12}}, textString = "Time Value", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {0, -25}, textColor = {0, 0, 128}, extent = {{-96.456, -12}, {96.456, 12}}, textString = "TVM", fontName = "Lato Black", textStyle = {TextStyle.Bold})})); +end TimeValueOfMoney; diff --git a/BusinessSimulation/MoleculesOfStructure/InformationProcessing/Trend.mo b/BusinessSimulation/MoleculesOfStructure/InformationProcessing/Trend.mo new file mode 100644 index 0000000..7399a6e --- /dev/null +++ b/BusinessSimulation/MoleculesOfStructure/InformationProcessing/Trend.mo @@ -0,0 +1,60 @@ +within BusinessSimulation.MoleculesOfStructure.InformationProcessing; + +block Trend "Calculating a fractional rate of change to be used in forecasting" + import BusinessSimulation.Types.InitializationOptions; + import BusinessSimulation.Units.{Rate,Time}; + extends Interfaces.PartialConverters.InformationProcessing_SO(redeclare replaceable type OutputType = Rate); + Interfaces.Connectors.RealInput u "Current value as basis for trend formulation" annotation(Placement(visible = true, transformation(origin = {-145, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-110, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealOutput y_ppc if reportPPC "Report the perceived present condition (optional)" annotation(Placement(visible = true, transformation(origin = {160, -60}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {110, -50}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + parameter Rate initialTrend = 0 "Initial trend" annotation(Dialog(enable = not init == InitializationOptions.SteadyState)); + parameter Time tppc(min = 0) = 1 "Averaging time for perception of current quantity (i.e. the present condition)"; + parameter Time thrc(min = 0) = 1 "Time horizon for reference condition"; + parameter Time tpt(min = 0) = 1 "Time to perceive the trend (i.e. there is gradual adaptation to a new trend)" annotation(Dialog(enable = smoothTrend)); + parameter Boolean smoothTrend = false "= true, if the calculated trend is to be smoothed" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean reportPPC = false "= true, if the perceived present conditon is to be reported" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter InitializationOptions init = modelSettings.init "Provide InitializationOptions (Free, FixedValue, SteadyState)" annotation(Evaluate = true, Dialog(tab = "Advanced")); + outer ModelSettings modelSettings; +protected + parameter Real initialRC(fixed = false) "Initial Value for the reference condition" annotation(Dialog(tab = "Initialization", enable = false)); + parameter Real initialPPC(fixed = false) "InitialValue for the perceived present condition" annotation(Dialog(tab = "Initialization", enable = false)); + Converters.PassThrough actualTrend if not smoothTrend annotation(Placement(visible = true, transformation(origin = {80, -30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.DiscreteDelay.Smooth rc(initialValue = initialRC, hasConstantDelayTime = false, init = init) "Reference condition for calculating the fractional trend" annotation(Placement(visible = true, transformation(origin = {-50, -40}, extent = {{-10, 10}, {10, -10}}, rotation = 0))); + Converters.DiscreteDelay.Smooth ppc(initialValue = initialPPC, hasConstantDelayTime = false, init = init) "Perceived present condition" annotation(Placement(visible = true, transformation(origin = {-85, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ConstantConverterTime parTPPC(value = tppc) "Time to perceive present condition" annotation(Placement(visible = true, transformation(origin = {-105, 20}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ConstantConverterTime parTHRC(value = thrc) "Time horizon for the reference condition (duration of trend formulation)" annotation(Placement(visible = true, transformation(origin = {-105, -60}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ConstantConverterTime parTPT(value = tpt) if smoothTrend "Time to perceive the trend (i.e. adjustment time)" annotation(Placement(visible = true, transformation(origin = {100, 25}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Converters.DiscreteDelay.Smooth perceivedTrend(initialValue = initialTrend, hasConstantDelayTime = false, redeclare replaceable type OutputType = Rate, init = init) if smoothTrend "Perceived growth rate" annotation(Placement(visible = true, transformation(origin = {80, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Division_Guarded indicatedTrend "Indicated fractional growth rate (trend)" annotation(Placement(visible = true, transformation(origin = {30, -10}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Gap delta "Difference between perceived present condition and reference condition" annotation(Placement(visible = true, transformation(origin = {-20, -5}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Product_2 rcTimesTHRC "Referenc condition times time horizon for reference condition" annotation(Placement(visible = true, transformation(origin = {-6.933, -45}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +initial equation + initialPPC = u / (1 + tppc * initialTrend); + initialRC = initialPPC / (1 + thrc * initialTrend); +equation + connect(ppc.y, rc.u) annotation(Line(visible = true, origin = {-68.591, -20}, points = {{-6.409, 20}, {-1.409, 20}, {-1.409, -20}, {9.228, -20}}, color = {0, 0, 127})); + connect(u, ppc.u) annotation(Line(visible = true, origin = {-119.681, 0}, points = {{-25.319, 0}, {25.319, 0}}, color = {0, 0, 127})); + connect(perceivedTrend.y, y) "Fractional trend (fractional rate of growth)" annotation(Line(visible = true, origin = {122.384, -5}, points = {{-32.384, 5}, {-2.384, 5}, {-2.384, 5}, {27.616, 5}}, color = {1, 37, 163})); + connect(parTPPC.y, ppc.u_delayTime) annotation(Line(visible = true, origin = {-89.667, 15}, points = {{-9.333, 5}, {4.667, 5}, {4.667, -10}}, color = {1, 37, 163})); + connect(parTHRC.y, rc.u_delayTime) annotation(Line(visible = true, origin = {-66.333, -55}, points = {{-32.667, -5}, {16.333, -5}, {16.333, 10}}, color = {1, 37, 163})); + connect(parTPT.y, perceivedTrend.u_delayTime) annotation(Line(visible = true, origin = {84.667, 18.333}, points = {{9.333, 6.667}, {-4.667, 6.667}, {-4.667, -13.333}}, color = {1, 37, 163})); + connect(indicatedTrend.y, perceivedTrend.u) annotation(Line(visible = true, origin = {49.659, -5}, points = {{-11.659, -5}, {-4.659, -5}, {-4.659, 5}, {20.978, 5}}, color = {0, 0, 127})); + connect(ppc.y, delta.u1) annotation(Line(visible = true, origin = {-51.5, 0}, points = {{-23.5, 0}, {23.5, 0}}, color = {0, 0, 127})); + connect(delta.y, indicatedTrend.u1) annotation(Line(visible = true, origin = {5, -5}, points = {{-17, 0}, {17, 0}}, color = {0, 0, 127})); + connect(rc.y, delta.u2) annotation(Line(visible = true, origin = {-31.366, -25}, points = {{-8.634, -15}, {1.366, -15}, {1.366, 15}, {3.366, 15}}, color = {0, 0, 127})); + connect(rcTimesTHRC.y, indicatedTrend.u2) annotation(Line(visible = true, origin = {13.857, -30}, points = {{-12.79, -15}, {1.143, -15}, {1.143, 15}, {8.143, 15}}, color = {0, 0, 127})); + connect(parTHRC.y, rcTimesTHRC.u2) annotation(Line(visible = true, origin = {-45.868, -55}, points = {{-53.132, -5}, {15.868, -5}, {15.868, 5}, {30.935, 5}}, color = {0, 0, 127})); + connect(rc.y, rcTimesTHRC.u1) annotation(Line(visible = true, origin = {-27.466, -40}, points = {{-12.534, 0}, {12.534, 0}}, color = {0, 0, 127})); + connect(indicatedTrend.y, actualTrend.u) annotation(Line(visible = true, origin = {50, -20}, points = {{-12, 10}, {-5, 10}, {-5, -10}, {22, -10}}, color = {1, 37, 163})); + connect(actualTrend.y, y) annotation(Line(visible = true, origin = {122, -15}, points = {{-34, -15}, {-2, -15}, {-2, 15}, {38, 15}}, color = {1, 37, 163})); + connect(ppc.y, y_ppc) annotation(Line(visible = true, origin = {30.833, -51.667}, points = {{-105.833, 51.667}, {-100.833, 51.667}, {-100.833, -43.333}, {89.167, -43.333}, {89.167, -8.333}, {129.167, -8.333}}, color = {1, 37, 163})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The Trend component represents forecasting in behavioral models and has been proposed by Sterman [3, pp. 634 - 638]. The basic idea is rather intuitive: Forecasters perceive a present condition of some input as a smoothed input (ppc), while they also perceive the historic or reference condition (rc) as a smooth of their current perception.

+

Dividing the diffence between the current condition and the reference condition by the reference condition will determine the fractional increase. A further division by the time horizon for the reference condition will then turn this into a fractional rate. The thus calculated rate of change (i.e. the indicated trend) may then again be smoothed, if smoothTrend = true.

+

See also

+

+TrendBasedForecast, +Smooth +

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {0, 0, 128}, extent = {{-96.456, -12}, {96.456, 12}}, textString = "Trend", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}), graphics = {Rectangle(visible = true, origin = {12.357, -32.5}, lineColor = {128, 128, 128}, fillColor = {255, 255, 255}, pattern = LinePattern.Dash, extent = {{-45, -42.5}, {45, 42.5}}), Text(visible = true, origin = {10.611, -80}, textColor = {128, 128, 128}, extent = {{-54.39, -6.559}, {54.39, 6.559}}, textString = "indicatedTrend = ( ppc- rc ) / rc / thrc", fontSize = 16, fontName = "Arial")})); +end Trend; diff --git a/BusinessSimulation/MoleculesOfStructure/InformationProcessing/TrendBasedForecast.mo b/BusinessSimulation/MoleculesOfStructure/InformationProcessing/TrendBasedForecast.mo new file mode 100644 index 0000000..e71373e --- /dev/null +++ b/BusinessSimulation/MoleculesOfStructure/InformationProcessing/TrendBasedForecast.mo @@ -0,0 +1,44 @@ +within BusinessSimulation.MoleculesOfStructure.InformationProcessing; + +block TrendBasedForecast "Trend-based forecast for an exponentially growing quantity" + import BusinessSimulation.Units.{Rate,Time}; + extends Interfaces.PartialConverters.InformationProcessing_SO; + Interfaces.Connectors.RealInput u "Current value as basis for trend formulation" annotation(Placement(visible = true, transformation(origin = {-145, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-110, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + parameter Units.Rate initialTrend = 0 "Initial trend (fracGrowthRate.initialTrend)"; + parameter Time fcsth(min = 0) = 1 "Forecast horizon"; + parameter Time tppc(min = 0) = 1 "Averaging time for perception of current quantity (i.e. the present condition)"; + parameter Time thrc(min = 0) = 1 "Time horizon for reference condition"; + parameter Time tpt(min = 0) = 1 "Time to perceive the trend (i.e. there is gradual adaptation to a new trend)" annotation(Dialog(enable = smoothTrend)); + parameter Boolean smoothTrend = false "= true, if the calculated trend is to be smoothed (fracGrowthRate.smoothTrend)" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); +protected + Converters.Product_2 fractionalGrowth "FractionalGrowthRate times perceptionTime" annotation(Placement(visible = true, transformation(origin = {-7.422, 40.047}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Add_2 extrapolationFactor "Extrapolaton factor using fractional growth rate and perception time to eliminate perception lage" annotation(Placement(visible = true, transformation(origin = {21.781, 45}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Trend fracGrowthRate(tppc = tppc, thrc = thrc, tpt = tpt, reportPPC = true, initialTrend = initialTrend, smoothTrend = smoothTrend) "TREND-formulation is used to calculate a fractional growth rate" annotation(Placement(visible = true, transformation(origin = {-47.422, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Product_2 extrapolPC "Present Condition extrapolated from perceived quantity and the time to perceive it" annotation(Placement(visible = true, transformation(origin = {51.661, 20}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + TimeValueOfMoney futureValue "Future value according to exponential growth model" annotation(Placement(visible = true, transformation(origin = {91.661, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ConstantConverterTime timePPC(value = tppc) "Time to perceive present condition" annotation(Placement(visible = true, transformation(origin = {-50, 45}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ConstantConverterTime forecastHorizon(value = fcsth) "Forecast horizon (T)" annotation(Placement(visible = true, transformation(origin = {56.661, -15}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ConstantConverter one(value = 1, redeclare replaceable type OutputType = Units.Dimensionless) "Time to perceive present condition" annotation(Placement(visible = true, transformation(origin = {-6.688, 60}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(u, fracGrowthRate.u) annotation(Line(visible = true, origin = {-101.896, 0}, points = {{-43.104, 0}, {43.103, 0}}, color = {0, 0, 127})); + connect(futureValue.y, y) annotation(Line(visible = true, origin = {115.342, 0}, points = {{-12.681, 0}, {44.658, -0}}, color = {0, 0, 127})); + connect(forecastHorizon.y, futureValue.u_T) annotation(Line(visible = true, origin = {71.286, -10}, points = {{-9.625, -5}, {0.375, -5}, {0.375, 5}, {8.875, 5}}, color = {1, 37, 163})); + connect(extrapolPC.y, futureValue.u) annotation(Line(visible = true, origin = {76.563, 10}, points = {{-16.902, 10}, {-1.466, 10}, {-1.466, -10}, {4.098, -10}}, color = {1, 37, 163})); + connect(fractionalGrowth.y, extrapolationFactor.u2) annotation(Line(visible = true, origin = {5.879, 40.023}, points = {{-5.301, 0.023}, {-1.301, 0.023}, {-1.301, -0.023}, {7.902, -0.023}}, color = {1, 37, 163})); + connect(one.y, extrapolationFactor.u1) annotation(Line(visible = true, origin = {5.68, 55}, points = {{-7.367, 5}, {-0.367, 5}, {-0.367, -5}, {8.102, -5}}, color = {1, 37, 163})); + connect(timePPC.y, fractionalGrowth.u1) annotation(Line(visible = true, origin = {-32.605, 45.023}, points = {{-12.395, -0.023}, {-2.395, -0.023}, {-2.395, 0.023}, {17.184, 0.023}}, color = {1, 37, 163})); + connect(extrapolationFactor.y, extrapolPC.u1) annotation(Line(visible = true, origin = {36.751, 35}, points = {{-6.97, 10}, {0.03, 10}, {0.03, -10}, {6.91, -10}}, color = {1, 37, 163})); + connect(fracGrowthRate.y, futureValue.u_r) annotation(Line(visible = true, origin = {43.56, 2.5}, points = {{-79.982, -2.5}, {21.44, -2.5}, {21.44, 2.5}, {37.101, 2.5}}, color = {1, 37, 163})); + connect(fracGrowthRate.y_ppc, extrapolPC.u2) annotation(Line(visible = true, origin = {-12.282, 5}, points = {{-24.14, -10}, {12.282, -10}, {12.282, 10}, {55.943, 10}}, color = {1, 37, 163})); + connect(fracGrowthRate.y, fractionalGrowth.u2) annotation(Line(visible = true, origin = {-26.593, 17.477}, points = {{-9.829, -17.477}, {-3.407, -17.523}, {-3.407, 17.523}, {11.171, 17.57}}, color = {1, 37, 163})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The trend-based forecast makes use of a perceived present condition and a fractional growth rate computed by a →Trend block that follows the model proposed by Sterman [3, pp. 34 - 38].

+

The perceived present condition (PPC) will be \"brought forward\" to the actual time using linear extrapolation:

+

Extrapolated Present Condition = Perceived Present Condition · ( 1 + fractional growth rate · time to perceive present condition)

+

The actual forecast is then arrived at by using exponential growth and continuous compounding:

+

forecast = extrapolated present condition · EXP( fractional growth rate · forecast horizon)

+

See also

+

Trend

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, -25}, textColor = {0, 0, 128}, extent = {{-96.456, -12}, {96.456, 12}}, textString = "Forecast", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, textColor = {0, 0, 128}, extent = {{-96.456, -12}, {96.456, 12}}, textString = "Trend-based", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Rectangle(visible = true, origin = {-134.89, 113.027}, fillColor = {255, 255, 255}, extent = {{-0.491, -0.631}, {0.491, 0.631}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end TrendBasedForecast; diff --git a/BusinessSimulation/MoleculesOfStructure/InformationProcessing/package.mo b/BusinessSimulation/MoleculesOfStructure/InformationProcessing/package.mo new file mode 100644 index 0000000..cbebaa5 --- /dev/null +++ b/BusinessSimulation/MoleculesOfStructure/InformationProcessing/package.mo @@ -0,0 +1,11 @@ +within BusinessSimulation.MoleculesOfStructure; + +package InformationProcessing "Making use of raw data from sensors and other sources" + extends Icons.Package; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This package contains components that represent some form of information processing—as opposed to actual decision making.

+

+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Ellipse(visible = true, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, lineThickness = 5, extent = {{-53.126, -53.126}, {53.126, 53.126}}), Text(visible = true, textColor = {255, 255, 255}, extent = {{-23.482, -40}, {23.482, 40}}, textString = "i", fontName = "Consolas", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end InformationProcessing; diff --git a/BusinessSimulation/MoleculesOfStructure/InformationProcessing/package.order b/BusinessSimulation/MoleculesOfStructure/InformationProcessing/package.order new file mode 100644 index 0000000..5eebc25 --- /dev/null +++ b/BusinessSimulation/MoleculesOfStructure/InformationProcessing/package.order @@ -0,0 +1,8 @@ +AggregatePerformance +BasicOrientation +FinancialReporting +PresentValue +ResidenceTime +TimeValueOfMoney +Trend +TrendBasedForecast diff --git a/BusinessSimulation/MoleculesOfStructure/Policy/ActionFromResource.mo b/BusinessSimulation/MoleculesOfStructure/Policy/ActionFromResource.mo new file mode 100644 index 0000000..ef0c70c --- /dev/null +++ b/BusinessSimulation/MoleculesOfStructure/Policy/ActionFromResource.mo @@ -0,0 +1,22 @@ +within BusinessSimulation.MoleculesOfStructure.Policy; + +block ActionFromResource "Flow (action) is proportional to resource level" + extends Interfaces.PartialConverters.Policy_SO(redeclare replaceable type OutputType = Units.Rate); + Interfaces.Connectors.RealInput u_res "Level of available resources" annotation(Placement(visible = true, transformation(origin = {-145, 20}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-115, 50}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealInput u_prod "Ability of resources to create a flow (productivity)" annotation(Placement(visible = true, transformation(origin = {-145, -20}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-115, -50}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +protected + Converters.Product_2 flowFromResource "Action (flow) from resource" annotation(Placement(visible = true, transformation(origin = {0, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(u_res, flowFromResource.u1) annotation(Line(visible = true, origin = {-51.75, 12.5}, points = {{-93.25, 7.5}, {31.75, 7.5}, {31.75, -7.5}, {43.75, -7.5}}, color = {0, 0, 127})); + connect(u_prod, flowFromResource.u2) annotation(Line(visible = true, origin = {-51.75, -12.5}, points = {{-93.25, -7.5}, {31.75, -7.5}, {31.75, 7.5}, {43.75, 7.5}}, color = {0, 0, 127})); + connect(flowFromResource.y, y) annotation(Line(visible = true, origin = {84, 0}, points = {{-76, 0}, {76, 0}}, color = {0, 0, 127})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output y is the product of the amount of some resource (u_res) and its ability to generate a flow/action (i.e. its productivity u_prod).

+

y[1/s] = u_res[1] · u_prod[1/s]

+

Acknowledgements

+

Additonal information can be found in [6, p. 109] and on Jim Hines's Molecules of Structure website: →Flow From Resource.

+

See also

+

CloseGap

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, 12.5}, textColor = {0, 0, 128}, extent = {{-96.456, -12}, {96.456, 12}}, textString = "Action From", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {0, -12.5}, textColor = {0, 0, 128}, extent = {{-96.456, -12}, {96.456, 12}}, textString = "Resource", fontName = "Lato Black", textStyle = {TextStyle.Bold})})); +end ActionFromResource; diff --git a/BusinessSimulation/MoleculesOfStructure/Policy/CloseGap.mo b/BusinessSimulation/MoleculesOfStructure/Policy/CloseGap.mo new file mode 100644 index 0000000..0bfcb19 --- /dev/null +++ b/BusinessSimulation/MoleculesOfStructure/Policy/CloseGap.mo @@ -0,0 +1,58 @@ +within BusinessSimulation.MoleculesOfStructure.Policy; + +block CloseGap "Determine the rate of flow (action) to close a gap between a quantity and its desired value" + import BusinessSimulation.Units.{Time,Rate}; + import BusinessSimulation.Constants.inf; + import Modelica.Blocks.Types.LimiterHomotopy; + extends Interfaces.PartialConverters.Policy_SO(redeclare replaceable type OutputType = Units.Rate); + Interfaces.Connectors.RealInput u_reference "Desired or reference value for the controlled quantity (i.e. the goal)" annotation(Placement(visible = true, transformation(origin = {-145, 50}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-110, 0}, extent = {{-10, -10}, {10, 10}}, rotation = -360))); + Interfaces.Connectors.RealInput u_current "Current value of controlled quantity" annotation(Placement(visible = true, transformation(origin = {-145, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {0, 110}, extent = {{-10, -10}, {10, 10}}, rotation = -450))); + Interfaces.Connectors.RealInput u_adjTime if not hasConstantAdjTime "Time to close the gap" annotation(Placement(visible = true, transformation(origin = {-145, -60}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-110, -50}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + parameter Time adjTime(min = 0) = 1 "Time to close the gap" annotation(Dialog(enable = hasConstantAdjTime)); + parameter Rate maxRate = inf "Maximum rate feasible" annotation(Dialog(enable = clipOutput)); + parameter Rate minRate = 0 "Minimum rate feasible" annotation(Dialog(enable = clipOutput)); + parameter Boolean hasConstantAdjTime = true "= true, if the time to close the gap is a constant paramater" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean invertOutput = false "= true, if the output is to be multiplied with (-1)" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean clipOutput = false "= true, if the indicated rate is to clipped to not exceed limitations" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean strict = true "= true, if strict limits with noEvent(..) (constantLimiter.strict) (clip1.strict)" annotation(Evaluate = true, Dialog(tab = "Advanced")); + parameter LimiterHomotopy homotopyType = LimiterHomotopy.Linear "Simplified model for homotopy-based initialization (constantLimiter.homotopyType) (clip1.homotopyType)" annotation(Evaluate = true, Dialog(tab = "Advanced")); + outer ModelSettings modelSettings; +protected + Converters.PassThrough unchanged1 if not invertOutput "Use the calculated net rate of flow" annotation(Placement(visible = true, transformation(origin = {40, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Gain invertedAction(c = -1) if invertOutput "This will turn negative rates to positive ones (for use with an outflow)" annotation(Placement(visible = true, transformation(origin = {40, -20}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.PassThrough unchanged2 if not clipOutput "Use the calculated net rate of flow" annotation(Placement(visible = true, transformation(origin = {90, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Clip clip1(maxValue = maxRate, minValue = minRate, hasConstantLimits = true, strict = strict, homotopyType = homotopyType) if clipOutput annotation(Placement(visible = true, transformation(origin = {90, -20}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ConstantConverterTime parAdjTime(final value = adjTime) if hasConstantAdjTime "Constant time to close the gap (optional)" annotation(Placement(visible = true, transformation(origin = {-100, -35}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Gap gap "Difference between the goal and the current value" annotation(Placement(visible = true, transformation(origin = {-40, 5}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Division_Guarded actionToCloseGap(final outputIfZero = 0) "Rate of (net) flow to close the gap" annotation(Placement(visible = true, transformation(origin = {-2.412, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(u_reference, gap.u1) annotation(Line(visible = true, origin = {-70.25, 30.075}, points = {{-74.75, 19.925}, {17.25, 19.925}, {17.25, -20.075}, {22.25, -20.075}}, color = {0, 0, 127})); + connect(u_current, gap.u2) annotation(Line(visible = true, origin = {-96.5, 0}, points = {{-48.5, 0}, {48.5, 0}}, color = {0, 0, 127})); + connect(gap.y, actionToCloseGap.u1) annotation(Line(visible = true, origin = {-21.206, 5}, points = {{-10.794, 0}, {10.794, 0}}, color = {0, 0, 127})); + connect(u_adjTime, actionToCloseGap.u2) annotation(Line(visible = true, origin = {-44.191, -32.5}, points = {{-100.809, -27.5}, {24.191, -27.5}, {24.191, 27.5}, {33.779, 27.5}}, color = {0, 0, 127})); + connect(parAdjTime.y, actionToCloseGap.u2) annotation(Line(visible = true, origin = {-36.103, -20}, points = {{-57.897, -15}, {16.103, -15}, {16.103, 15}, {25.691, 15}}, color = {1, 37, 163})); + connect(actionToCloseGap.y, unchanged1.u) annotation(Line(visible = true, origin = {18.794, 0}, points = {{-13.206, 0}, {13.206, 0}}, color = {1, 37, 163})); + connect(actionToCloseGap.y, invertedAction.u) annotation(Line(visible = true, origin = {15.691, -10}, points = {{-10.103, 10}, {-3.103, 10}, {-3.103, -10}, {16.309, -10}}, color = {1, 37, 163})); + connect(unchanged1.y, unchanged2.u) annotation(Line(visible = true, origin = {65, 0}, points = {{-17, 0}, {17, 0}}, color = {1, 37, 163})); + connect(unchanged2.y, y) annotation(Line(visible = true, origin = {129, 0}, points = {{-31, 0}, {31, 0}}, color = {1, 37, 163})); + connect(invertedAction.y, unchanged2.u) annotation(Line(visible = true, origin = {60, -10}, points = {{-12, -10}, {0, -10}, {0, 10}, {22, 10}}, color = {1, 37, 163})); + connect(unchanged1.y, clip1.u) annotation(Line(visible = true, origin = {62.5, -10}, points = {{-14.5, 10}, {2.5, 10}, {2.5, -10}, {19.5, -10}}, color = {1, 37, 163})); + connect(invertedAction.y, clip1.u) annotation(Line(visible = true, origin = {65, -20}, points = {{-17, 0}, {17, 0}}, color = {1, 37, 163})); + connect(clip1.y, y) annotation(Line(visible = true, origin = {124.5, -10}, points = {{-26.5, -10}, {-4.5, -10}, {-4.5, 10}, {35.5, 10}}, color = {1, 37, 163})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output y is given by the expression:

+

y = (u_reference - u_current) / u_adjTime

+

where the time to close the gap (u_adjTime) can alternatively be a constant (adjTime). If the adjustement time is zero, then the output y will be zero as well.

+

Limitations

+ +

Notes

+ +"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, -0.409}, textColor = {0, 0, 128}, extent = {{-77.269, -12}, {77.269, 12}}, textString = "Close Gap", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end CloseGap; diff --git a/BusinessSimulation/MoleculesOfStructure/Policy/FirstOrderStockAdjustment.mo b/BusinessSimulation/MoleculesOfStructure/Policy/FirstOrderStockAdjustment.mo new file mode 100644 index 0000000..da06cb6 --- /dev/null +++ b/BusinessSimulation/MoleculesOfStructure/Policy/FirstOrderStockAdjustment.mo @@ -0,0 +1,53 @@ +within BusinessSimulation.MoleculesOfStructure.Policy; + +block FirstOrderStockAdjustment "Maintain a stock at a desired level" + import BusinessSimulation.Units.{Time,Rate}; + import BusinessSimulation.Constants.inf; + import Modelica.Blocks.Types.LimiterHomotopy; + extends Interfaces.PartialConverters.Policy_SO(redeclare replaceable type OutputType = Units.Rate); + Interfaces.Connectors.RealInput u_reference "Desired or reference amount in the stock under control" annotation(Placement(visible = true, transformation(origin = {-145, 5}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-110, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealInput u_current "Current amount in the stock under control" annotation(Placement(visible = true, transformation(origin = {-145, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-50, 110}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Interfaces.Connectors.RealInput u_outflow "Current outflow from the stock under control" annotation(Placement(visible = true, transformation(origin = {-145, -70}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {50, 110}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Interfaces.Connectors.RealInput u_adjTime if not hasConstantAdjTime "Variable time for adjustment (optional)" annotation(Placement(visible = true, transformation(origin = {-145, -20}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-110, -50}, extent = {{-10, -10}, {10, 10}}, rotation = -360))); + parameter Time adjTime(min = 0) = 1 "Time constant for the adjustment to the desired level (optional)" annotation(Dialog(enable = hasConstantAdjTime)); + parameter Rate maxRate = inf "Maximum rate feasible (clippedRate.maxValue)" annotation(Dialog(enable = clipOutput)); + parameter Boolean hasConstantAdjTime = true "= true, if adjustment time is to be given by a constant parameter" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean clipOutput = false "= true, if the indicated rate is to clipped to not exceed limitations" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean strict = true "= true, if strict limits with noEvent(..) (constantLimiter.strict) (clip1.strict)" annotation(Evaluate = true, Dialog(tab = "Advanced")); + parameter LimiterHomotopy homotopyType = LimiterHomotopy.Linear "Simplified model for homotopy-based initialization (constantLimiter.homotopyType) (clip1.homotopyType)" annotation(Evaluate = true, Dialog(tab = "Advanced")); +protected + outer ModelSettings modelSettings; + Converters.Clip clippedRate(strict = strict, homotopyType = homotopyType, hasConstantLimits = true, minValue = 0, maxValue = maxRate) if clipOutput "Limit rate to feasible values" annotation(Placement(visible = true, transformation(origin = {90, -20}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.PassThrough unchanged if not clipOutput "Leave the indicated rate unchanged" annotation(Placement(visible = true, transformation(origin = {90, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + CloseGap adjustment(hasConstantAdjTime = false, invertOutput = false, clipOutput = false) "Inflow needed to reach desired level of stock" annotation(Placement(visible = true, transformation(origin = {-10, 5}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Add_2 totalAdjustment(redeclare replaceable type OutputType = Units.Rate) "Closing gap and compensate for outflow from stock" annotation(Placement(visible = true, transformation(origin = {40, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ConstantConverterTime parAdjTime(value = adjTime) if hasConstantAdjTime "Constant time of adjustment (optional)" annotation(Placement(visible = true, transformation(origin = {-120, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(u_outflow, totalAdjustment.u2) annotation(Line(visible = true, origin = {-21.75, -37.5}, points = {{-123.25, -32.5}, {41.75, -32.5}, {41.75, 32.5}, {53.75, 32.5}}, color = {0, 0, 127})); + connect(u_reference, adjustment.u_reference) annotation(Line(visible = true, origin = {-83, 5}, points = {{-62, 0}, {62, 0}}, color = {0, 0, 128})); + connect(u_current, adjustment.u_current) annotation(Line(visible = true, origin = {-55, 32}, points = {{-90, 8}, {45, 8}, {45, -16}}, color = {0, 0, 128})); + connect(adjustment.y, totalAdjustment.u1) annotation(Line(visible = true, origin = {16.5, 5}, points = {{-15.5, 0}, {15.5, 0}}, color = {1, 37, 163})); + connect(u_adjTime, adjustment.u_adjTime) annotation(Line(visible = true, origin = {-61.5, -10}, points = {{-83.5, -10}, {21.5, -10}, {21.5, 10}, {40.5, 10}}, color = {0, 0, 128})); + connect(parAdjTime.y, adjustment.u_adjTime) annotation(Line(visible = true, origin = {-53.75, -20}, points = {{-60.25, -20}, {13.75, -20}, {13.75, 20}, {32.75, 20}}, color = {1, 37, 163})); + connect(totalAdjustment.y, unchanged.u) annotation(Line(visible = true, origin = {65, 0}, points = {{-17, 0}, {17, 0}}, color = {1, 37, 163})); + connect(unchanged.y, y) annotation(Line(visible = true, origin = {129, 0}, points = {{-31, 0}, {31, 0}}, color = {1, 37, 163})); + connect(totalAdjustment.y, clippedRate.u) annotation(Line(visible = true, origin = {62.5, -10}, points = {{-14.5, 10}, {-2.5, 10}, {-2.5, -10}, {19.5, -10}}, color = {1, 37, 163})); + connect(clippedRate.y, y) annotation(Line(visible = true, origin = {124.5, -10}, points = {{-26.5, -10}, {-4.5, -10}, {-4.5, 10}, {35.5, 10}}, color = {1, 37, 163})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The output y indicates the rate of inflow required to keep a stock at a desired level. The (perceived) outflow from the stock will be replaced immediately to keep the stock at its current level, while the gap between the current level and the desired level will be closed using a →CloseGap component.

+

Limitations

+ +

Notes

+ +

See also

+

CloseGap, SmoothSmoothN

+

 

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, 12.5}, textColor = {0, 0, 128}, extent = {{-77.269, -12}, {77.269, 12}}, textString = "First-Order", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {0, -12.5}, textColor = {0, 0, 128}, extent = {{-77.987, -12}, {77.987, 12}}, textString = "Stock Adjustment", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end FirstOrderStockAdjustment; diff --git a/BusinessSimulation/MoleculesOfStructure/Policy/PID.mo b/BusinessSimulation/MoleculesOfStructure/Policy/PID.mo new file mode 100644 index 0000000..2a9f0b1 --- /dev/null +++ b/BusinessSimulation/MoleculesOfStructure/Policy/PID.mo @@ -0,0 +1,44 @@ +within BusinessSimulation.MoleculesOfStructure.Policy; + +block PID "Limited PID controller" + extends Interfaces.PartialConverters.Policy_SO; + import BusinessSimulation.Constants.{small,inf,eps}; + import BusinessSimulation.Units.Time; + import Modelica.Blocks.Types.InitPID; + import Modelica.Blocks.Types.Init; + import Modelica.Blocks.Types.SimpleController; + Interfaces.Connectors.RealInput u_desiredValue "The goal to meet (setpoint)" annotation(Placement(visible = true, transformation(origin = {-145, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-110, 0}, extent = {{-10, -10}, {10, 10}}, rotation = -360))); + Interfaces.Connectors.RealInput u_currentValue "The measured state of the system under control" annotation(Placement(visible = true, transformation(origin = {-145, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {0, 110}, extent = {{-10, -10}, {10, 10}}, rotation = -450))); + Interfaces.Connectors.RealInput u_feedForward if hasFeedForward "An optional feedforward input" annotation(Placement(visible = true, transformation(origin = {-145, -60}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {50, 110}, extent = {{-10, -10}, {10, 10}}, rotation = -450))); + parameter .Modelica.Blocks.Types.SimpleController controllerType = Modelica.Blocks.Types.SimpleController.PID "Type of controller" annotation(Dialog(group = "Structural Parameters")); + parameter Boolean hasFeedForward = false "Use feed-forward input? (PID.withFeedForward)" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Real k(min = 0) = 1 "Gain of controller"; + parameter Modelica.SIunits.Time Ti(min = small) = 0.5 "Time constant of Integrator block" annotation(Dialog(enable = controllerType == .Modelica.Blocks.Types.SimpleController.PI or controllerType == .Modelica.Blocks.Types.SimpleController.PID)); + parameter Modelica.SIunits.Time Td(min = 0) = 0.1 "Time constant of Derivative block" annotation(Dialog(enable = controllerType == .Modelica.Blocks.Types.SimpleController.PD or controllerType == .Modelica.Blocks.Types.SimpleController.PID)); + parameter Real yMax = inf "Upper limit of output"; + parameter Real yMin = -yMax "Lower limit of output"; + parameter Real wp(min = 0) = 1 "Set-point weight for Proportional block (0..1)"; + parameter Real wd(min = 0) = 0 "Set-point weight for Derivative block (0..1)" annotation(Dialog(enable = controllerType == .Modelica.Blocks.Types.SimpleController.PD or controllerType == .Modelica.Blocks.Types.SimpleController.PID)); + parameter Real Ni(min = 100 * eps) = 0.9 "Ni*Ti is time constant of anti-windup compensation" annotation(Dialog(enable = controllerType == .Modelica.Blocks.Types.SimpleController.PI or controllerType == .Modelica.Blocks.Types.SimpleController.PID)); + parameter Real Nd(min = 100 * eps) = 10 "The higher Nd, the more ideal the derivative block" annotation(Dialog(enable = controllerType == .Modelica.Blocks.Types.SimpleController.PD or controllerType == .Modelica.Blocks.Types.SimpleController.PID)); + parameter Real kFF = 1 "Gain of feed-forward input" annotation(Dialog(enable = withFeedForward)); + parameter .Modelica.Blocks.Types.InitPID initType = .Modelica.Blocks.Types.InitPID.DoNotUse_InitialIntegratorState "Type of initialization (1: no init, 2: steady state, 3: initial state, 4: initial output)" annotation(Evaluate = true, Dialog(group = "Initialization")); + parameter Real xi_start = 0 "Initial or guess value for integrator output (= integrator state)" annotation(Dialog(group = "Initialization", enable = controllerType == .Modelica.Blocks.Types.SimpleController.PI or controllerType == .Modelica.Blocks.Types.SimpleController.PID)); + parameter Real xd_start = 0 "Initial or guess value for state of derivative block" annotation(Dialog(group = "Initialization", enable = controllerType == .Modelica.Blocks.Types.SimpleController.PD or controllerType == .Modelica.Blocks.Types.SimpleController.PID)); + parameter Real y_start = 0 "Initial value of output" annotation(Dialog(enable = initType == .Modelica.Blocks.Types.InitPID.InitialOutput, group = "Initialization")); + parameter Modelica.Blocks.Types.LimiterHomotopy homotopyType = Modelica.Blocks.Types.LimiterHomotopy.Linear "Simplified model for homotopy-based initialization" annotation(Evaluate = true, Dialog(group = "Initialization")); + parameter Boolean strict = false "= true, if strict limits with noEvent(..)" annotation(Evaluate = true, choices(checkBox = true), Dialog(tab = "Advanced")); + parameter Boolean limitsAtInit = true "Has no longer an effect and is only kept for backwards compatibility (the implementation uses now the homotopy operator)" annotation(Dialog(tab = "Dummy"), Evaluate = true, choices(checkBox = true)); +protected + Modelica.Blocks.Continuous.LimPID PID(controllerType = Modelica.Blocks.Types.SimpleController.PID, withFeedForward = hasFeedForward, Ti = Ti, k = k, Td = Td, yMax = yMax, yMin = yMin, wp = wp, wd = wd, Ni = Ni, Nd = Nd, kFF = kFF, xi_start = xi_start, xd_start = xd_start, y_start = y_start, homotopyType = homotopyType) annotation(Placement(visible = true, transformation(origin = {0, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(u_desiredValue, PID.u_s) annotation(Line(visible = true, origin = {-78.5, 0}, points = {{-66.5, 0}, {66.5, 0}}, color = {0, 0, 127})); + connect(u_currentValue, PID.u_m) annotation(Line(visible = true, origin = {-48.333, -30.667}, points = {{-96.667, -9.333}, {48.333, -9.333}, {48.333, 18.667}}, color = {0, 0, 127})); + connect(PID.y, y) annotation(Line(visible = true, origin = {85.5, 0}, points = {{-74.5, 0}, {74.5, 0}}, color = {0, 0, 127})); + connect(u_feedForward, PID.u_ff) annotation(Line(visible = true, origin = {-44.333, -44}, points = {{-100.667, -16}, {50.333, -16}, {50.333, 32}}, color = {0, 0, 128})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This element makes use of the →LimPID element in the Modelica Standard Library. The controller is a very flexible component which allows to model P, PI, PD, PID controllers as needed.

+

A PID controller continually calculates the error e(t) = u_desiredValue - u_currentValue and then applies a correction based upon proportional (P), integral (I), and derivatice (D) terms.

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, textColor = {0, 0, 128}, extent = {{-77.269, -12}, {77.269, 12}}, textString = "P I D", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end PID; diff --git a/BusinessSimulation/MoleculesOfStructure/Policy/package.mo b/BusinessSimulation/MoleculesOfStructure/Policy/package.mo new file mode 100644 index 0000000..e4ba867 --- /dev/null +++ b/BusinessSimulation/MoleculesOfStructure/Policy/package.mo @@ -0,0 +1,11 @@ +within BusinessSimulation.MoleculesOfStructure; + +package Policy "Structure for processing information and making decisions" + extends Icons.Package; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This package contains pre-built components for typical \"policy\" modules representing some form of decision making (sometimes also of information processing).

+

+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Ellipse(visible = true, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, lineThickness = 5, extent = {{-53.126, -53.126}, {53.126, 53.126}}), Line(visible = true, origin = {-0.092, 30}, rotation = -90, points = {{0, 43.231}, {0, -43.231}}, color = {255, 255, 255}, thickness = 5), Line(visible = true, origin = {0, -30}, rotation = -90, points = {{0, 43.231}, {0, -43.231}}, color = {255, 255, 255}, thickness = 5)}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Policy; diff --git a/BusinessSimulation/MoleculesOfStructure/Policy/package.order b/BusinessSimulation/MoleculesOfStructure/Policy/package.order new file mode 100644 index 0000000..47be9ca --- /dev/null +++ b/BusinessSimulation/MoleculesOfStructure/Policy/package.order @@ -0,0 +1,4 @@ +ActionFromResource +CloseGap +FirstOrderStockAdjustment +PID diff --git a/BusinessSimulation/MoleculesOfStructure/Transceivers/Chain.mo b/BusinessSimulation/MoleculesOfStructure/Transceivers/Chain.mo new file mode 100644 index 0000000..e0b9a32 --- /dev/null +++ b/BusinessSimulation/MoleculesOfStructure/Transceivers/Chain.mo @@ -0,0 +1,40 @@ +within BusinessSimulation.MoleculesOfStructure.Transceivers; + +model Chain "A chain of serially connected reservoirs" + import BusinessSimulation.Constants.inf; + import BusinessSimulation.Types.InitializationOptions; + extends Icons.SubsystemTransceiver; + extends Interfaces.Basics.OutputTypeChoice; + Interfaces.Connectors.StockPort stockPort "Inflow-side of the chain" annotation(Placement(visible = true, transformation(origin = {-148.207, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-100, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.FlowPort flowPort if hasFlowPort "Outflow side of the chain conditional upon `endWithCloud` switch" annotation(Placement(visible = true, transformation(origin = {148.053, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {100, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealMultiInput[n] u "Vector input of transition rates" annotation(Placement(visible = true, transformation(origin = {-145, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-50, 100}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + RealMultiOutput[n] y "Amounts contained in the stocks" annotation(Placement(visible = true, transformation(origin = {150, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {50, 104}, extent = {{-10, -10}, {10, 10}}, rotation = -270))); + Interfaces.Connectors.StockInfoOutput[n] y_stockInfo if hasStockInfoOutput "Optional StockInfoOutput" annotation(Placement(visible = true, transformation(origin = {150, -80}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {80, 104}, extent = {{-10, -10}, {10, 10}}, rotation = -270))); + parameter Integer n(min = 2) = 2 "The number of stocks in the chain" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Real[n] initialValue = zeros(n) "Vector of initial values for the stocks in the chain"; + parameter OutputType[n] maxValue = fill(inf, n) "Maximum admissable value"; + parameter OutputType[n] minValue = fill(-inf, n) "Minimum admissable value"; + parameter Boolean hasFlowPort = true "= true, if the outflow from the stock will go to a flow port instead of a cloud" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean useAssert = false "= true, if leaving the admissable range is to cause an error or warning" annotation(Evaluate = true, Dialog(tab = "Advanced")); + parameter Boolean causeError = true "= true, if leaving the admissable range is to cause an error instead of simply a warning" annotation(Evaluate = true, Dialog(tab = "Advanced")); + parameter Boolean hasStockInfoOutput = false "= true, if a StockInfoOutput should be added to the stock" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); +protected + Reservoir reservoir[n](initialValue = initialValue, maxValue = maxValue, minValue = minValue, each hasStockInfoOutput = hasStockInfoOutput, each useAssert = useAssert, each causeError = causeError) annotation(Placement(visible = true, transformation(origin = {0, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + SourcesOrSinks.Cloud cloud if not hasFlowPort annotation(Placement(visible = true, transformation(origin = {70, -20}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); +equation + connect(stockPort, reservoir[1].stockPort) annotation(Line(visible = true, origin = {-79.103, 0}, points = {{-69.103, 0}, {69.103, 0}}, color = {128, 0, 128})); + // connect the outflow from reservoir i to the stock port (inflow) of reservoir i+1 + for i in 1:n - 1 loop + connect(reservoir[i].flowPort, reservoir[i + 1].stockPort); + end for; + // connect the outflow from the last reservoir to the flow port of the chain + connect(reservoir[end].flowPort, flowPort) annotation(Line(visible = true, origin = {79.026, 0}, points = {{-69.026, 0}, {69.026, 0}}, color = {128, 0, 128})); + connect(reservoir[end].flowPort, cloud.massPort) "alternative end of chain" annotation(Line(visible = true, origin = {41.14, -10}, points = {{-31.14, 10}, {6.14, 10}, {6.14, -10}, {18.86, -10}}, color = {128, 0, 128})); + connect(u, reservoir.u) annotation(Line(visible = true, origin = {-51.667, 30}, points = {{-93.333, 10}, {46.667, 10}, {46.667, -20}}, color = {0, 0, 127})); + connect(reservoir.y, y) annotation(Line(visible = true, origin = {53.333, 30.133}, points = {{-48.333, -19.733}, {-48.333, 9.867}, {96.667, 9.867}}, color = {1, 37, 163})); + connect(reservoir.y_stockInfo, y_stockInfo) annotation(Line(visible = true, origin = {73.2, -21.92}, points = {{-65.2, 32.32}, {-65.2, 41.92}, {26.8, 41.92}, {26.8, -58.08}, {76.8, -58.08}}, color = {128, 0, 128})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

A chain (aka cascade) consists of a series of →reservoirs that are connected in a sequence. Depending upon the Boolean parameter hasFlowPort the component will either end in a →Cloud or in a →FlowPort.

+"), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}), graphics = {Text(visible = true, origin = {0, -20.02}, textColor = {128, 128, 128}, extent = {{-38.625, -5.02}, {38.625, 5.02}}, textString = "array of reservoirs in a chain", fontSize = 16)}), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {-34.16, -0.234}, points = {{0, 0}, {28.109, 0}}, color = {0, 128, 0}, thickness = 5), Rectangle(visible = true, origin = {-44.948, 0}, lineColor = {255, 0, 0}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 3, extent = {{-10, -10}, {10, 10}}), Ellipse(visible = true, origin = {-20.022, 0}, lineColor = {0, 128, 0}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 0.5, extent = {{-4.138, -4.138}, {4.138, 4.138}}), Polygon(visible = true, origin = {-5.547, -0.275}, lineColor = {0, 128, 0}, fillColor = {0, 128, 0}, fillPattern = FillPattern.Solid, points = {{-2.773, 3.823}, {-2.773, -3.863}, {5.547, 0.041}}), Text(visible = true, origin = {0, 75}, textColor = {76, 112, 136}, extent = {{-100, -12}, {100, 12}}, textString = "Chain", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Line(visible = true, origin = {21.84, -0.234}, points = {{0, 0}, {28.109, 0}}, color = {0, 128, 0}, thickness = 5), Ellipse(visible = true, origin = {35.978, 0}, lineColor = {0, 128, 0}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 0.5, extent = {{-4.138, -4.138}, {4.138, 4.138}}), Rectangle(visible = true, origin = {11.052, 0}, lineColor = {255, 0, 0}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 3, extent = {{-10, -10}, {10, 10}}), Polygon(visible = true, origin = {50.453, -0.275}, lineColor = {0, 128, 0}, fillColor = {0, 128, 0}, fillPattern = FillPattern.Solid, points = {{-2.773, 3.823}, {-2.773, -3.863}, {5.547, 0.041}}), Text(visible = true, origin = {0, -70}, extent = {{-97.365, -6}, {97.365, 6}}, textString = "n = %n", fontName = "Lato", textStyle = {TextStyle.Bold})})); +end Chain; diff --git a/BusinessSimulation/MoleculesOfStructure/Transceivers/Reservoir.mo b/BusinessSimulation/MoleculesOfStructure/Transceivers/Reservoir.mo new file mode 100644 index 0000000..d5bf984 --- /dev/null +++ b/BusinessSimulation/MoleculesOfStructure/Transceivers/Reservoir.mo @@ -0,0 +1,47 @@ +within BusinessSimulation.MoleculesOfStructure.Transceivers; + +model Reservoir "A single stock drained by an outflow at a given rate" + import BusinessSimulation.Constants.inf; + import BusinessSimulation.Types.InitializationOptions; + extends Icons.SubsystemTransceiver; + extends Interfaces.Basics.OutputTypeChoice; + Interfaces.Connectors.StockPort stockPort "Receiving side of the element" annotation(Placement(visible = true, transformation(origin = {-148.207, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-100, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.FlowPort flowPort if hasFlowPort annotation(Placement(visible = true, transformation(origin = {148.053, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {100, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealInput u "Rate of outflow from the stock" annotation(Placement(visible = true, transformation(origin = {-145, 60}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-50, 100}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Interfaces.Connectors.StockInfoOutput y_stockInfo if hasStockInfoOutput "Optional StockInfoOutput" annotation(Placement(visible = true, transformation(origin = {150, -80}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {80, 104}, extent = {{-10, -10}, {10, 10}}, rotation = -270))); + RealOutput y "Amount in the stock" annotation(Placement(visible = true, transformation(origin = {160, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {50, 104}, extent = {{10, -10}, {-10, 10}}, rotation = -90))); + parameter OutputType initialValue = 0 "Initial level of stock"; + parameter OutputType maxValue = inf "Maximum admissable value (reservoir.maxValue)"; + parameter OutputType minValue = -inf "Minimum admissable value (reservoir.minValue)"; + parameter Boolean hasStockInfoOutput = false "= true, if a StockInfoOutput should be added to the stock (reservoir.hasStockInfoOutput)" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean hasFlowPort = true "= true, if the outflow from the stock will go to a flow port instead of a cloud" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter InitializationOptions init = modelSettings.init "Provide InitializationOptions (Free, FixedValue, SteadyState) (reservoir.init)" annotation(Evaluate = true, Dialog(tab = "Advanced")); + parameter Boolean useAssert = false "= true, if leaving the admissable range is to cause an error or warning (reservoir.useAssert)" annotation(Evaluate = true, Dialog(tab = "Advanced")); + parameter Boolean causeError = true "= true, if leaving the admissable range is to cause an error instead of simply a warning (reservoir.causeError)" annotation(Evaluate = true, Dialog(tab = "Advanced")); + outer ModelSettings modelSettings; +protected + replaceable Stocks.InformationLevel stock(initialValue = initialValue, hasStockInfoOutput = hasStockInfoOutput, init = init, useAssert = useAssert, causeError = causeError, maxValue = maxValue, minValue = minValue) constrainedby BusinessSimulation.Interfaces.PartialStocks.BasicStock "The reservoir that is filled or drained by the connected flows." annotation(Placement(visible = true, transformation(origin = {0, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0)), choices(choice(redeclare replaceable BusinessSimulation.Stocks.InformationLevel stock(initialValue = initialValue, hasStockInfoOutput = hasStockInfoOutput, init = init, useAssert = useAssert, causeError = causeError, maxValue = maxValue, minValue = minValue) "Information Level"), choice(redeclare replaceable BusinessSimulation.Stocks.MaterialStock stock(initialValue = initialValue, hasStockInfoOutput = hasStockInfoOutput, init = init, useAssert = useAssert, causeError = causeError, maxValue = maxValue, minValue = minValue) "Material Stock"), choice(redeclare replaceable BusinessSimulation.Stocks.CapacityRestrictedStock stock(initialValue = initialValue, hasStockInfoOutput = hasStockInfoOutput, init = init, useAssert = useAssert, causeError = causeError, maxValue = maxValue, minValue = minValue) "Capacity Restricted Stock"))); + Flows.Unidirectional.Transition movingOn annotation(Placement(visible = true, transformation(origin = {40, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + SourcesOrSinks.Cloud cloud if not hasFlowPort "System boundary" annotation(Placement(visible = true, transformation(origin = {105, -20}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); +equation + connect(u, movingOn.u) annotation(Line(visible = true, origin = {-25, 43.333}, points = {{-120, 16.667}, {60, 16.667}, {60, -33.333}}, color = {0, 0, 127})); + connect(stock.outflow, movingOn.portA) annotation(Line(visible = true, origin = {20, 0}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(movingOn.portB, flowPort) annotation(Line(visible = true, origin = {99.026, 0}, points = {{-49.026, 0}, {49.026, 0}}, color = {128, 0, 128})); + connect(stock.inflow, stockPort) annotation(Line(visible = true, origin = {-79.103, 0}, points = {{69.103, 0}, {-69.103, 0}}, color = {128, 0, 128})); + connect(stock.y, y) annotation(Line(visible = true, origin = {56.667, 30.133}, points = {{-51.667, -19.733}, {-51.667, 9.867}, {103.333, 9.867}}, color = {1, 37, 163})); + connect(stock.y_stockInfo, y_stockInfo) annotation(Line(visible = true, origin = {65.2, -21.92}, points = {{-57.2, 32.32}, {-57.2, 41.92}, {14.8, 41.92}, {14.8, -58.08}, {84.8, -58.08}}, color = {128, 0, 128})); + connect(movingOn.portB, cloud.massPort) annotation(Line(visible = true, origin = {66.25, -10}, points = {{-16.25, 10}, {-6.25, 10}, {-6.25, -10}, {28.75, -10}}, color = {128, 0, 128})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The reservoir structure consists of a stock component that is typically filled via the accumulated net flow received at its stockPort. The stock is then drained at a rate set by the input u.

+

Implementation

+

The stock component used is declared as

+
replaceable Stocks.Informationlevel stock constrainedby Interfaces.PartialStocks.BasicStock
+

Accordingly the →InformationLevel can be redeclared either as a →MaterialStock or a →CapacityRestrictedStock.

+

See also

+

+Account, +Chain +

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {-4.16, -0.234}, points = {{0, 0}, {28.109, 0}}, color = {0, 128, 0}, thickness = 5), Ellipse(visible = true, origin = {9.978, 0}, lineColor = {0, 128, 0}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 0.5, extent = {{-4.138, -4.138}, {4.138, 4.138}}), Rectangle(visible = true, origin = {-14.948, 0}, lineColor = {255, 0, 0}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 3, extent = {{-10, -10}, {10, 10}}), Polygon(visible = true, origin = {24.453, -0.275}, lineColor = {0, 128, 0}, fillColor = {0, 128, 0}, fillPattern = FillPattern.Solid, points = {{-2.773, 3.823}, {-2.773, -3.863}, {5.547, 0.041}}), Text(visible = true, origin = {0, 75}, textColor = {76, 112, 136}, extent = {{-100, -12}, {100, 12}}, textString = "Reservoir", fontName = "Lato Black", textStyle = {TextStyle.Bold})})); +end Reservoir; diff --git a/BusinessSimulation/MoleculesOfStructure/Transceivers/SplitFlow.mo b/BusinessSimulation/MoleculesOfStructure/Transceivers/SplitFlow.mo new file mode 100644 index 0000000..52ddb09 --- /dev/null +++ b/BusinessSimulation/MoleculesOfStructure/Transceivers/SplitFlow.mo @@ -0,0 +1,60 @@ +within BusinessSimulation.MoleculesOfStructure.Transceivers; + +model SplitFlow "Splitting an arbitrary flow into n subflows" + extends Interfaces.Basics.OutputTypeChoice(redeclare replaceable type OutputType = Units.Rate); + extends Icons.SubsystemTransceiver; + RealMultiOutput[nout] y "Rates of the split flows" annotation(Placement(visible = true, transformation(origin = {150, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {50, 104}, extent = {{-10, -10}, {10, 10}}, rotation = -270))); + Interfaces.Connectors.StockPort stockPort "Connected to incoming flow to be split or broken up" annotation(Placement(visible = true, transformation(origin = {-148.287, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-100, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.FlowMultiPort flowPort[nout] "n-dimensional array of outgoing flows" annotation(Placement(visible = true, transformation(origin = {147.761, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {100, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealMultiInput u[nout] if not hasConstantWeights "Vector of weights for the splits or breaks" annotation(Placement(visible = true, transformation(origin = {-145, 60}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-50, 100}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + parameter Real[nout] weights = ones(nout) "Constant weights for splitting (optional)" annotation(Dialog(enable = hasConstantWeights)); + parameter Integer nout(min = 1) = 2 "Number of flows to split into" annotation(Dialog(group = "Structural Parameters")); + parameter Boolean hasConstantWeights = false "= true, if the weights are constant parameters" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean isSplit = true "= true, if the input given is assumed to be weights (adding up to one) splitting the flow" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean shiftInputs = false "= true, if all values are to be shifted to prevent negative inputs, otherwise negative inputs are simply set to zero (proportionalSplitFactors.shiftInputs)" annotation(Dialog(enable = isSplit, group = "Structural Parameters")); +protected + Converters.Vector.ProportionalSplitFactors proportionalSplitFactors(nin = nout, shiftInputs = shiftInputs) if isSplit "Split factors adding up to one" annotation(Placement(visible = true, transformation(origin = {-90, 60}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.PassThrough unchangedInput[nout] if not isSplit annotation(Placement(visible = true, transformation(origin = {-90, 80}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Sensors.StockPortSensor_Control sensor_A "Measuring the flow and seting the flags" annotation(Placement(visible = true, transformation(origin = {-120, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Sensors.FlowPortSensor_Control sensor_B[nout] "Measuring stock level and Boolean flags" annotation(Placement(visible = true, transformation(origin = {110, 11.975}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Converters.Logical.AnyTrue stopInflow(nin = nout) annotation(Placement(visible = true, transformation(origin = {20, 25}, extent = {{10, 10}, {-10, -10}}, rotation = 0))); + Converters.Logical.AnyTrue stopOutflow(nin = nout) annotation(Placement(visible = true, transformation(origin = {50, 15}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Converters.Vector.ConstantConverter parWeights(value = weights, redeclare replaceable type OutputType = Units.Dimensionless) if hasConstantWeights "Constant weights for splitting (optional)" annotation(Placement(visible = true, transformation(origin = {-135, 95}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Flows.Bidirectional.Switching splitFlows[nout] "The splitted outflow" annotation(Placement(visible = true, transformation(origin = {-30, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + SourcesOrSinks.Cloud cloudOutflow "Cloud connected to the aggregate outflow" annotation(Placement(visible = true, transformation(origin = {-90, 0}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + SourcesOrSinks.Cloud[nout] cloudBrokenFlow "Clouds connected to the broken flows" annotation(Placement(visible = true, transformation(origin = {-70, 0}, extent = {{10, -10}, {-10, 10}}, rotation = 180))); + Converters.Vector.ScalarMultiplication splitRates(nin = nout) "The rates for the split flows" annotation(Placement(visible = true, transformation(origin = {-50, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(cloudBrokenFlow.massPort, splitFlows.portA) annotation(Line(visible = true, origin = {-50, 0}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(splitFlows.portB, flowPort) annotation(Line(visible = true, origin = {63.88, 0}, points = {{-83.88, 0}, {83.88, 0}}, color = {128, 0, 128})); + connect(proportionalSplitFactors.y, splitRates.u1) annotation(Line(visible = true, origin = {-81.782, 52.519}, points = {{-0.218, 7.481}, {16.782, 7.481}, {16.782, -7.557}, {23.744, -7.557}}, color = {1, 37, 163})); + connect(u, proportionalSplitFactors.u) annotation(Line(visible = true, origin = {-121.5, 60}, points = {{-23.5, 0}, {23.5, 0}}, color = {1, 37, 163})); + connect(splitRates.y, splitFlows.u) annotation(Line(visible = true, origin = {-37.5, 30}, points = {{-5, 10}, {2.5, 10}, {2.5, -20}}, color = {1, 37, 163})); + connect(u, unchangedInput.u) annotation(Line(visible = true, origin = {-136.568, 70}, points = {{-8.432, -10}, {1.568, -10}, {1.568, 10}, {38.568, 10}}, color = {1, 37, 163})); + connect(unchangedInput.y, splitRates.u1) annotation(Line(visible = true, origin = {-82.908, 62.481}, points = {{0.908, 17.519}, {17.908, 17.519}, {17.908, -17.519}, {24.87, -17.519}}, color = {1, 37, 163})); + connect(stockPort, sensor_A.stockPort) annotation(Line(visible = true, origin = {-139.144, 0}, points = {{-9.143, 0}, {9.144, 0}}, color = {128, 0, 128})); + connect(sensor_A.flowPort, cloudOutflow.massPort) annotation(Line(visible = true, origin = {-105.118, 0}, points = {{-5.118, 0}, {5.118, -0}}, color = {128, 0, 128})); + connect(sensor_A.netFlow, splitRates.u2) annotation(Line(visible = true, origin = {-94.804, 29.009}, points = {{-25.172, -18.009}, {-25.172, 5.991}, {36.766, 5.991}, {36.766, 6.029}}, color = {1, 37, 163})); + connect(sensor_B.flowPort, flowPort) annotation(Line(visible = true, origin = {135.174, 7.983}, points = {{-25.174, 3.992}, {12.587, 3.992}, {12.587, -7.983}}, color = {128, 0, 128})); + connect(sensor_B.stopInflow, stopInflow.u) annotation(Line(visible = true, origin = {97.5, 19.987}, points = {{14.5, -5.013}, {27.5, -5.013}, {27.5, 5.013}, {-69.5, 5.013}}, color = {255, 0, 255})); + connect(sensor_B.stopOutflow, stopOutflow.u) annotation(Line(visible = true, origin = {89, 14.987}, points = {{19, -0.013}, {6, -0.013}, {6, 0.013}, {-31, 0.013}}, color = {255, 0, 255})); + connect(stopInflow.y, sensor_A.u_stopInflow) annotation(Line(visible = true, origin = {-79.333, 20}, points = {{91.333, 5}, {-45.667, 5}, {-45.667, -10}}, color = {255, 0, 255})); + connect(stopOutflow.y, sensor_A.u_stopOutflow) annotation(Line(visible = true, origin = {-62.667, 13.333}, points = {{104.667, 1.667}, {-52.334, 1.667}, {-52.334, -3.334}}, color = {255, 0, 255})); + connect(splitFlows.y, y) annotation(Line(visible = true, origin = {33.333, 30.133}, points = {{-58.333, -19.733}, {-58.333, 9.867}, {116.667, 9.867}}, color = {1, 37, 163})); + connect(parWeights.y, unchangedInput.u) annotation(Line(visible = true, origin = {-116.75, 87.5}, points = {{-12.25, 7.5}, {-3.25, 7.5}, {-3.25, -7.5}, {18.75, -7.5}}, color = {1, 37, 163})); + connect(parWeights.y, proportionalSplitFactors.u) annotation(Line(visible = true, origin = {-116.75, 77.5}, points = {{-12.25, 17.5}, {-3.25, 17.5}, {-3.25, -17.5}, {18.75, -17.5}}, color = {1, 37, 163})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The flow connected to the stock port (stockPort) will be split or broken into n = nout flows. This is a rather generic component, so that the input vector u of weights or factors may add up to 1 (the flow is split into n components that in sum will match the aggregate flow) or not.

+

When the factors do not add up to 1, the structure can be used to describe some kind of multiple-production from one main effort, e.g. the flow of work hours per period may be used to produce n products according to a productivity ratio ( products per work hour ).

+

Notes

+ +

See also

+ProportionalSplitFactors, +BrokenTransition, +BrokenTransitionPull +"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {21.891, 0}, points = {{0, 0}, {18.109, 0}}, color = {0, 128, 0}, thickness = 5), Ellipse(visible = true, origin = {32.283, 0}, lineColor = {0, 128, 0}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 0.5, extent = {{-4.138, -4.138}, {4.138, 4.138}}), Text(visible = true, origin = {0, 75}, textColor = {76, 112, 136}, extent = {{-100, -12}, {100, 12}}, textString = "Split Flow", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Rectangle(visible = true, origin = {4, 32.089}, lineColor = {255, 0, 0}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 3, extent = {{-10, -10}, {10, 10}}), Line(visible = true, origin = {7.759, 28.479}, points = {{-10.617, 2.61}, {-8.681, 8.473}, {-0.406, -1.527}, {2.998, 2.61}, {-0.784, 8.473}, {-7.213, -1.172}, {-10.617, 2.61}}, color = {255, 0, 0}, thickness = 1.5, smooth = Smooth.Bezier), Polygon(visible = true, origin = {42.453, 31.814}, lineColor = {0, 128, 0}, fillColor = {0, 128, 0}, fillPattern = FillPattern.Solid, points = {{-2.773, 3.823}, {-2.773, -3.863}, {5.547, 0.041}}), Rectangle(visible = true, origin = {4, 0}, lineColor = {255, 0, 0}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 3, extent = {{-10, -10}, {10, 10}}), Line(visible = true, origin = {7.759, -3.61}, points = {{-10.617, 2.61}, {-8.681, 8.473}, {-0.406, -1.527}, {2.998, 2.61}, {-0.784, 8.473}, {-7.213, -1.172}, {-10.617, 2.61}}, color = {255, 0, 0}, thickness = 1.5, smooth = Smooth.Bezier), Polygon(visible = true, origin = {42.453, -0.275}, lineColor = {0, 128, 0}, fillColor = {0, 128, 0}, fillPattern = FillPattern.Solid, points = {{-2.773, 3.823}, {-2.773, -3.863}, {5.547, 0.041}}), Line(visible = true, origin = {21.891, -32.153}, points = {{0, 0}, {18.109, 0}}, color = {0, 128, 0}, thickness = 5), Ellipse(visible = true, origin = {31.978, -31.884}, lineColor = {0, 128, 0}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 0.5, extent = {{-4.138, -4.138}, {4.138, 4.138}}), Rectangle(visible = true, origin = {4, -31.884}, lineColor = {255, 0, 0}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 3, extent = {{-10, -10}, {10, 10}}), Line(visible = true, origin = {7.759, -35.495}, points = {{-10.617, 2.61}, {-8.681, 8.473}, {-0.406, -1.527}, {2.998, 2.61}, {-0.784, 8.473}, {-7.213, -1.172}, {-10.617, 2.61}}, color = {255, 0, 0}, thickness = 1.5, smooth = Smooth.Bezier), Polygon(visible = true, origin = {42.453, -32.159}, lineColor = {0, 128, 0}, fillColor = {0, 128, 0}, fillPattern = FillPattern.Solid, points = {{-2.773, 3.823}, {-2.773, -3.863}, {5.547, 0.041}}), Rectangle(visible = true, origin = {-49, 0}, lineColor = {255, 0, 0}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 3, extent = {{-10, -10}, {10, 10}}), Line(visible = true, origin = {-44.998, -3.473}, points = {{-10.617, 2.61}, {-8.681, 8.473}, {-0.406, -1.527}, {2.998, 2.61}, {-0.784, 8.473}, {-7.213, -1.172}, {-10.617, 2.61}}, color = {255, 0, 0}, thickness = 1.5, smooth = Smooth.Bezier), Line(visible = true, origin = {-39.586, -75.667}, points = {{9.586, 100.926}, {9.586, 93.462}, {71.923, 93.462}, {71.923, 87.412}}, color = {0, 0, 128}, thickness = 2), Line(visible = true, origin = {-39.586, -106.737}, points = {{9.586, 126.737}, {9.586, 90.254}, {71.771, 90.254}, {71.771, 86.737}}, color = {0, 0, 128}, thickness = 2), Polygon(visible = true, origin = {31.328, 40.586}, rotation = -90, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, points = {{-2.773, 2.672}, {-2.773, -2.623}, {3.945, -0.02}}), Polygon(visible = true, origin = {32.328, 8.227}, rotation = -90, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, points = {{-2.773, 2.672}, {-2.773, -2.623}, {3.945, -0.02}}), Polygon(visible = true, origin = {31.975, -23.773}, rotation = -90, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, points = {{-2.773, 2.672}, {-2.773, -2.623}, {3.945, -0.02}}), Line(visible = true, origin = {-38.586, -43.462}, points = {{-36.613, 48.343}, {-36.613, 68}, {8.586, 68}, {8.586, 93.462}, {70.313, 93.462}, {70.313, 88.612}}, color = {0, 0, 128}, thickness = 2), Line(visible = true, origin = {-82.434, 0}, points = {{0, 0}, {15.777, 0}}, color = {0, 128, 0}, thickness = 5), Ellipse(visible = true, origin = {-75.022, 0.089}, lineColor = {0, 128, 0}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 0.5, extent = {{-4.138, -4.138}, {4.138, 4.138}}), Polygon(visible = true, origin = {-65.547, -0.186}, lineColor = {0, 128, 0}, fillColor = {0, 128, 0}, fillPattern = FillPattern.Solid, points = {{-2.773, 3.823}, {-2.773, -3.863}, {5.547, 0.041}}), Text(visible = true, origin = {0, -70}, extent = {{-97.365, -6}, {97.365, 6}}, textString = "n = %nout", fontName = "Lato", textStyle = {TextStyle.Bold}), Polygon(visible = true, origin = {-84.453, 0.02}, lineColor = {0, 128, 0}, fillColor = {0, 128, 0}, fillPattern = FillPattern.Solid, points = {{2.773, 3.823}, {2.773, -3.863}, {-5.547, 0.041}}), Polygon(visible = true, origin = {21.644, -31.928}, lineColor = {0, 128, 0}, fillColor = {0, 128, 0}, fillPattern = FillPattern.Solid, points = {{2.773, 3.823}, {2.773, -3.863}, {-5.547, 0.041}}), Polygon(visible = true, origin = {21.644, 0.072}, lineColor = {0, 128, 0}, fillColor = {0, 128, 0}, fillPattern = FillPattern.Solid, points = {{2.773, 3.823}, {2.773, -3.863}, {-5.547, 0.041}}), Polygon(visible = true, origin = {21.644, 32.072}, lineColor = {0, 128, 0}, fillColor = {0, 128, 0}, fillPattern = FillPattern.Solid, points = {{2.773, 3.823}, {2.773, -3.863}, {-5.547, 0.041}}), Line(visible = true, origin = {22.891, 32}, points = {{0, 0}, {18.109, 0}}, color = {0, 128, 0}, thickness = 5), Ellipse(visible = true, origin = {31.978, 32.089}, lineColor = {0, 128, 0}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 0.5, extent = {{-4.138, -4.138}, {4.138, 4.138}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end SplitFlow; diff --git a/BusinessSimulation/MoleculesOfStructure/Transceivers/package.mo b/BusinessSimulation/MoleculesOfStructure/Transceivers/package.mo new file mode 100644 index 0000000..9b5a247 --- /dev/null +++ b/BusinessSimulation/MoleculesOfStructure/Transceivers/package.mo @@ -0,0 +1,12 @@ +within BusinessSimulation.MoleculesOfStructure; + +package Transceivers "Subsystems with a mix of stock and flow ports" + extends Icons.Package; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Transceivers are the most general type of subsystem as they will be receptors as well as actuators with regard to physical entities (\"mass\"). Typically all manufacturing in an economy (seconday sector) can by seen as a transceiver, receiving raw material while pushing onward finished goods to distributors. Note, that when order flows are modeled explicitly even subsystems of the primary sector (e.g. mining, fishing, and agriculture) may be modeled as transceivers.

+

On a lower level of aggregation we may simply conceive of transceivers as subsystems that start with a stock port on one end while transmitting stuff via a flow port on the other end.

+

+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, origin = {0, 5}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, lineThickness = 7, extent = {{-62.764, -53.47}, {62.764, 53.47}}), Rectangle(visible = true, origin = {-62.781, 4.645}, lineColor = {255, 255, 255}, fillColor = {76, 112, 136}, fillPattern = FillPattern.Solid, lineThickness = 7, extent = {{-10.968, -11.451}, {10.968, 11.451}}), Rectangle(visible = true, origin = {62.219, 4.645}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 7, extent = {{-10.968, -11.451}, {10.968, 11.451}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Transceivers; diff --git a/BusinessSimulation/MoleculesOfStructure/Transceivers/package.order b/BusinessSimulation/MoleculesOfStructure/Transceivers/package.order new file mode 100644 index 0000000..012086b --- /dev/null +++ b/BusinessSimulation/MoleculesOfStructure/Transceivers/package.order @@ -0,0 +1,3 @@ +SplitFlow +Reservoir +Chain diff --git a/BusinessSimulation/MoleculesOfStructure/package.mo b/BusinessSimulation/MoleculesOfStructure/package.mo new file mode 100644 index 0000000..015094b --- /dev/null +++ b/BusinessSimulation/MoleculesOfStructure/package.mo @@ -0,0 +1,20 @@ +within BusinessSimulation; + +package MoleculesOfStructure "Pre-built components to model decision making, information processing, and subsystems in general" + extends Icons.Package; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This package contains generic model structure widely used by the System Dynamics community. Since this library makes use of acausal connectors to represent \"mass ports\"—connectors for what would be a double arrow connecting in classical System Dynamics notation—it turned out, that the organization of Molecules in this library should best be done with a focus on the actual interfaces (i.e. connectors) of a generic structure.

+

Acknowledgements

+

There exist well known generic structures in the System Dynamics methodology that are reused over and over—quite independent from the actual modeling domain. James \"Jim\" Hines [6] has meticulously collected such elementary structures and coined the term \"Molecules of Structure\".

+

In building the Business Simulation Library the name \"Molecules of Structure\" was adapted and whenever possible it was tried to stick to the names in Jim Hines' publication as that use is widespread in the System Dynamics community. Nevertheless, the object-oriented nature of Modelica allows to do what Hines has only hinted at: It can reuse components and thus truly arrive at new structure built upon existing structure.

+

See also

+

+Tutorial.ElementaryBuildingBlocks, +Molecules of Structure Website (maintained by Jim Hines) +

+
+
+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Ellipse(visible = true, origin = {-39.037, 49.037}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-20.963, -20.963}, {20.963, 20.963}}), Ellipse(visible = true, origin = {-20, -47.43}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-20.963, -20.963}, {20.963, 20.963}}), Ellipse(visible = true, origin = {49.037, 19.037}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-20.963, -20.963}, {20.963, 20.963}}), Line(visible = true, origin = {27.649, -23.009}, points = {{-67.649, 75.352}, {-47.649, -29.74}, {22.351, 46.555}}, color = {255, 255, 255}, thickness = 3), Line(visible = true, origin = {35.649, -31.009}, points = {{-67.649, 75.352}, {11.756, 51.009}}, color = {255, 255, 255}, thickness = 3)}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end MoleculesOfStructure; diff --git a/BusinessSimulation/MoleculesOfStructure/package.order b/BusinessSimulation/MoleculesOfStructure/package.order new file mode 100644 index 0000000..8f95c6a --- /dev/null +++ b/BusinessSimulation/MoleculesOfStructure/package.order @@ -0,0 +1,6 @@ +InformationProcessing +Policy +Blocks +Incubators +Transceivers +Actuators diff --git a/BusinessSimulation/Resources/Images/BusinessSimulation.svg b/BusinessSimulation/Resources/Images/BusinessSimulation.svg new file mode 100644 index 0000000..3e653da --- /dev/null +++ b/BusinessSimulation/Resources/Images/BusinessSimulation.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Converters.png b/BusinessSimulation/Resources/Images/Converters.png new file mode 100644 index 0000000..fa62a2f Binary files /dev/null and b/BusinessSimulation/Resources/Images/Converters.png differ diff --git a/BusinessSimulation/Resources/Images/Converters.svg b/BusinessSimulation/Resources/Images/Converters.svg new file mode 100644 index 0000000..21f335a --- /dev/null +++ b/BusinessSimulation/Resources/Images/Converters.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Converters/DiscreteDelay/Smooth/Formula.png b/BusinessSimulation/Resources/Images/Converters/DiscreteDelay/Smooth/Formula.png new file mode 100644 index 0000000..c897af9 Binary files /dev/null and b/BusinessSimulation/Resources/Images/Converters/DiscreteDelay/Smooth/Formula.png differ diff --git a/BusinessSimulation/Resources/Images/Converters/DiscreteDelay/Smooth/Formula.svg b/BusinessSimulation/Resources/Images/Converters/DiscreteDelay/Smooth/Formula.svg new file mode 100644 index 0000000..f05b722 --- /dev/null +++ b/BusinessSimulation/Resources/Images/Converters/DiscreteDelay/Smooth/Formula.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Converters/Lookup/ConcaveLookupNegative/Formula.png b/BusinessSimulation/Resources/Images/Converters/Lookup/ConcaveLookupNegative/Formula.png new file mode 100644 index 0000000..655a69f Binary files /dev/null and b/BusinessSimulation/Resources/Images/Converters/Lookup/ConcaveLookupNegative/Formula.png differ diff --git a/BusinessSimulation/Resources/Images/Converters/Lookup/ConcaveLookupNegative/Formula.svg b/BusinessSimulation/Resources/Images/Converters/Lookup/ConcaveLookupNegative/Formula.svg new file mode 100644 index 0000000..9c12835 --- /dev/null +++ b/BusinessSimulation/Resources/Images/Converters/Lookup/ConcaveLookupNegative/Formula.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Converters/Lookup/ConcaveLookupNegative/Graph.png b/BusinessSimulation/Resources/Images/Converters/Lookup/ConcaveLookupNegative/Graph.png new file mode 100644 index 0000000..1f0b307 Binary files /dev/null and b/BusinessSimulation/Resources/Images/Converters/Lookup/ConcaveLookupNegative/Graph.png differ diff --git a/BusinessSimulation/Resources/Images/Converters/Lookup/ConcaveLookupNegative/Graph.svg b/BusinessSimulation/Resources/Images/Converters/Lookup/ConcaveLookupNegative/Graph.svg new file mode 100644 index 0000000..98841a5 --- /dev/null +++ b/BusinessSimulation/Resources/Images/Converters/Lookup/ConcaveLookupNegative/Graph.svg @@ -0,0 +1,438 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Converters/Lookup/ConcaveLookupPositive/Formula.png b/BusinessSimulation/Resources/Images/Converters/Lookup/ConcaveLookupPositive/Formula.png new file mode 100644 index 0000000..5a5a7a5 Binary files /dev/null and b/BusinessSimulation/Resources/Images/Converters/Lookup/ConcaveLookupPositive/Formula.png differ diff --git a/BusinessSimulation/Resources/Images/Converters/Lookup/ConcaveLookupPositive/Formula.svg b/BusinessSimulation/Resources/Images/Converters/Lookup/ConcaveLookupPositive/Formula.svg new file mode 100644 index 0000000..394ae4b --- /dev/null +++ b/BusinessSimulation/Resources/Images/Converters/Lookup/ConcaveLookupPositive/Formula.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Converters/Lookup/ConcaveLookupPositive/Graph.png b/BusinessSimulation/Resources/Images/Converters/Lookup/ConcaveLookupPositive/Graph.png new file mode 100644 index 0000000..55d0615 Binary files /dev/null and b/BusinessSimulation/Resources/Images/Converters/Lookup/ConcaveLookupPositive/Graph.png differ diff --git a/BusinessSimulation/Resources/Images/Converters/Lookup/ConcaveLookupPositive/Graph.svg b/BusinessSimulation/Resources/Images/Converters/Lookup/ConcaveLookupPositive/Graph.svg new file mode 100644 index 0000000..ca23f06 --- /dev/null +++ b/BusinessSimulation/Resources/Images/Converters/Lookup/ConcaveLookupPositive/Graph.svg @@ -0,0 +1,343 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Converters/Lookup/ConvexLookupNegative/Formula.png b/BusinessSimulation/Resources/Images/Converters/Lookup/ConvexLookupNegative/Formula.png new file mode 100644 index 0000000..1829646 Binary files /dev/null and b/BusinessSimulation/Resources/Images/Converters/Lookup/ConvexLookupNegative/Formula.png differ diff --git a/BusinessSimulation/Resources/Images/Converters/Lookup/ConvexLookupNegative/Formula.svg b/BusinessSimulation/Resources/Images/Converters/Lookup/ConvexLookupNegative/Formula.svg new file mode 100644 index 0000000..05893b0 --- /dev/null +++ b/BusinessSimulation/Resources/Images/Converters/Lookup/ConvexLookupNegative/Formula.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Converters/Lookup/ConvexLookupNegative/Graph.png b/BusinessSimulation/Resources/Images/Converters/Lookup/ConvexLookupNegative/Graph.png new file mode 100644 index 0000000..50078c5 Binary files /dev/null and b/BusinessSimulation/Resources/Images/Converters/Lookup/ConvexLookupNegative/Graph.png differ diff --git a/BusinessSimulation/Resources/Images/Converters/Lookup/ConvexLookupNegative/Graph.svg b/BusinessSimulation/Resources/Images/Converters/Lookup/ConvexLookupNegative/Graph.svg new file mode 100644 index 0000000..d53faa1 --- /dev/null +++ b/BusinessSimulation/Resources/Images/Converters/Lookup/ConvexLookupNegative/Graph.svg @@ -0,0 +1,359 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Converters/Lookup/ConvexLookupPositive/Formula.png b/BusinessSimulation/Resources/Images/Converters/Lookup/ConvexLookupPositive/Formula.png new file mode 100644 index 0000000..7ddfa6d Binary files /dev/null and b/BusinessSimulation/Resources/Images/Converters/Lookup/ConvexLookupPositive/Formula.png differ diff --git a/BusinessSimulation/Resources/Images/Converters/Lookup/ConvexLookupPositive/Formula.svg b/BusinessSimulation/Resources/Images/Converters/Lookup/ConvexLookupPositive/Formula.svg new file mode 100644 index 0000000..310f33e --- /dev/null +++ b/BusinessSimulation/Resources/Images/Converters/Lookup/ConvexLookupPositive/Formula.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Converters/Lookup/ConvexLookupPositive/Graph.png b/BusinessSimulation/Resources/Images/Converters/Lookup/ConvexLookupPositive/Graph.png new file mode 100644 index 0000000..41b3a5f Binary files /dev/null and b/BusinessSimulation/Resources/Images/Converters/Lookup/ConvexLookupPositive/Graph.png differ diff --git a/BusinessSimulation/Resources/Images/Converters/Lookup/ConvexLookupPositive/Graph.svg b/BusinessSimulation/Resources/Images/Converters/Lookup/ConvexLookupPositive/Graph.svg new file mode 100644 index 0000000..350436d --- /dev/null +++ b/BusinessSimulation/Resources/Images/Converters/Lookup/ConvexLookupPositive/Graph.svg @@ -0,0 +1,347 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Converters/Lookup/JanoschekNegative/AnimatedGraph.gif b/BusinessSimulation/Resources/Images/Converters/Lookup/JanoschekNegative/AnimatedGraph.gif new file mode 100644 index 0000000..a819c46 Binary files /dev/null and b/BusinessSimulation/Resources/Images/Converters/Lookup/JanoschekNegative/AnimatedGraph.gif differ diff --git a/BusinessSimulation/Resources/Images/Converters/Lookup/JanoschekNegative/Formula.png b/BusinessSimulation/Resources/Images/Converters/Lookup/JanoschekNegative/Formula.png new file mode 100644 index 0000000..19bcf8d Binary files /dev/null and b/BusinessSimulation/Resources/Images/Converters/Lookup/JanoschekNegative/Formula.png differ diff --git a/BusinessSimulation/Resources/Images/Converters/Lookup/JanoschekNegative/Formula.svg b/BusinessSimulation/Resources/Images/Converters/Lookup/JanoschekNegative/Formula.svg new file mode 100644 index 0000000..9bdbcab --- /dev/null +++ b/BusinessSimulation/Resources/Images/Converters/Lookup/JanoschekNegative/Formula.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Converters/Lookup/JanoschekPositive/AnimatedGraph.gif b/BusinessSimulation/Resources/Images/Converters/Lookup/JanoschekPositive/AnimatedGraph.gif new file mode 100644 index 0000000..5dafed0 Binary files /dev/null and b/BusinessSimulation/Resources/Images/Converters/Lookup/JanoschekPositive/AnimatedGraph.gif differ diff --git a/BusinessSimulation/Resources/Images/Converters/Lookup/JanoschekPositive/Formula.png b/BusinessSimulation/Resources/Images/Converters/Lookup/JanoschekPositive/Formula.png new file mode 100644 index 0000000..b2bb7bb Binary files /dev/null and b/BusinessSimulation/Resources/Images/Converters/Lookup/JanoschekPositive/Formula.png differ diff --git a/BusinessSimulation/Resources/Images/Converters/Lookup/JanoschekPositive/Formula.svg b/BusinessSimulation/Resources/Images/Converters/Lookup/JanoschekPositive/Formula.svg new file mode 100644 index 0000000..878e623 --- /dev/null +++ b/BusinessSimulation/Resources/Images/Converters/Lookup/JanoschekPositive/Formula.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Converters/Lookup/PerformanceIndicator/Grid.png b/BusinessSimulation/Resources/Images/Converters/Lookup/PerformanceIndicator/Grid.png new file mode 100644 index 0000000..6d7a589 Binary files /dev/null and b/BusinessSimulation/Resources/Images/Converters/Lookup/PerformanceIndicator/Grid.png differ diff --git a/BusinessSimulation/Resources/Images/Converters/Lookup/PerformanceIndicator/Grid.svg b/BusinessSimulation/Resources/Images/Converters/Lookup/PerformanceIndicator/Grid.svg new file mode 100644 index 0000000..416c086 --- /dev/null +++ b/BusinessSimulation/Resources/Images/Converters/Lookup/PerformanceIndicator/Grid.svg @@ -0,0 +1,1505 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Converters/Lookup/SShapedNegative/Formula.png b/BusinessSimulation/Resources/Images/Converters/Lookup/SShapedNegative/Formula.png new file mode 100644 index 0000000..f2df926 Binary files /dev/null and b/BusinessSimulation/Resources/Images/Converters/Lookup/SShapedNegative/Formula.png differ diff --git a/BusinessSimulation/Resources/Images/Converters/Lookup/SShapedNegative/Formula.svg b/BusinessSimulation/Resources/Images/Converters/Lookup/SShapedNegative/Formula.svg new file mode 100644 index 0000000..a7a0652 --- /dev/null +++ b/BusinessSimulation/Resources/Images/Converters/Lookup/SShapedNegative/Formula.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Converters/Lookup/SShapedNegative/Graph.png b/BusinessSimulation/Resources/Images/Converters/Lookup/SShapedNegative/Graph.png new file mode 100644 index 0000000..8676ff3 Binary files /dev/null and b/BusinessSimulation/Resources/Images/Converters/Lookup/SShapedNegative/Graph.png differ diff --git a/BusinessSimulation/Resources/Images/Converters/Lookup/SShapedNegative/Graph.svg b/BusinessSimulation/Resources/Images/Converters/Lookup/SShapedNegative/Graph.svg new file mode 100644 index 0000000..69319e9 --- /dev/null +++ b/BusinessSimulation/Resources/Images/Converters/Lookup/SShapedNegative/Graph.svg @@ -0,0 +1,319 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Converters/Lookup/SShapedPositive/Formula.png b/BusinessSimulation/Resources/Images/Converters/Lookup/SShapedPositive/Formula.png new file mode 100644 index 0000000..3f98be7 Binary files /dev/null and b/BusinessSimulation/Resources/Images/Converters/Lookup/SShapedPositive/Formula.png differ diff --git a/BusinessSimulation/Resources/Images/Converters/Lookup/SShapedPositive/Formula.svg b/BusinessSimulation/Resources/Images/Converters/Lookup/SShapedPositive/Formula.svg new file mode 100644 index 0000000..28b5077 --- /dev/null +++ b/BusinessSimulation/Resources/Images/Converters/Lookup/SShapedPositive/Formula.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Converters/Lookup/SShapedPositive/Graph.png b/BusinessSimulation/Resources/Images/Converters/Lookup/SShapedPositive/Graph.png new file mode 100644 index 0000000..0c0ec52 Binary files /dev/null and b/BusinessSimulation/Resources/Images/Converters/Lookup/SShapedPositive/Graph.png differ diff --git a/BusinessSimulation/Resources/Images/Converters/Lookup/SShapedPositive/Graph.svg b/BusinessSimulation/Resources/Images/Converters/Lookup/SShapedPositive/Graph.svg new file mode 100644 index 0000000..49a22c5 --- /dev/null +++ b/BusinessSimulation/Resources/Images/Converters/Lookup/SShapedPositive/Graph.svg @@ -0,0 +1,319 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Converters/PolynomialFunction/Formula.png b/BusinessSimulation/Resources/Images/Converters/PolynomialFunction/Formula.png new file mode 100644 index 0000000..0907094 Binary files /dev/null and b/BusinessSimulation/Resources/Images/Converters/PolynomialFunction/Formula.png differ diff --git a/BusinessSimulation/Resources/Images/Converters/PolynomialFunction/Formula.svg b/BusinessSimulation/Resources/Images/Converters/PolynomialFunction/Formula.svg new file mode 100644 index 0000000..838ed9a --- /dev/null +++ b/BusinessSimulation/Resources/Images/Converters/PolynomialFunction/Formula.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Converters/Vector/ArithmeticMean/Formula.png b/BusinessSimulation/Resources/Images/Converters/Vector/ArithmeticMean/Formula.png new file mode 100644 index 0000000..23da780 Binary files /dev/null and b/BusinessSimulation/Resources/Images/Converters/Vector/ArithmeticMean/Formula.png differ diff --git a/BusinessSimulation/Resources/Images/Converters/Vector/ArithmeticMean/Formula.svg b/BusinessSimulation/Resources/Images/Converters/Vector/ArithmeticMean/Formula.svg new file mode 100644 index 0000000..1e4002b --- /dev/null +++ b/BusinessSimulation/Resources/Images/Converters/Vector/ArithmeticMean/Formula.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Converters/Vector/DotProduct/Formula.png b/BusinessSimulation/Resources/Images/Converters/Vector/DotProduct/Formula.png new file mode 100644 index 0000000..5fd8f4d Binary files /dev/null and b/BusinessSimulation/Resources/Images/Converters/Vector/DotProduct/Formula.png differ diff --git a/BusinessSimulation/Resources/Images/Converters/Vector/DotProduct/Formula.svg b/BusinessSimulation/Resources/Images/Converters/Vector/DotProduct/Formula.svg new file mode 100644 index 0000000..486fb45 --- /dev/null +++ b/BusinessSimulation/Resources/Images/Converters/Vector/DotProduct/Formula.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Converters/Vector/GeometricMean/Formula.png b/BusinessSimulation/Resources/Images/Converters/Vector/GeometricMean/Formula.png new file mode 100644 index 0000000..640ef6e Binary files /dev/null and b/BusinessSimulation/Resources/Images/Converters/Vector/GeometricMean/Formula.png differ diff --git a/BusinessSimulation/Resources/Images/Converters/Vector/GeometricMean/Formula.svg b/BusinessSimulation/Resources/Images/Converters/Vector/GeometricMean/Formula.svg new file mode 100644 index 0000000..e2b25c4 --- /dev/null +++ b/BusinessSimulation/Resources/Images/Converters/Vector/GeometricMean/Formula.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Converters/Vector/Product/Formula.svg b/BusinessSimulation/Resources/Images/Converters/Vector/Product/Formula.svg new file mode 100644 index 0000000..ad267d1 --- /dev/null +++ b/BusinessSimulation/Resources/Images/Converters/Vector/Product/Formula.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Converters/Vector/ProportionalSplitFactors/Formula.png b/BusinessSimulation/Resources/Images/Converters/Vector/ProportionalSplitFactors/Formula.png new file mode 100644 index 0000000..70ed1e3 Binary files /dev/null and b/BusinessSimulation/Resources/Images/Converters/Vector/ProportionalSplitFactors/Formula.png differ diff --git a/BusinessSimulation/Resources/Images/Converters/Vector/ProportionalSplitFactors/Formula.svg b/BusinessSimulation/Resources/Images/Converters/Vector/ProportionalSplitFactors/Formula.svg new file mode 100644 index 0000000..945d673 --- /dev/null +++ b/BusinessSimulation/Resources/Images/Converters/Vector/ProportionalSplitFactors/Formula.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Converters/Vector/ProportionalSplitFactors/Formula2.png b/BusinessSimulation/Resources/Images/Converters/Vector/ProportionalSplitFactors/Formula2.png new file mode 100644 index 0000000..19048cc Binary files /dev/null and b/BusinessSimulation/Resources/Images/Converters/Vector/ProportionalSplitFactors/Formula2.png differ diff --git a/BusinessSimulation/Resources/Images/Converters/Vector/ProportionalSplitFactors/Formula2.svg b/BusinessSimulation/Resources/Images/Converters/Vector/ProportionalSplitFactors/Formula2.svg new file mode 100644 index 0000000..37d0794 --- /dev/null +++ b/BusinessSimulation/Resources/Images/Converters/Vector/ProportionalSplitFactors/Formula2.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Converters/Vector/ScalarMultiplication/Formula.png b/BusinessSimulation/Resources/Images/Converters/Vector/ScalarMultiplication/Formula.png new file mode 100644 index 0000000..1be4bed Binary files /dev/null and b/BusinessSimulation/Resources/Images/Converters/Vector/ScalarMultiplication/Formula.png differ diff --git a/BusinessSimulation/Resources/Images/Converters/Vector/ScalarMultiplication/Formula.svg b/BusinessSimulation/Resources/Images/Converters/Vector/ScalarMultiplication/Formula.svg new file mode 100644 index 0000000..481ce71 --- /dev/null +++ b/BusinessSimulation/Resources/Images/Converters/Vector/ScalarMultiplication/Formula.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Converters/Vector/Sum/Formula.png b/BusinessSimulation/Resources/Images/Converters/Vector/Sum/Formula.png new file mode 100644 index 0000000..492bd5b Binary files /dev/null and b/BusinessSimulation/Resources/Images/Converters/Vector/Sum/Formula.png differ diff --git a/BusinessSimulation/Resources/Images/Converters/Vector/Sum/Formula.svg b/BusinessSimulation/Resources/Images/Converters/Vector/Sum/Formula.svg new file mode 100644 index 0000000..0ef7b8d --- /dev/null +++ b/BusinessSimulation/Resources/Images/Converters/Vector/Sum/Formula.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Converters/Vector/Times/Formula.png b/BusinessSimulation/Resources/Images/Converters/Vector/Times/Formula.png new file mode 100644 index 0000000..d5ca378 Binary files /dev/null and b/BusinessSimulation/Resources/Images/Converters/Vector/Times/Formula.png differ diff --git a/BusinessSimulation/Resources/Images/Converters/Vector/Times/Formula.svg b/BusinessSimulation/Resources/Images/Converters/Vector/Times/Formula.svg new file mode 100644 index 0000000..33e634c --- /dev/null +++ b/BusinessSimulation/Resources/Images/Converters/Vector/Times/Formula.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Converters/Vector/Total/Formula.png b/BusinessSimulation/Resources/Images/Converters/Vector/Total/Formula.png new file mode 100644 index 0000000..a20f107 Binary files /dev/null and b/BusinessSimulation/Resources/Images/Converters/Vector/Total/Formula.png differ diff --git a/BusinessSimulation/Resources/Images/Converters/Vector/Total/Formula.svg b/BusinessSimulation/Resources/Images/Converters/Vector/Total/Formula.svg new file mode 100644 index 0000000..c9ef7d6 --- /dev/null +++ b/BusinessSimulation/Resources/Images/Converters/Vector/Total/Formula.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Examples/LotkaVolterraEquationsRevisited/TimePlot.svg b/BusinessSimulation/Resources/Images/Examples/LotkaVolterraEquationsRevisited/TimePlot.svg new file mode 100644 index 0000000..e68f6ec --- /dev/null +++ b/BusinessSimulation/Resources/Images/Examples/LotkaVolterraEquationsRevisited/TimePlot.svg @@ -0,0 +1,376 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Examples/LotkaVolterraSystems/Graph.svg b/BusinessSimulation/Resources/Images/Examples/LotkaVolterraSystems/Graph.svg new file mode 100644 index 0000000..35d51b8 --- /dev/null +++ b/BusinessSimulation/Resources/Images/Examples/LotkaVolterraSystems/Graph.svg @@ -0,0 +1,312 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Examples/LoveHateDynamics/Formula.svg b/BusinessSimulation/Resources/Images/Examples/LoveHateDynamics/Formula.svg new file mode 100644 index 0000000..3878533 --- /dev/null +++ b/BusinessSimulation/Resources/Images/Examples/LoveHateDynamics/Formula.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Examples/LoveHateDynamics/Formula2.svg b/BusinessSimulation/Resources/Images/Examples/LoveHateDynamics/Formula2.svg new file mode 100644 index 0000000..1d4dd92 --- /dev/null +++ b/BusinessSimulation/Resources/Images/Examples/LoveHateDynamics/Formula2.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Examples/SIR/Graph.svg b/BusinessSimulation/Resources/Images/Examples/SIR/Graph.svg new file mode 100644 index 0000000..95f53fc --- /dev/null +++ b/BusinessSimulation/Resources/Images/Examples/SIR/Graph.svg @@ -0,0 +1,403 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Examples/SimpleProductionChain/UsefulLifeDistributions.png b/BusinessSimulation/Resources/Images/Examples/SimpleProductionChain/UsefulLifeDistributions.png new file mode 100644 index 0000000..3f94b67 Binary files /dev/null and b/BusinessSimulation/Resources/Images/Examples/SimpleProductionChain/UsefulLifeDistributions.png differ diff --git a/BusinessSimulation/Resources/Images/Flows.png b/BusinessSimulation/Resources/Images/Flows.png new file mode 100644 index 0000000..228efb5 Binary files /dev/null and b/BusinessSimulation/Resources/Images/Flows.png differ diff --git a/BusinessSimulation/Resources/Images/Flows.svg b/BusinessSimulation/Resources/Images/Flows.svg new file mode 100644 index 0000000..43814cc --- /dev/null +++ b/BusinessSimulation/Resources/Images/Flows.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Flows/Interaction/BrokenTransition/Diagram.png b/BusinessSimulation/Resources/Images/Flows/Interaction/BrokenTransition/Diagram.png new file mode 100644 index 0000000..03f0120 Binary files /dev/null and b/BusinessSimulation/Resources/Images/Flows/Interaction/BrokenTransition/Diagram.png differ diff --git a/BusinessSimulation/Resources/Images/Flows/Interaction/BrokenTransitionPull/Diagram.png b/BusinessSimulation/Resources/Images/Flows/Interaction/BrokenTransitionPull/Diagram.png new file mode 100644 index 0000000..eba0839 Binary files /dev/null and b/BusinessSimulation/Resources/Images/Flows/Interaction/BrokenTransitionPull/Diagram.png differ diff --git a/BusinessSimulation/Resources/Images/Flows/Interaction/ComplexInteraction/Formula.png b/BusinessSimulation/Resources/Images/Flows/Interaction/ComplexInteraction/Formula.png new file mode 100644 index 0000000..d676185 Binary files /dev/null and b/BusinessSimulation/Resources/Images/Flows/Interaction/ComplexInteraction/Formula.png differ diff --git a/BusinessSimulation/Resources/Images/Flows/Interaction/ComplexInteraction/Formula.svg b/BusinessSimulation/Resources/Images/Flows/Interaction/ComplexInteraction/Formula.svg new file mode 100644 index 0000000..b58ed8c --- /dev/null +++ b/BusinessSimulation/Resources/Images/Flows/Interaction/ComplexInteraction/Formula.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Flows/Interaction/LinearInteraction/Formula.png b/BusinessSimulation/Resources/Images/Flows/Interaction/LinearInteraction/Formula.png new file mode 100644 index 0000000..2c2b2e8 Binary files /dev/null and b/BusinessSimulation/Resources/Images/Flows/Interaction/LinearInteraction/Formula.png differ diff --git a/BusinessSimulation/Resources/Images/Flows/Interaction/LinearInteraction/Formula.svg b/BusinessSimulation/Resources/Images/Flows/Interaction/LinearInteraction/Formula.svg new file mode 100644 index 0000000..4fadd4d --- /dev/null +++ b/BusinessSimulation/Resources/Images/Flows/Interaction/LinearInteraction/Formula.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Flows/Interaction/LotkaVolterra/Formula.png b/BusinessSimulation/Resources/Images/Flows/Interaction/LotkaVolterra/Formula.png new file mode 100644 index 0000000..bf232cb Binary files /dev/null and b/BusinessSimulation/Resources/Images/Flows/Interaction/LotkaVolterra/Formula.png differ diff --git a/BusinessSimulation/Resources/Images/Flows/Interaction/LotkaVolterra/Formula.svg b/BusinessSimulation/Resources/Images/Flows/Interaction/LotkaVolterra/Formula.svg new file mode 100644 index 0000000..1589297 --- /dev/null +++ b/BusinessSimulation/Resources/Images/Flows/Interaction/LotkaVolterra/Formula.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Flows/Interaction/NonlinearInteraction/Formula.png b/BusinessSimulation/Resources/Images/Flows/Interaction/NonlinearInteraction/Formula.png new file mode 100644 index 0000000..90f556c Binary files /dev/null and b/BusinessSimulation/Resources/Images/Flows/Interaction/NonlinearInteraction/Formula.png differ diff --git a/BusinessSimulation/Resources/Images/Flows/Interaction/NonlinearInteraction/Formula.svg b/BusinessSimulation/Resources/Images/Flows/Interaction/NonlinearInteraction/Formula.svg new file mode 100644 index 0000000..68a84fc --- /dev/null +++ b/BusinessSimulation/Resources/Images/Flows/Interaction/NonlinearInteraction/Formula.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Icons/World/World.png b/BusinessSimulation/Resources/Images/Icons/World/World.png new file mode 100644 index 0000000..3f937a6 Binary files /dev/null and b/BusinessSimulation/Resources/Images/Icons/World/World.png differ diff --git a/BusinessSimulation/Resources/Images/InformationSources.png b/BusinessSimulation/Resources/Images/InformationSources.png new file mode 100644 index 0000000..161069b Binary files /dev/null and b/BusinessSimulation/Resources/Images/InformationSources.png differ diff --git a/BusinessSimulation/Resources/Images/InformationSources.svg b/BusinessSimulation/Resources/Images/InformationSources.svg new file mode 100644 index 0000000..61e37c1 --- /dev/null +++ b/BusinessSimulation/Resources/Images/InformationSources.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/MoleculesOfStructure.png b/BusinessSimulation/Resources/Images/MoleculesOfStructure.png new file mode 100644 index 0000000..bf99a51 Binary files /dev/null and b/BusinessSimulation/Resources/Images/MoleculesOfStructure.png differ diff --git a/BusinessSimulation/Resources/Images/MoleculesOfStructure.svg b/BusinessSimulation/Resources/Images/MoleculesOfStructure.svg new file mode 100644 index 0000000..4a049e5 --- /dev/null +++ b/BusinessSimulation/Resources/Images/MoleculesOfStructure.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/MoleculesOfStructure/ActuatorIcon.png b/BusinessSimulation/Resources/Images/MoleculesOfStructure/ActuatorIcon.png new file mode 100644 index 0000000..f6fcb01 Binary files /dev/null and b/BusinessSimulation/Resources/Images/MoleculesOfStructure/ActuatorIcon.png differ diff --git a/BusinessSimulation/Resources/Images/MoleculesOfStructure/Actuators/Diffusion/Contact.png b/BusinessSimulation/Resources/Images/MoleculesOfStructure/Actuators/Diffusion/Contact.png new file mode 100644 index 0000000..535e1fe Binary files /dev/null and b/BusinessSimulation/Resources/Images/MoleculesOfStructure/Actuators/Diffusion/Contact.png differ diff --git a/BusinessSimulation/Resources/Images/MoleculesOfStructure/BlockIcon.png b/BusinessSimulation/Resources/Images/MoleculesOfStructure/BlockIcon.png new file mode 100644 index 0000000..5bbcfa1 Binary files /dev/null and b/BusinessSimulation/Resources/Images/MoleculesOfStructure/BlockIcon.png differ diff --git a/BusinessSimulation/Resources/Images/MoleculesOfStructure/IncubatorIcon.png b/BusinessSimulation/Resources/Images/MoleculesOfStructure/IncubatorIcon.png new file mode 100644 index 0000000..e65f20d Binary files /dev/null and b/BusinessSimulation/Resources/Images/MoleculesOfStructure/IncubatorIcon.png differ diff --git a/BusinessSimulation/Resources/Images/MoleculesOfStructure/InformationProcessing/TimeValueOfMoney/Formula.png b/BusinessSimulation/Resources/Images/MoleculesOfStructure/InformationProcessing/TimeValueOfMoney/Formula.png new file mode 100644 index 0000000..7f099be Binary files /dev/null and b/BusinessSimulation/Resources/Images/MoleculesOfStructure/InformationProcessing/TimeValueOfMoney/Formula.png differ diff --git a/BusinessSimulation/Resources/Images/MoleculesOfStructure/InformationProcessing/TimeValueOfMoney/Formula.svg b/BusinessSimulation/Resources/Images/MoleculesOfStructure/InformationProcessing/TimeValueOfMoney/Formula.svg new file mode 100644 index 0000000..348386a --- /dev/null +++ b/BusinessSimulation/Resources/Images/MoleculesOfStructure/InformationProcessing/TimeValueOfMoney/Formula.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/MoleculesOfStructure/TransceiverIcon.png b/BusinessSimulation/Resources/Images/MoleculesOfStructure/TransceiverIcon.png new file mode 100644 index 0000000..72b7d96 Binary files /dev/null and b/BusinessSimulation/Resources/Images/MoleculesOfStructure/TransceiverIcon.png differ diff --git a/BusinessSimulation/Resources/Images/SourcesOrSinks.png b/BusinessSimulation/Resources/Images/SourcesOrSinks.png new file mode 100644 index 0000000..c03515b Binary files /dev/null and b/BusinessSimulation/Resources/Images/SourcesOrSinks.png differ diff --git a/BusinessSimulation/Resources/Images/SourcesOrSinks.svg b/BusinessSimulation/Resources/Images/SourcesOrSinks.svg new file mode 100644 index 0000000..ca3b534 --- /dev/null +++ b/BusinessSimulation/Resources/Images/SourcesOrSinks.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/SourcesOrSinks/ExponentialDecay/FormulaHalfLife.png b/BusinessSimulation/Resources/Images/SourcesOrSinks/ExponentialDecay/FormulaHalfLife.png new file mode 100644 index 0000000..8c3412e Binary files /dev/null and b/BusinessSimulation/Resources/Images/SourcesOrSinks/ExponentialDecay/FormulaHalfLife.png differ diff --git a/BusinessSimulation/Resources/Images/SourcesOrSinks/ExponentialDecay/FormulaHalfLife.svg b/BusinessSimulation/Resources/Images/SourcesOrSinks/ExponentialDecay/FormulaHalfLife.svg new file mode 100644 index 0000000..4a47a09 --- /dev/null +++ b/BusinessSimulation/Resources/Images/SourcesOrSinks/ExponentialDecay/FormulaHalfLife.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/SourcesOrSinks/ExponentialDecay/FormulaRate.png b/BusinessSimulation/Resources/Images/SourcesOrSinks/ExponentialDecay/FormulaRate.png new file mode 100644 index 0000000..5867396 Binary files /dev/null and b/BusinessSimulation/Resources/Images/SourcesOrSinks/ExponentialDecay/FormulaRate.png differ diff --git a/BusinessSimulation/Resources/Images/SourcesOrSinks/ExponentialDecay/FormulaRate.svg b/BusinessSimulation/Resources/Images/SourcesOrSinks/ExponentialDecay/FormulaRate.svg new file mode 100644 index 0000000..7a93223 --- /dev/null +++ b/BusinessSimulation/Resources/Images/SourcesOrSinks/ExponentialDecay/FormulaRate.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/SourcesOrSinks/ExponentialDecay/FormulaResidenceTime.png b/BusinessSimulation/Resources/Images/SourcesOrSinks/ExponentialDecay/FormulaResidenceTime.png new file mode 100644 index 0000000..fd0d0d4 Binary files /dev/null and b/BusinessSimulation/Resources/Images/SourcesOrSinks/ExponentialDecay/FormulaResidenceTime.png differ diff --git a/BusinessSimulation/Resources/Images/SourcesOrSinks/ExponentialDecay/FormulaResidenceTime.svg b/BusinessSimulation/Resources/Images/SourcesOrSinks/ExponentialDecay/FormulaResidenceTime.svg new file mode 100644 index 0000000..fc429e6 --- /dev/null +++ b/BusinessSimulation/Resources/Images/SourcesOrSinks/ExponentialDecay/FormulaResidenceTime.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/SourcesOrSinks/LogisticGrowth/Formula.png b/BusinessSimulation/Resources/Images/SourcesOrSinks/LogisticGrowth/Formula.png new file mode 100644 index 0000000..3e61cd0 Binary files /dev/null and b/BusinessSimulation/Resources/Images/SourcesOrSinks/LogisticGrowth/Formula.png differ diff --git a/BusinessSimulation/Resources/Images/SourcesOrSinks/LogisticGrowth/Formula.svg b/BusinessSimulation/Resources/Images/SourcesOrSinks/LogisticGrowth/Formula.svg new file mode 100644 index 0000000..0d4ac39 --- /dev/null +++ b/BusinessSimulation/Resources/Images/SourcesOrSinks/LogisticGrowth/Formula.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/SourcesOrSinks/LogisticGrowth/Plot.png b/BusinessSimulation/Resources/Images/SourcesOrSinks/LogisticGrowth/Plot.png new file mode 100644 index 0000000..81df609 Binary files /dev/null and b/BusinessSimulation/Resources/Images/SourcesOrSinks/LogisticGrowth/Plot.png differ diff --git a/BusinessSimulation/Resources/Images/SourcesOrSinks/LogisticGrowth/Plot.svg b/BusinessSimulation/Resources/Images/SourcesOrSinks/LogisticGrowth/Plot.svg new file mode 100644 index 0000000..0fb2d3a --- /dev/null +++ b/BusinessSimulation/Resources/Images/SourcesOrSinks/LogisticGrowth/Plot.svg @@ -0,0 +1,284 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/Stocks.png b/BusinessSimulation/Resources/Images/Stocks.png new file mode 100644 index 0000000..fe31ab4 Binary files /dev/null and b/BusinessSimulation/Resources/Images/Stocks.png differ diff --git a/BusinessSimulation/Resources/Images/Stocks.svg b/BusinessSimulation/Resources/Images/Stocks.svg new file mode 100644 index 0000000..aaa58e7 --- /dev/null +++ b/BusinessSimulation/Resources/Images/Stocks.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Contact/BSL_Schriftzug.png b/BusinessSimulation/Resources/Images/UsersGuide/Contact/BSL_Schriftzug.png new file mode 100644 index 0000000..ef8e29f Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Contact/BSL_Schriftzug.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Contact/ContactInformation.png b/BusinessSimulation/Resources/Images/UsersGuide/Contact/ContactInformation.png new file mode 100644 index 0000000..7973654 Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Contact/ContactInformation.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Actuators.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Actuators.png new file mode 100644 index 0000000..f263f84 Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Actuators.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Actuators.svg b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Actuators.svg new file mode 100644 index 0000000..337e05b --- /dev/null +++ b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Actuators.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/BidirectionalFlow.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/BidirectionalFlow.png new file mode 100644 index 0000000..9bfc6ef Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/BidirectionalFlow.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Blocks.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Blocks.png new file mode 100644 index 0000000..99ab8e4 Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Blocks.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Blocks.svg b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Blocks.svg new file mode 100644 index 0000000..c07d3ea --- /dev/null +++ b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Blocks.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/CapacityRestrictedStock.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/CapacityRestrictedStock.png new file mode 100644 index 0000000..f1ff194 Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/CapacityRestrictedStock.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Cloud.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Cloud.png new file mode 100644 index 0000000..537133a Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Cloud.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Converters.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Converters.png new file mode 100644 index 0000000..baee00f Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Converters.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Converters.svg b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Converters.svg new file mode 100644 index 0000000..21f335a --- /dev/null +++ b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Converters.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Conveyor.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Conveyor.png new file mode 100644 index 0000000..e3b9862 Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Conveyor.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/DelayN.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/DelayN.png new file mode 100644 index 0000000..2036cd4 Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/DelayN.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/DiscreteDelay.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/DiscreteDelay.png new file mode 100644 index 0000000..f16cb49 Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/DiscreteDelay.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/DiscreteDelay.svg b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/DiscreteDelay.svg new file mode 100644 index 0000000..003efcb --- /dev/null +++ b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/DiscreteDelay.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Flows.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Flows.png new file mode 100644 index 0000000..cafd7ef Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Flows.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Flows.svg b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Flows.svg new file mode 100644 index 0000000..43814cc --- /dev/null +++ b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Flows.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Incubators.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Incubators.png new file mode 100644 index 0000000..5709b37 Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Incubators.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Incubators.svg b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Incubators.svg new file mode 100644 index 0000000..f6d81a4 --- /dev/null +++ b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Incubators.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/InformationLevel.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/InformationLevel.png new file mode 100644 index 0000000..b72da9d Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/InformationLevel.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/InformationProcessing.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/InformationProcessing.png new file mode 100644 index 0000000..e9b3417 Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/InformationProcessing.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/InformationProcessing.svg b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/InformationProcessing.svg new file mode 100644 index 0000000..cfa45ec --- /dev/null +++ b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/InformationProcessing.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/InformationSources.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/InformationSources.png new file mode 100644 index 0000000..f1b8a79 Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/InformationSources.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/InformationSources.svg b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/InformationSources.svg new file mode 100644 index 0000000..61e37c1 --- /dev/null +++ b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/InformationSources.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Interaction.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Interaction.png new file mode 100644 index 0000000..dab49ac Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Interaction.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Logical.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Logical.png new file mode 100644 index 0000000..49a5e95 Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Logical.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Logical.svg b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Logical.svg new file mode 100644 index 0000000..b8f096c --- /dev/null +++ b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Logical.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Lookup.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Lookup.png new file mode 100644 index 0000000..4f98fa3 Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Lookup.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Lookup.svg b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Lookup.svg new file mode 100644 index 0000000..19e52fd --- /dev/null +++ b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Lookup.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/MaterialStock.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/MaterialStock.png new file mode 100644 index 0000000..9fa9ae7 Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/MaterialStock.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/MoleculesOfStructure.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/MoleculesOfStructure.png new file mode 100644 index 0000000..490afe5 Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/MoleculesOfStructure.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/MoleculesOfStructure.svg b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/MoleculesOfStructure.svg new file mode 100644 index 0000000..4a049e5 --- /dev/null +++ b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/MoleculesOfStructure.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Oven.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Oven.png new file mode 100644 index 0000000..d7a7b4d Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Oven.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Policy.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Policy.png new file mode 100644 index 0000000..bb546e1 Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Policy.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Policy.svg b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Policy.svg new file mode 100644 index 0000000..cc839a9 --- /dev/null +++ b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Policy.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/PureDelay.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/PureDelay.png new file mode 100644 index 0000000..3a25b4c Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/PureDelay.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/SimpleConveyor.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/SimpleConveyor.png new file mode 100644 index 0000000..583eb43 Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/SimpleConveyor.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Sink.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Sink.png new file mode 100644 index 0000000..3601feb Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Sink.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Source.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Source.png new file mode 100644 index 0000000..9b9cb1b Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Source.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/SourceOrSink.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/SourceOrSink.png new file mode 100644 index 0000000..58f24db Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/SourceOrSink.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/SourcesOrSinks.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/SourcesOrSinks.png new file mode 100644 index 0000000..b3812eb Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/SourcesOrSinks.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/SourcesOrSinks.svg b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/SourcesOrSinks.svg new file mode 100644 index 0000000..ca3b534 --- /dev/null +++ b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/SourcesOrSinks.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Stocks.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Stocks.png new file mode 100644 index 0000000..0358086 Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Stocks.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Stocks.svg b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Stocks.svg new file mode 100644 index 0000000..aaa58e7 --- /dev/null +++ b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Stocks.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Transceivers.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Transceivers.png new file mode 100644 index 0000000..f4e22d5 Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Transceivers.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Transceivers.svg b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Transceivers.svg new file mode 100644 index 0000000..0d7555f --- /dev/null +++ b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Transceivers.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/UnidirectionalFlow.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/UnidirectionalFlow.png new file mode 100644 index 0000000..df3bb14 Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/UnidirectionalFlow.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Vector.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Vector.png new file mode 100644 index 0000000..0de9cfd Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Vector.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Vector.svg b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Vector.svg new file mode 100644 index 0000000..115b160 --- /dev/null +++ b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/ElementaryBuildingBlocks/Vector.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/StrategicBusinessSimulation/ContinuousView.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/StrategicBusinessSimulation/ContinuousView.png new file mode 100644 index 0000000..627f8c8 Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/StrategicBusinessSimulation/ContinuousView.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/StrategicBusinessSimulation/SettingTheRate.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/StrategicBusinessSimulation/SettingTheRate.png new file mode 100644 index 0000000..d757adf Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/StrategicBusinessSimulation/SettingTheRate.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/StrategicBusinessSimulation/SimpleProductionProcess.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/StrategicBusinessSimulation/SimpleProductionProcess.png new file mode 100644 index 0000000..a8b84bc Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/StrategicBusinessSimulation/SimpleProductionProcess.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/UnitsInBusinessSimulations/CustomConversions_Amount.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/UnitsInBusinessSimulations/CustomConversions_Amount.png new file mode 100644 index 0000000..155edcf Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/UnitsInBusinessSimulations/CustomConversions_Amount.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/UnitsInBusinessSimulations/CustomConversions_Rate.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/UnitsInBusinessSimulations/CustomConversions_Rate.png new file mode 100644 index 0000000..10f3e98 Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/UnitsInBusinessSimulations/CustomConversions_Rate.png differ diff --git a/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/UnitsInBusinessSimulations/CustomConversions_Time.png b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/UnitsInBusinessSimulations/CustomConversions_Time.png new file mode 100644 index 0000000..8c250d1 Binary files /dev/null and b/BusinessSimulation/Resources/Images/UsersGuide/Tutorial/UnitsInBusinessSimulations/CustomConversions_Time.png differ diff --git a/BusinessSimulation/Resources/LICENSE.txt b/BusinessSimulation/Resources/LICENSE.txt new file mode 100644 index 0000000..c29ce2f --- /dev/null +++ b/BusinessSimulation/Resources/LICENSE.txt @@ -0,0 +1,287 @@ + EUROPEAN UNION PUBLIC LICENCE v. 1.2 + EUPL © the European Union 2007, 2016 + +This European Union Public Licence (the ‘EUPL’) applies to the Work (as defined +below) which is provided under the terms of this Licence. Any use of the Work, +other than as authorised under this Licence is prohibited (to the extent such +use is covered by a right of the copyright holder of the Work). + +The Work is provided under the terms of this Licence when the Licensor (as +defined below) has placed the following notice immediately following the +copyright notice for the Work: + + Licensed under the EUPL + +or has expressed by any other means his willingness to license under the EUPL. + +1. Definitions + +In this Licence, the following terms have the following meaning: + +- ‘The Licence’: this Licence. + +- ‘The Original Work’: the work or software distributed or communicated by the + Licensor under this Licence, available as Source Code and also as Executable + Code as the case may be. + +- ‘Derivative Works’: the works or software that could be created by the + Licensee, based upon the Original Work or modifications thereof. This Licence + does not define the extent of modification or dependence on the Original Work + required in order to classify a work as a Derivative Work; this extent is + determined by copyright law applicable in the country mentioned in Article 15. + +- ‘The Work’: the Original Work or its Derivative Works. + +- ‘The Source Code’: the human-readable form of the Work which is the most + convenient for people to study and modify. + +- ‘The Executable Code’: any code which has generally been compiled and which is + meant to be interpreted by a computer as a program. + +- ‘The Licensor’: the natural or legal person that distributes or communicates + the Work under the Licence. + +- ‘Contributor(s)’: any natural or legal person who modifies the Work under the + Licence, or otherwise contributes to the creation of a Derivative Work. + +- ‘The Licensee’ or ‘You’: any natural or legal person who makes any usage of + the Work under the terms of the Licence. + +- ‘Distribution’ or ‘Communication’: any act of selling, giving, lending, + renting, distributing, communicating, transmitting, or otherwise making + available, online or offline, copies of the Work or providing access to its + essential functionalities at the disposal of any other natural or legal + person. + +2. Scope of the rights granted by the Licence + +The Licensor hereby grants You a worldwide, royalty-free, non-exclusive, +sublicensable licence to do the following, for the duration of copyright vested +in the Original Work: + +- use the Work in any circumstance and for all usage, +- reproduce the Work, +- modify the Work, and make Derivative Works based upon the Work, +- communicate to the public, including the right to make available or display + the Work or copies thereof to the public and perform publicly, as the case may + be, the Work, +- distribute the Work or copies thereof, +- lend and rent the Work or copies thereof, +- sublicense rights in the Work or copies thereof. + +Those rights can be exercised on any media, supports and formats, whether now +known or later invented, as far as the applicable law permits so. + +In the countries where moral rights apply, the Licensor waives his right to +exercise his moral right to the extent allowed by law in order to make effective +the licence of the economic rights here above listed. + +The Licensor grants to the Licensee royalty-free, non-exclusive usage rights to +any patents held by the Licensor, to the extent necessary to make use of the +rights granted on the Work under this Licence. + +3. Communication of the Source Code + +The Licensor may provide the Work either in its Source Code form, or as +Executable Code. If the Work is provided as Executable Code, the Licensor +provides in addition a machine-readable copy of the Source Code of the Work +along with each copy of the Work that the Licensor distributes or indicates, in +a notice following the copyright notice attached to the Work, a repository where +the Source Code is easily and freely accessible for as long as the Licensor +continues to distribute or communicate the Work. + +4. Limitations on copyright + +Nothing in this Licence is intended to deprive the Licensee of the benefits from +any exception or limitation to the exclusive rights of the rights owners in the +Work, of the exhaustion of those rights or of other applicable limitations +thereto. + +5. Obligations of the Licensee + +The grant of the rights mentioned above is subject to some restrictions and +obligations imposed on the Licensee. Those obligations are the following: + +Attribution right: The Licensee shall keep intact all copyright, patent or +trademarks notices and all notices that refer to the Licence and to the +disclaimer of warranties. The Licensee must include a copy of such notices and a +copy of the Licence with every copy of the Work he/she distributes or +communicates. The Licensee must cause any Derivative Work to carry prominent +notices stating that the Work has been modified and the date of modification. + +Copyleft clause: If the Licensee distributes or communicates copies of the +Original Works or Derivative Works, this Distribution or Communication will be +done under the terms of this Licence or of a later version of this Licence +unless the Original Work is expressly distributed only under this version of the +Licence — for example by communicating ‘EUPL v. 1.2 only’. The Licensee +(becoming Licensor) cannot offer or impose any additional terms or conditions on +the Work or Derivative Work that alter or restrict the terms of the Licence. + +Compatibility clause: If the Licensee Distributes or Communicates Derivative +Works or copies thereof based upon both the Work and another work licensed under +a Compatible Licence, this Distribution or Communication can be done under the +terms of this Compatible Licence. For the sake of this clause, ‘Compatible +Licence’ refers to the licences listed in the appendix attached to this Licence. +Should the Licensee's obligations under the Compatible Licence conflict with +his/her obligations under this Licence, the obligations of the Compatible +Licence shall prevail. + +Provision of Source Code: When distributing or communicating copies of the Work, +the Licensee will provide a machine-readable copy of the Source Code or indicate +a repository where this Source will be easily and freely available for as long +as the Licensee continues to distribute or communicate the Work. + +Legal Protection: This Licence does not grant permission to use the trade names, +trademarks, service marks, or names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the copyright notice. + +6. Chain of Authorship + +The original Licensor warrants that the copyright in the Original Work granted +hereunder is owned by him/her or licensed to him/her and that he/she has the +power and authority to grant the Licence. + +Each Contributor warrants that the copyright in the modifications he/she brings +to the Work are owned by him/her or licensed to him/her and that he/she has the +power and authority to grant the Licence. + +Each time You accept the Licence, the original Licensor and subsequent +Contributors grant You a licence to their contributions to the Work, under the +terms of this Licence. + +7. Disclaimer of Warranty + +The Work is a work in progress, which is continuously improved by numerous +Contributors. It is not a finished work and may therefore contain defects or +‘bugs’ inherent to this type of development. + +For the above reason, the Work is provided under the Licence on an ‘as is’ basis +and without warranties of any kind concerning the Work, including without +limitation merchantability, fitness for a particular purpose, absence of defects +or errors, accuracy, non-infringement of intellectual property rights other than +copyright as stated in Article 6 of this Licence. + +This disclaimer of warranty is an essential part of the Licence and a condition +for the grant of any rights to the Work. + +8. Disclaimer of Liability + +Except in the cases of wilful misconduct or damages directly caused to natural +persons, the Licensor will in no event be liable for any direct or indirect, +material or moral, damages of any kind, arising out of the Licence or of the use +of the Work, including without limitation, damages for loss of goodwill, work +stoppage, computer failure or malfunction, loss of data or any commercial +damage, even if the Licensor has been advised of the possibility of such damage. +However, the Licensor will be liable under statutory product liability laws as +far such laws apply to the Work. + +9. Additional agreements + +While distributing the Work, You may choose to conclude an additional agreement, +defining obligations or services consistent with this Licence. However, if +accepting obligations, You may act only on your own behalf and on your sole +responsibility, not on behalf of the original Licensor or any other Contributor, +and only if You agree to indemnify, defend, and hold each Contributor harmless +for any liability incurred by, or claims asserted against such Contributor by +the fact You have accepted any warranty or additional liability. + +10. Acceptance of the Licence + +The provisions of this Licence can be accepted by clicking on an icon ‘I agree’ +placed under the bottom of a window displaying the text of this Licence or by +affirming consent in any other similar way, in accordance with the rules of +applicable law. Clicking on that icon indicates your clear and irrevocable +acceptance of this Licence and all of its terms and conditions. + +Similarly, you irrevocably accept this Licence and all of its terms and +conditions by exercising any rights granted to You by Article 2 of this Licence, +such as the use of the Work, the creation by You of a Derivative Work or the +Distribution or Communication by You of the Work or copies thereof. + +11. Information to the public + +In case of any Distribution or Communication of the Work by means of electronic +communication by You (for example, by offering to download the Work from a +remote location) the distribution channel or media (for example, a website) must +at least provide to the public the information requested by the applicable law +regarding the Licensor, the Licence and the way it may be accessible, concluded, +stored and reproduced by the Licensee. + +12. Termination of the Licence + +The Licence and the rights granted hereunder will terminate automatically upon +any breach by the Licensee of the terms of the Licence. + +Such a termination will not terminate the licences of any person who has +received the Work from the Licensee under the Licence, provided such persons +remain in full compliance with the Licence. + +13. Miscellaneous + +Without prejudice of Article 9 above, the Licence represents the complete +agreement between the Parties as to the Work. + +If any provision of the Licence is invalid or unenforceable under applicable +law, this will not affect the validity or enforceability of the Licence as a +whole. Such provision will be construed or reformed so as necessary to make it +valid and enforceable. + +The European Commission may publish other linguistic versions or new versions of +this Licence or updated versions of the Appendix, so far this is required and +reasonable, without reducing the scope of the rights granted by the Licence. New +versions of the Licence will be published with a unique version number. + +All linguistic versions of this Licence, approved by the European Commission, +have identical value. Parties can take advantage of the linguistic version of +their choice. + +14. Jurisdiction + +Without prejudice to specific agreement between parties, + +- any litigation resulting from the interpretation of this License, arising + between the European Union institutions, bodies, offices or agencies, as a + Licensor, and any Licensee, will be subject to the jurisdiction of the Court + of Justice of the European Union, as laid down in article 272 of the Treaty on + the Functioning of the European Union, + +- any litigation arising between other parties and resulting from the + interpretation of this License, will be subject to the exclusive jurisdiction + of the competent court where the Licensor resides or conducts its primary + business. + +15. Applicable Law + +Without prejudice to specific agreement between parties, + +- this Licence shall be governed by the law of the European Union Member State + where the Licensor has his seat, resides or has his registered office, + +- this licence shall be governed by Belgian law if the Licensor has no seat, + residence or registered office inside a European Union Member State. + +Appendix + +‘Compatible Licences’ according to Article 5 EUPL are: + +- GNU General Public License (GPL) v. 2, v. 3 +- GNU Affero General Public License (AGPL) v. 3 +- Open Software License (OSL) v. 2.1, v. 3.0 +- Eclipse Public License (EPL) v. 1.0 +- CeCILL v. 2.0, v. 2.1 +- Mozilla Public Licence (MPL) v. 2 +- GNU Lesser General Public Licence (LGPL) v. 2.1, v. 3 +- Creative Commons Attribution-ShareAlike v. 3.0 Unported (CC BY-SA 3.0) for + works other than software +- European Union Public Licence (EUPL) v. 1.1, v. 1.2 +- Québec Free and Open-Source Licence — Reciprocity (LiLiQ-R) or Strong + Reciprocity (LiLiQ-R+). + +The European Commission may update this Appendix to later versions of the above +licences without producing a new version of the EUPL, as long as they provide +the rights granted in Article 2 of this Licence and protect the covered Source +Code from exclusive appropriation. + +All other changes or additions to this Appendix require the production of a new +EUPL version. \ No newline at end of file diff --git a/BusinessSimulation/Resources/README.txt b/BusinessSimulation/Resources/README.txt new file mode 100644 index 0000000..918a077 --- /dev/null +++ b/BusinessSimulation/Resources/README.txt @@ -0,0 +1,6 @@ +Copyright © 2020 Guido Wolf Reichert +Licensed under the EUPL-1.2 or later + +You may not use this work except in compliance with the Licence. You may obtain a copy of the Licence at: https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + +Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either expressed or implied. See the Licence for the specific langauge governing permissions and limitations under the Licence. \ No newline at end of file diff --git a/BusinessSimulation/Resources/SampleData.txt b/BusinessSimulation/Resources/SampleData.txt new file mode 100644 index 0000000..d2393bd --- /dev/null +++ b/BusinessSimulation/Resources/SampleData.txt @@ -0,0 +1,96 @@ +#1 +double germanyPopulation(94,2) + 4.417632e8 6.718e7 + 4.732992e8 6.7849e7 + 5.048352e8 6.758e7 + 5.364576e8 6.7155e7 + 5.679936e8 6.4565e7 + 5.995296e8 6.03247e7 + 6.310656e8 6.2126e7 + 6.62688e8 6.06258e7 + 6.94224e8 6.11854e7 + 7.2576e8 6.15773e7 + 7.57296e8 6.19524e7 + 7.889184e8 6.3363e7 + 8.204544e8 6.28659e7 + 8.519904e8 6.32523e7 + 8.835264e8 6.439e7 + 9.151488e8 6.474e7 + 9.466848e8 6.53e7 + 9.782208e8 6.542e7 + 1.0097568e9 6.572e7 + 1.0413792e9 6.60316e7 + 1.0729152e9 6.641e7 + 1.1044512e9 6.687e7 + 1.1359872e9 6.735e7 + 1.1676096e9 6.783e7 + 1.1991456e9 6.8072e7 + 1.2306816e9 6.96225e7 + 1.29384e9 7.19167e7 + 1.5146784e9 6.7365e7 + 1.5463008e9 6.808e7 + 1.5778368e9 6.9966243e7 + 1.6093728e9 7.0299358e7 + 1.6409088e9 7.0619499e7 + 1.6725312e9 7.0929259e7 + 1.7040672e9 7.1233131e7 + 1.7356032e9 7.1537537e7 + 1.7671392e9 7.185098e7 + 1.7987616e9 7.2183916e7 + 1.8302976e9 7.2548042e7 + 1.8618336e9 7.2955244e7 + 1.8933696e9 7.3414427e7 + 1.924992e9 7.3928048e7 + 1.956528e9 7.4489142e7 + 1.988064e9 7.5080047e7 + 2.0196e9 7.5676011e7 + 2.0512224e9 7.6255926e7 + 2.0827584e9 7.6816337e7 + 2.1142944e9 7.7352662e7 + 2.1458304e9 7.7841435e7 + 2.1774528e9 7.8254626e7 + 2.2089888e9 7.8572984e7 + 2.2405248e9 7.8786608e7 + 2.2720608e9 7.8901707e7 + 2.3036832e9 7.8936165e7 + 2.3352192e9 7.891722e7 + 2.3667552e9 7.8866498e7 + 2.3982912e9 7.8794496e7 + 2.4299136e9 7.8701801e7 + 2.4614496e9 7.8589311e7 + 2.4929856e9 7.8454848e7 + 2.5245216e9 7.830065e7 + 2.556144e9 7.8126104e7 + 2.58768e9 7.7944848e7 + 2.619216e9 7.779008e7 + 2.650752e9 7.7704336e7 + 2.6823744e9 7.7717431e7 + 2.7139104e9 7.78375e7 + 2.7454464e9 7.8054086e7 + 2.7769824e9 7.8354017e7 + 2.8086048e9 7.871561e7 + 2.8401408e9 7.9118326e7 + 2.8716768e9 7.9564454e7 + 2.9032128e9 8.0046157e7 + 2.9348352e9 8.0520088e7 + 2.9663712e9 8.0931041e7 + 2.9979072e9 8.1240604e7 + 3.0294432e9 8.1426337e7 + 3.0610656e9 8.1499866e7 + 3.0926016e9 8.1499232e7 + 3.1241376e9 8.1481612e7 + 3.1556736e9 8.1487757e7 + 3.187296e9 8.1535848e7 + 3.218832e9 8.1611868e7 + 3.250368e9 8.1686495e7 + 3.281904e9 8.1715659e7 + 3.3135264e9 8.1671234e7 + 3.3450624e9 8.1540353e7 + 3.3765984e9 8.1344457e7 + 3.4081344e9 8.1130944e7 + 3.4397568e9 8.0965612e7 + 3.4712928e9 8.0894785e7 + 3.5028288e9 8.093398e7 + 3.5343648e9 8.1066228e7 + 3.5659872e9 8.1265139e7 + 3.5975232e9 8.148966e7 diff --git a/BusinessSimulation/Resources/SampleTable1D.txt b/BusinessSimulation/Resources/SampleTable1D.txt new file mode 100644 index 0000000..2f430b9 --- /dev/null +++ b/BusinessSimulation/Resources/SampleTable1D.txt @@ -0,0 +1,163 @@ +#1 +double var1(161,2) + 0. 0. + 0.0625 0.00390625 + 0.125 0.015625 + 0.1875 0.03515625 + 0.25 0.0625 + 0.3125 0.09765625 + 0.375 0.140625 + 0.4375 0.19140625 + 0.5 0.25 + 0.5625 0.31640625 + 0.625 0.390625 + 0.6875 0.47265625 + 0.75 0.5625 + 0.8125 0.66015625 + 0.875 0.765625 + 0.9375 0.87890625 + 1. 1. + 1.0625 1.12890625 + 1.125 1.265625 + 1.1875 1.41015625 + 1.25 1.5625 + 1.3125 1.72265625 + 1.375 1.890625 + 1.4375 2.06640625 + 1.5 2.25 + 1.5625 2.44140625 + 1.625 2.640625 + 1.6875 2.84765625 + 1.75 3.0625 + 1.8125 3.28515625 + 1.875 3.515625 + 1.9375 3.75390625 + 2. 4. + 2.0625 4.25390625 + 2.125 4.515625 + 2.1875 4.78515625 + 2.25 5.0625 + 2.3125 5.34765625 + 2.375 5.640625 + 2.4375 5.94140625 + 2.5 6.25 + 2.5625 6.56640625 + 2.625 6.890625 + 2.6875 7.22265625 + 2.75 7.5625 + 2.8125 7.91015625 + 2.875 8.265625 + 2.9375 8.62890625 + 3. 9. + 3.0625 9.37890625 + 3.125 9.765625 + 3.1875 10.16015625 + 3.25 10.5625 + 3.3125 10.97265625 + 3.375 11.390625 + 3.4375 11.81640625 + 3.5 12.25 + 3.5625 12.69140625 + 3.625 13.140625 + 3.6875 13.59765625 + 3.75 14.0625 + 3.8125 14.53515625 + 3.875 15.015625 + 3.9375 15.50390625 + 4. 16. + 4.0625 16.50390625 + 4.125 17.015625 + 4.1875 17.53515625 + 4.25 18.0625 + 4.3125 18.59765625 + 4.375 19.140625 + 4.4375 19.69140625 + 4.5 20.25 + 4.5625 20.81640625 + 4.625 21.390625 + 4.6875 21.97265625 + 4.75 22.5625 + 4.8125 23.16015625 + 4.875 23.765625 + 4.9375 24.37890625 + 5. 25. + 5.0625 25.62890625 + 5.125 26.265625 + 5.1875 26.91015625 + 5.25 27.5625 + 5.3125 28.22265625 + 5.375 28.890625 + 5.4375 29.56640625 + 5.5 30.25 + 5.5625 30.94140625 + 5.625 31.640625 + 5.6875 32.34765625 + 5.75 33.0625 + 5.8125 33.78515625 + 5.875 34.515625 + 5.9375 35.25390625 + 6. 36. + 6.0625 36.75390625 + 6.125 37.515625 + 6.1875 38.28515625 + 6.25 39.0625 + 6.3125 39.84765625 + 6.375 40.640625 + 6.4375 41.44140625 + 6.5 42.25 + 6.5625 43.06640625 + 6.625 43.890625 + 6.6875 44.72265625 + 6.75 45.5625 + 6.8125 46.41015625 + 6.875 47.265625 + 6.9375 48.12890625 + 7. 49. + 7.0625 49.87890625 + 7.125 50.765625 + 7.1875 51.66015625 + 7.25 52.5625 + 7.3125 53.47265625 + 7.375 54.390625 + 7.4375 55.31640625 + 7.5 56.25 + 7.5625 57.19140625 + 7.625 58.140625 + 7.6875 59.09765625 + 7.75 60.0625 + 7.8125 61.03515625 + 7.875 62.015625 + 7.9375 63.00390625 + 8. 64. + 8.0625 65.00390625 + 8.125 66.015625 + 8.1875 67.03515625 + 8.25 68.0625 + 8.3125 69.09765625 + 8.375 70.140625 + 8.4375 71.19140625 + 8.5 72.25 + 8.5625 73.31640625 + 8.625 74.390625 + 8.6875 75.47265625 + 8.75 76.5625 + 8.8125 77.66015625 + 8.875 78.765625 + 8.9375 79.87890625 + 9. 81. + 9.0625 82.12890625 + 9.125 83.265625 + 9.1875 84.41015625 + 9.25 85.5625 + 9.3125 86.72265625 + 9.375 87.890625 + 9.4375 89.06640625 + 9.5 90.25 + 9.5625 91.44140625 + 9.625 92.640625 + 9.6875 93.84765625 + 9.75 95.0625 + 9.8125 96.28515625 + 9.875 97.515625 + 9.9375 98.75390625 + 10. 100. diff --git a/BusinessSimulation/Resources/SampleTable1DVector.txt b/BusinessSimulation/Resources/SampleTable1DVector.txt new file mode 100644 index 0000000..04f0f13 --- /dev/null +++ b/BusinessSimulation/Resources/SampleTable1DVector.txt @@ -0,0 +1,163 @@ +#1 +double var1(161,4) + 0. 0. 0. 0. + 0.0625 0.00390625 0.000244140625 0.0000152587890625 + 0.125 0.015625 0.001953125 0.000244140625 + 0.1875 0.03515625 0.006591796875 0.0012359619140625 + 0.25 0.0625 0.015625 0.00390625 + 0.3125 0.09765625 0.030517578125 0.0095367431640625 + 0.375 0.140625 0.052734375 0.019775390625 + 0.4375 0.19140625 0.083740234375 0.0366363525390625 + 0.5 0.25 0.125 0.0625 + 0.5625 0.31640625 0.177978515625 0.1001129150390625 + 0.625 0.390625 0.244140625 0.152587890625 + 0.6875 0.47265625 0.324951171875 0.2234039306640625 + 0.75 0.5625 0.421875 0.31640625 + 0.8125 0.66015625 0.536376953125 0.4358062744140625 + 0.875 0.765625 0.669921875 0.586181640625 + 0.9375 0.87890625 0.823974609375 0.7724761962890625 + 1. 1. 1. 1. + 1.0625 1.12890625 1.199462890625 1.2744293212890625 + 1.125 1.265625 1.423828125 1.601806640625 + 1.1875 1.41015625 1.674560546875 1.9885406494140625 + 1.25 1.5625 1.953125 2.44140625 + 1.3125 1.72265625 2.260986328125 2.9675445556640625 + 1.375 1.890625 2.599609375 3.574462890625 + 1.4375 2.06640625 2.970458984375 4.2700347900390625 + 1.5 2.25 3.375 5.0625 + 1.5625 2.44140625 3.814697265625 5.9604644775390625 + 1.625 2.640625 4.291015625 6.972900390625 + 1.6875 2.84765625 4.805419921875 8.109146118164062 + 1.75 3.0625 5.359375 9.37890625 + 1.8125 3.28515625 5.954345703125 10.792251586914062 + 1.875 3.515625 6.591796875 12.359619140625 + 1.9375 3.75390625 7.273193359375 14.091812133789062 + 2. 4. 8. 16. + 2.0625 4.25390625 8.773681640625 18.095718383789062 + 2.125 4.515625 9.595703125 20.390869140625 + 2.1875 4.78515625 10.467529296875 22.897720336914062 + 2.25 5.0625 11.390625 25.62890625 + 2.3125 5.34765625 12.366455078125 28.597427368164062 + 2.375 5.640625 13.396484375 31.816650390625 + 2.4375 5.94140625 14.482177734375 35.30030822753906 + 2.5 6.25 15.625 39.0625 + 2.5625 6.56640625 16.826416015625 43.11769104003906 + 2.625 6.890625 18.087890625 47.480712890625 + 2.6875 7.22265625 19.410888671875 52.16676330566406 + 2.75 7.5625 20.796875 57.19140625 + 2.8125 7.91015625 22.247314453125 62.57057189941406 + 2.875 8.265625 23.763671875 68.320556640625 + 2.9375 8.62890625 25.347412109375 74.45802307128906 + 3. 9. 27. 81. + 3.0625 9.37890625 28.722900390625 87.96388244628906 + 3.125 9.765625 30.517578125 95.367431640625 + 3.1875 10.16015625 32.385498046875 103.22877502441406 + 3.25 10.5625 34.328125 111.56640625 + 3.3125 10.97265625 36.346923828125 120.39918518066406 + 3.375 11.390625 38.443359375 129.746337890625 + 3.4375 11.81640625 40.618896484375 139.62745666503906 + 3.5 12.25 42.875 150.0625 + 3.5625 12.69140625 45.213134765625 161.07179260253906 + 3.625 13.140625 47.634765625 172.676025390625 + 3.6875 13.59765625 50.141357421875 184.89625549316406 + 3.75 14.0625 52.734375 197.75390625 + 3.8125 14.53515625 55.415283203125 211.27076721191406 + 3.875 15.015625 58.185546875 225.468994140625 + 3.9375 15.50390625 61.046630859375 240.37110900878906 + 4. 16. 64. 256. + 4.0625 16.50390625 67.047119140625 272.37892150878906 + 4.125 17.015625 70.189453125 289.531494140625 + 4.1875 17.53515625 73.428466796875 307.48170471191406 + 4.25 18.0625 76.765625 326.25390625 + 4.3125 18.59765625 80.202392578125 345.87281799316406 + 4.375 19.140625 83.740234375 366.363525390625 + 4.4375 19.69140625 87.380615234375 387.75148010253906 + 4.5 20.25 91.125 410.0625 + 4.5625 20.81640625 94.974853515625 433.32276916503906 + 4.625 21.390625 98.931640625 457.558837890625 + 4.6875 21.97265625 102.996826171875 482.79762268066406 + 4.75 22.5625 107.171875 509.06640625 + 4.8125 23.16015625 111.458251953125 536.3928375244141 + 4.875 23.765625 115.857421875 564.804931640625 + 4.9375 24.37890625 120.370849609375 594.3310699462891 + 5. 25. 125. 625. + 5.0625 25.62890625 129.746337890625 656.8408355712891 + 5.125 26.265625 134.611328125 689.883056640625 + 5.1875 26.91015625 139.596435546875 724.1565093994141 + 5.25 27.5625 144.703125 759.69140625 + 5.3125 28.22265625 149.932861328125 796.5183258056641 + 5.375 28.890625 155.287109375 834.668212890625 + 5.4375 29.56640625 160.767333984375 874.1723785400391 + 5.5 30.25 166.375 915.0625 + 5.5625 30.94140625 172.111572265625 957.3706207275391 + 5.625 31.640625 177.978515625 1001.129150390625 + 5.6875 32.34765625 183.977294921875 1046.370864868164 + 5.75 33.0625 190.109375 1093.12890625 + 5.8125 33.78515625 196.376220703125 1141.436782836914 + 5.875 34.515625 202.779296875 1191.328369140625 + 5.9375 35.25390625 209.320068359375 1242.837905883789 + 6. 36. 216. 1296. + 6.0625 36.75390625 222.820556640625 1350.849624633789 + 6.125 37.515625 229.783203125 1407.422119140625 + 6.1875 38.28515625 236.889404296875 1465.753189086914 + 6.25 39.0625 244.140625 1525.87890625 + 6.3125 39.84765625 251.538330078125 1587.835708618164 + 6.375 40.640625 259.083984375 1651.660400390625 + 6.4375 41.44140625 266.779052734375 1717.390151977539 + 6.5 42.25 274.625 1785.0625 + 6.5625 43.06640625 282.623291015625 1854.715347290039 + 6.625 43.890625 290.775390625 1926.386962890625 + 6.6875 44.72265625 299.082763671875 2000.115982055664 + 6.75 45.5625 307.546875 2075.94140625 + 6.8125 46.41015625 316.169189453125 2153.902603149414 + 6.875 47.265625 324.951171875 2234.039306640625 + 6.9375 48.12890625 333.894287109375 2316.391616821289 + 7. 49. 343. 2401. + 7.0625 49.87890625 352.269775390625 2487.905288696289 + 7.125 50.765625 361.705078125 2577.148681640625 + 7.1875 51.66015625 371.307373046875 2668.771743774414 + 7.25 52.5625 381.078125 2762.81640625 + 7.3125 53.47265625 391.018798828125 2859.324966430664 + 7.375 54.390625 401.130859375 2958.340087890625 + 7.4375 55.31640625 411.415771484375 3059.904800415039 + 7.5 56.25 421.875 3164.0625 + 7.5625 57.19140625 432.510009765625 3270.856948852539 + 7.625 58.140625 443.322265625 3380.332275390625 + 7.6875 59.09765625 454.313232421875 3492.532974243164 + 7.75 60.0625 465.484375 3607.50390625 + 7.8125 61.03515625 476.837158203125 3725.290298461914 + 7.875 62.015625 488.373046875 3845.937744140625 + 7.9375 63.00390625 500.093505859375 3969.492202758789 + 8. 64. 512. 4096. + 8.0625 65.00390625 524.093994140625 4225.507827758789 + 8.125 66.015625 536.376953125 4358.062744140625 + 8.1875 67.03515625 548.850341796875 4493.712173461914 + 8.25 68.0625 561.515625 4632.50390625 + 8.3125 69.09765625 574.374267578125 4774.486099243164 + 8.375 70.140625 587.427734375 4919.707275390625 + 8.4375 71.19140625 600.677490234375 5068.216323852539 + 8.5 72.25 614.125 5220.0625 + 8.5625 73.31640625 627.771728515625 5375.295425415039 + 8.625 74.390625 641.619140625 5533.965087890625 + 8.6875 75.47265625 655.668701171875 5696.121841430664 + 8.75 76.5625 669.921875 5861.81640625 + 8.8125 77.66015625 684.380126953125 6031.099868774414 + 8.875 78.765625 699.044921875 6204.023681640625 + 8.9375 79.87890625 713.917724609375 6380.639663696289 + 9. 81. 729. 6561. + 9.0625 82.12890625 744.293212890625 6745.157241821289 + 9.125 83.265625 759.798828125 6933.164306640625 + 9.1875 84.41015625 775.518310546875 7125.074478149414 + 9.25 85.5625 791.453125 7320.94140625 + 9.3125 86.72265625 807.604736328125 7520.819107055664 + 9.375 87.890625 823.974609375 7724.761962890625 + 9.4375 89.06640625 840.564208984375 7932.824722290039 + 9.5 90.25 857.375 8145.0625 + 9.5625 91.44140625 874.408447265625 8361.530776977539 + 9.625 92.640625 891.666015625 8582.285400390625 + 9.6875 93.84765625 909.149169921875 8807.382583618164 + 9.75 95.0625 926.859375 9036.87890625 + 9.8125 96.28515625 944.798095703125 9270.831314086914 + 9.875 97.515625 962.966796875 9509.297119140625 + 9.9375 98.75390625 981.366943359375 9752.333999633789 + 10. 100. 1000. 10000. diff --git a/BusinessSimulation/Sensors/AbsoluteSensor.mo b/BusinessSimulation/Sensors/AbsoluteSensor.mo new file mode 100644 index 0000000..74ad29c --- /dev/null +++ b/BusinessSimulation/Sensors/AbsoluteSensor.mo @@ -0,0 +1,29 @@ +within BusinessSimulation.Sensors; + +model AbsoluteSensor "Reports basic stock–related information" + extends Interfaces.Basics.GenericSensor; +equation + stock = u_stockInfo.infoLevel; + inFlow = u_stockInfo.infoInflow; + outFlow = u_stockInfo.infoOutflow; + netFlow = u_stockInfo.infoNetFlow; + meanResidenceTime = u_stockInfo.infoMeanResidenceTime; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The AbsoluteSensor connects to the StockInfoOutput connectors (y_stockInfo), which can be turned on and off). It reports the following information via its output connectors:

+ +

Notes

+ +

See also

+

StockInfoDynamicStockInfo

+"), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end AbsoluteSensor; diff --git a/BusinessSimulation/Sensors/DynamicStockInfo.mo b/BusinessSimulation/Sensors/DynamicStockInfo.mo new file mode 100644 index 0000000..1edf31b --- /dev/null +++ b/BusinessSimulation/Sensors/DynamicStockInfo.mo @@ -0,0 +1,33 @@ +within BusinessSimulation.Sensors; + +model DynamicStockInfo "Collect basic stock-related information for stocks with implicit dynamics" + extends Interfaces.Basics.GenericStockInfo_Special; + Interfaces.Connectors.RealInput residenceTimeInfo "Provide residence time input" annotation(Placement(visible = true, transformation(origin = {-145, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {50, -60}, extent = {{10, -10}, {-10, 10}}, rotation = -90))); +protected + Real totalFlow = inPort.rate + outPort.rate; + Real inflowInflow, inflowOutflow, outflowInflow, outflowOutflow; +equation + // separate the flows + inflowInflow = if noEvent(inPort.rate > 0) then inPort.rate else 0; + inflowOutflow = if noEvent(inPort.rate < 0) then -inPort.rate else 0; + outflowInflow = if noEvent(outPort.rate > 0) then outPort.rate else 0; + outflowOutflow = if noEvent(outPort.rate < 0) then -outPort.rate else 0; + // report information + y_stockInfo.infoLevel = levelInfo; + y_stockInfo.infoInflow = inflowInflow + outflowInflow; + y_stockInfo.infoOutflow = inflowOutflow + outflowOutflow; + y_stockInfo.infoNetFlow = totalFlow; + y_stockInfo.infoMeanResidenceTime = residenceTimeInfo; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The DynamicStockInfo is used inside stock components with inherent dynamic behavior (e.g. a →DelayN) and will be connected to the matching outside connectors of a component to collect basic →stock-related information which will be passed as a record to the StockInfoOutput connector.

+

Notes

+ +

See also

+

AbsoluteSensorStockInfo

+"), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end DynamicStockInfo; diff --git a/BusinessSimulation/Sensors/FlowPortSensor.mo b/BusinessSimulation/Sensors/FlowPortSensor.mo new file mode 100644 index 0000000..81c5f76 --- /dev/null +++ b/BusinessSimulation/Sensors/FlowPortSensor.mo @@ -0,0 +1,16 @@ +within BusinessSimulation.Sensors; + +model FlowPortSensor "Level information for an outside FlowPort" + Interfaces.Connectors.FlowPort flowPort annotation(Placement(visible = true, transformation(origin = {0, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {0, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealOutput stock(unit = "1") "Current level of connected stock" annotation(Placement(visible = true, transformation(origin = {160, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {0.488, 110}, extent = {{-10, -10}, {10, 10}}, rotation = -270))); +equation + flowPort.rate = 0; + stock = flowPort.stock; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This component is typically used to build submodels where the information regarding the amount in a connected stock needs to be extracted from an outside FlowPort.

+

For example, the FlowPortSensor is used inside the SourceOrSink component ExponentialGrowth, where the level information is needed for the stock as it will be multiplied with a fractional rate to obtain the actual rate for the component's flow into the stock.

+

See also

+

FlowPortSensor_ControlStockPortSensor

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {0, 33.849}, points = {{0, -33.849}, {0, 33.849}}, color = {128, 0, 128}, thickness = 3), Ellipse(visible = true, origin = {0, 70}, rotation = 30, lineColor = {0, 0, 128}, fillColor = {76, 112, 136}, fillPattern = FillPattern.Solid, lineThickness = 3, extent = {{-20.708, -20.708}, {20.708, 20.708}}), Line(visible = true, origin = {-14.33, 77.5}, rotation = -300, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-8.5, 83.33}, rotation = 30, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {0.219, 86.375}, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-2.624, 73.453}, rotation = -300, points = {{2.435, 4.688}, {-2.435, -4.688}}, color = {255, 0, 0}, thickness = 1), Line(visible = true, origin = {13.857, 78.141}, rotation = 660, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {7.922, 84.346}, rotation = -30, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-16, 70}, rotation = -270, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {16, 70}, rotation = -270, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Text(visible = true, origin = {0, 60}, textColor = {255, 255, 255}, extent = {{-12.617, -10}, {12.617, 10}}, textString = "S", fontSize = 30, fontName = "Arial", textStyle = {TextStyle.Bold}), Ellipse(visible = true, origin = {0.097, 70}, lineColor = {255, 0, 0}, fillColor = {255, 0, 0}, fillPattern = FillPattern.Solid, extent = {{-3, -3}, {3, 3}}), Text(visible = true, origin = {1.113, -50.492}, textColor = {0, 0, 128}, extent = {{-141.113, -29.508}, {141.113, 29.508}}, textString = "%name", fontSize = 100, fontName = "Arial", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end FlowPortSensor; diff --git a/BusinessSimulation/Sensors/FlowPortSensor_Control.mo b/BusinessSimulation/Sensors/FlowPortSensor_Control.mo new file mode 100644 index 0000000..45439bf --- /dev/null +++ b/BusinessSimulation/Sensors/FlowPortSensor_Control.mo @@ -0,0 +1,27 @@ +within BusinessSimulation.Sensors; + +model FlowPortSensor_Control "Level information for an outside FlowPort" + Interfaces.Connectors.FlowPort flowPort annotation(Placement(visible = true, transformation(origin = {0, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {0, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.RealOutput stock "Current amount in connected stock" annotation(Placement(visible = true, transformation(origin = {160, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {0.488, 110}, extent = {{-10, -10}, {10, 10}}, rotation = -270))); + Interfaces.Connectors.BooleanOutput stopInflow "Report the signal received" annotation(Placement(visible = true, transformation(origin = {150, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-20, 30}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Interfaces.Connectors.BooleanOutput stopOutflow "Report the signal received" annotation(Placement(visible = true, transformation(origin = {150, -80}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {20, 30}, extent = {{10, -10}, {-10, 10}}, rotation = -540))); +initial equation + // properly initialize discret vars with fixed = false + pre(stopInflow) = flowPort.stopInflow; + pre(stopOutflow) = flowPort.stopOutflow; +equation + // no flow for this component + flowPort.rate = 0; + stock = flowPort.stock; + stopInflow = flowPort.stopInflow; + stopOutflow = flowPort.stopOutflow; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This component is typically used to build submodels where the information regarding the amount in a connected stock needs to be extracted from an outside FlowPort.

+

For example, the FlowPortSensor is used inside the SourceOrSink component ExponentialGrowth, where the level information is needed for the stock as it will be multiplied with a fractional rate to obtain the actual rate for the component's flow into the stock.

+

Notes

+

While the FlowPortSensor only reports the rate of flow, this component additionally reports the Boolean signals (stopInflow, stopOutflow) received at the outside FlowPort.

+

See also

+

FlowPortSensorStockPortSensor

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {0, 33.849}, points = {{0, -33.849}, {0, 33.849}}, color = {128, 0, 128}, thickness = 3), Ellipse(visible = true, origin = {0, 70}, rotation = 30, lineColor = {0, 0, 128}, fillColor = {76, 112, 136}, fillPattern = FillPattern.Solid, lineThickness = 3, extent = {{-20.708, -20.708}, {20.708, 20.708}}), Line(visible = true, origin = {-14.33, 77.5}, rotation = -300, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-8.5, 83.33}, rotation = 30, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {0.219, 86.375}, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-2.624, 73.453}, rotation = -300, points = {{2.435, 4.688}, {-2.435, -4.688}}, color = {255, 0, 0}, thickness = 1), Line(visible = true, origin = {13.857, 78.141}, rotation = 660, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {7.922, 84.346}, rotation = -30, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-16, 70}, rotation = -270, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {16, 70}, rotation = -270, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Text(visible = true, origin = {0, 60}, textColor = {255, 255, 255}, extent = {{-12.617, -10}, {12.617, 10}}, textString = "S", fontSize = 30, fontName = "Arial", textStyle = {TextStyle.Bold}), Ellipse(visible = true, origin = {0.097, 70}, lineColor = {255, 0, 0}, fillColor = {255, 0, 0}, fillPattern = FillPattern.Solid, extent = {{-3, -3}, {3, 3}}), Text(visible = true, origin = {1.113, -50.492}, textColor = {0, 0, 128}, extent = {{-141.113, -29.508}, {141.113, 29.508}}, textString = "%name", fontSize = 100, fontName = "Arial", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end FlowPortSensor_Control; diff --git a/BusinessSimulation/Sensors/StockInfo.mo b/BusinessSimulation/Sensors/StockInfo.mo new file mode 100644 index 0000000..20da92a --- /dev/null +++ b/BusinessSimulation/Sensors/StockInfo.mo @@ -0,0 +1,32 @@ +within BusinessSimulation.Sensors; + +model StockInfo "Collect basic stock-related information for basic stocks" + extends Interfaces.Basics.GenericStockInfo; +protected + Real totalFlow = inPort.rate + outPort.rate; + Real inflowInflow, inflowOutflow, outflowInflow, outflowOutflow; +equation + // separate the flows + inflowInflow = if noEvent(inPort.rate > 0) then inPort.rate else 0; + inflowOutflow = if noEvent(inPort.rate < 0) then -inPort.rate else 0; + outflowInflow = if noEvent(outPort.rate > 0) then outPort.rate else 0; + outflowOutflow = if noEvent(outPort.rate < 0) then -outPort.rate else 0; + // report information + y_stockInfo.infoLevel = levelInfo; + y_stockInfo.infoInflow = inflowInflow + outflowInflow; + y_stockInfo.infoOutflow = inflowOutflow + outflowOutflow; + y_stockInfo.infoNetFlow = totalFlow; + y_stockInfo.infoMeanResidenceTime = if noEvent(y_stockInfo.infoOutflow > 0) then levelInfo / y_stockInfo.infoOutflow else -1; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The StockInfo is used inside stock components and will be connected to the matching outside connectors of a component to collect basic →stock-related information which will be passed as a record to the StockInfoOutput connector.

+

Notes

+ +

See also

+

AbsoluteSensorDynamicStockInfo

+"), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end StockInfo; diff --git a/BusinessSimulation/Sensors/StockPortSensor.mo b/BusinessSimulation/Sensors/StockPortSensor.mo new file mode 100644 index 0000000..bef88a2 --- /dev/null +++ b/BusinessSimulation/Sensors/StockPortSensor.mo @@ -0,0 +1,20 @@ +within BusinessSimulation.Sensors; + +model StockPortSensor "Rate of flow information from stock ports" + Interfaces.Connectors.RealOutput netFlow(quantity = "Rate", unit = "1/s") "Current netflow" annotation(Placement(visible = true, transformation(origin = {160, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {0.237, 110}, extent = {{-10, -10}, {10, 10}}, rotation = -270))); + Interfaces.Connectors.StockPort stockPort annotation(Placement(visible = true, transformation(origin = {-148.083, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-100, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.FlowPort flowPort annotation(Placement(visible = true, transformation(origin = {147.868, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {97.643, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + netFlow = stockPort.rate; + stockPort.stock = flowPort.stock; + flowPort.rate = -stockPort.rate; + // relay the boolean signals from flowPort to stockPort + stockPort.stopInflow = flowPort.stopInflow; + stockPort.stopOutflow = flowPort.stopOutflow; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This component is typically used to build submodels where the information regarding the rate of flow needs to be extracted from the outside StockPort.

+

See also

+

StockPortSensor_ControlFlowPortSensor

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {0, 33.849}, points = {{0, -33.849}, {0, 33.849}}, color = {128, 0, 128}, thickness = 3), Ellipse(visible = true, origin = {0, 70}, rotation = 30, lineColor = {0, 0, 128}, fillColor = {76, 112, 136}, fillPattern = FillPattern.Solid, lineThickness = 3, extent = {{-20.708, -20.708}, {20.708, 20.708}}), Line(visible = true, origin = {-14.33, 77.5}, rotation = -300, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-8.5, 83.33}, rotation = 30, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {0.219, 86.375}, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-2.624, 73.453}, rotation = -300, points = {{2.435, 4.688}, {-2.435, -4.688}}, color = {255, 0, 0}, thickness = 1), Line(visible = true, origin = {13.857, 78.141}, rotation = 660, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {7.922, 84.346}, rotation = -30, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-16, 70}, rotation = -270, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {16, 70}, rotation = -270, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Text(visible = true, origin = {0, 60}, textColor = {255, 255, 255}, extent = {{-12.617, -10}, {12.617, 10}}, textString = "F", fontSize = 30, fontName = "Arial", textStyle = {TextStyle.Bold}), Ellipse(visible = true, origin = {0.097, 70}, lineColor = {255, 0, 0}, fillColor = {255, 0, 0}, fillPattern = FillPattern.Solid, extent = {{-3, -3}, {3, 3}}), Line(visible = true, origin = {0.848, 0}, points = {{-99.152, 0}, {99.152, 0}}, color = {128, 0, 128}, thickness = 3), Ellipse(visible = true, origin = {0.202, 0.791}, rotation = 5.118, lineColor = {128, 0, 128}, fillColor = {128, 0, 128}, fillPattern = FillPattern.Solid, lineThickness = 3, extent = {{-2.202, -2.202}, {2.202, 2.202}}), Text(visible = true, origin = {1.113, -50.492}, textColor = {0, 0, 128}, extent = {{-141.113, -29.508}, {141.113, 29.508}}, textString = "%name", fontSize = 100, fontName = "Arial", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end StockPortSensor; diff --git a/BusinessSimulation/Sensors/StockPortSensor_Control.mo b/BusinessSimulation/Sensors/StockPortSensor_Control.mo new file mode 100644 index 0000000..326cb27 --- /dev/null +++ b/BusinessSimulation/Sensors/StockPortSensor_Control.mo @@ -0,0 +1,33 @@ +within BusinessSimulation.Sensors; + +model StockPortSensor_Control "Rate of flow information from stock ports" + Interfaces.Connectors.RealOutput netFlow(quantity = "Rate", unit = "1/s") "Current netflow" annotation(Placement(visible = true, transformation(origin = {160, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {0.237, 110}, extent = {{-10, -10}, {10, 10}}, rotation = -270))); + Interfaces.Connectors.StockPort stockPort annotation(Placement(visible = true, transformation(origin = {-148.083, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-100, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.FlowPort flowPort annotation(Placement(visible = true, transformation(origin = {147.868, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {97.643, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Interfaces.Connectors.BooleanInput u_stopOutflow "Boolean signal to prevent outflow from the component" annotation(Placement(visible = true, transformation(origin = {-145, 60}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {49.994, 99.994}, extent = {{-9.994, -9.994}, {9.994, 9.994}}, rotation = -90))); + Interfaces.Connectors.BooleanInput u_stopInflow "Boolean signal to prevent inflow into the component" annotation(Placement(visible = true, transformation(origin = {-145, -60}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-50, 100}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Interfaces.Connectors.BooleanOutput stopInflow "Report the signal received at the flow port side" annotation(Placement(visible = true, transformation(origin = {160, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-20, 30}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Interfaces.Connectors.BooleanOutput stopOutflow "Report the signal received at the flow port side" annotation(Placement(visible = true, transformation(origin = {160, -80}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {20, 30}, extent = {{10, -10}, {-10, 10}}, rotation = -540))); +initial equation + // properly initialize discrete vars with fixed = false + pre(stopInflow) = flowPort.stopInflow; + pre(stopOutflow) = flowPort.stopOutflow; + pre(stockPort.stopInflow) = u_stopInflow; + pre(stockPort.stopOutflow) = u_stopOutflow; +equation + netFlow = stockPort.rate; + stockPort.stock = flowPort.stock; + flowPort.rate = -stockPort.rate; + // report signals received at flow port side + stopInflow = flowPort.stopInflow; + stopOutflow = flowPort.stopOutflow; + // boolean signals are set according to the explicitly given inputs + stockPort.stopInflow = u_stopInflow; + stockPort.stopOutflow = u_stopOutflow; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This component is typically used to build submodels where the information regarding the rate of flow needs to be extracted from the outside StockPort. In this component the Boolean flags stopInflow and stopOutflow can be explicitly set using the Boolean input connectors and the input values will override the signals received at the FlowPort, which will typically be connected to the inside StockPort which would normally be directly connected to the outside one.

+

See also

+

StockPortSensorFlowPortSensor

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, origin = {0, 33.849}, points = {{0, -33.849}, {0, 33.849}}, color = {128, 0, 128}, thickness = 3), Ellipse(visible = true, origin = {0, 70}, rotation = 30, lineColor = {0, 0, 128}, fillColor = {76, 112, 136}, fillPattern = FillPattern.Solid, lineThickness = 3, extent = {{-20.708, -20.708}, {20.708, 20.708}}), Line(visible = true, origin = {-14.33, 77.5}, rotation = -300, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-8.5, 83.33}, rotation = 30, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {0.219, 86.375}, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-2.624, 73.453}, rotation = -300, points = {{2.435, 4.688}, {-2.435, -4.688}}, color = {255, 0, 0}, thickness = 1), Line(visible = true, origin = {13.857, 78.141}, rotation = 660, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {7.922, 84.346}, rotation = -30, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {-16, 70}, rotation = -270, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Line(visible = true, origin = {16, 70}, rotation = -270, points = {{0, 3}, {0, -3}}, color = {255, 255, 255}, thickness = 1), Text(visible = true, origin = {0, 60}, textColor = {255, 255, 255}, extent = {{-12.617, -10}, {12.617, 10}}, textString = "F", fontSize = 30, fontName = "Arial", textStyle = {TextStyle.Bold}), Ellipse(visible = true, origin = {0.097, 70}, lineColor = {255, 0, 0}, fillColor = {255, 0, 0}, fillPattern = FillPattern.Solid, extent = {{-3, -3}, {3, 3}}), Line(visible = true, origin = {0.848, 0}, points = {{-99.152, 0}, {99.152, 0}}, color = {128, 0, 128}, thickness = 3), Ellipse(visible = true, origin = {0.202, 0.791}, rotation = 5.118, lineColor = {128, 0, 128}, fillColor = {128, 0, 128}, fillPattern = FillPattern.Solid, lineThickness = 3, extent = {{-2.202, -2.202}, {2.202, 2.202}}), Text(visible = true, origin = {1.113, -50.492}, textColor = {0, 0, 128}, extent = {{-141.113, -29.508}, {141.113, 29.508}}, textString = "%name", fontSize = 100, fontName = "Arial", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end StockPortSensor_Control; diff --git a/BusinessSimulation/Sensors/package.mo b/BusinessSimulation/Sensors/package.mo new file mode 100644 index 0000000..95ac29a --- /dev/null +++ b/BusinessSimulation/Sensors/package.mo @@ -0,0 +1,12 @@ +within BusinessSimulation; + +package Sensors "Package with sensor components" + extends Icons.Package; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This package contains sensor components especially needed to access acausal connector information from within a component.

+
+
+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Ellipse(visible = true, lineColor = {0, 0, 128}, fillColor = {76, 112, 136}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-58, -58}, {58, 58}}), Ellipse(visible = true, rotation = 30, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, lineThickness = 3, extent = {{-45, -45}, {45, 45}}), Line(visible = true, origin = {0, 39.149}, points = {{0, 5}, {0, -5}}, color = {255, 255, 255}, thickness = 3), Line(visible = true, origin = {0, -39.851}, points = {{0, 5}, {0, -5}}, color = {255, 255, 255}, thickness = 3), Line(visible = true, origin = {-40, 0}, rotation = -270, points = {{0, 5}, {0, -5}}, color = {255, 255, 255}, thickness = 3), Line(visible = true, origin = {39.55, -1.72}, rotation = -270, points = {{0, 5}, {0, -5}}, color = {255, 255, 255}, thickness = 3), Line(visible = true, origin = {-33.464, -20.536}, rotation = 300, points = {{0, 5}, {0, -5}}, color = {255, 255, 255}, thickness = 3), Line(visible = true, origin = {34.536, 20.464}, rotation = 300, points = {{0, 5}, {0, -5}}, color = {255, 255, 255}, thickness = 3), Line(visible = true, origin = {20.536, -33.536}, rotation = 30, points = {{0, 5}, {0, -5}}, color = {255, 255, 255}, thickness = 3), Line(visible = true, origin = {-19.464, 33.464}, rotation = 30, points = {{0, 5}, {0, -5}}, color = {255, 255, 255}, thickness = 3), Line(visible = true, origin = {20.5, 33.33}, rotation = -30, points = {{0, 5}, {0, -5}}, color = {255, 255, 255}, thickness = 3), Line(visible = true, origin = {-19.5, -34.67}, rotation = -30, points = {{0, 5}, {0, -5}}, color = {255, 255, 255}, thickness = 3), Line(visible = true, origin = {33.5, -19.67}, rotation = -300, points = {{0, 5}, {0, -5}}, color = {255, 255, 255}, thickness = 3), Line(visible = true, origin = {-34.5, 19.33}, rotation = -300, points = {{0, 5}, {0, -5}}, color = {255, 255, 255}, thickness = 3), Ellipse(visible = true, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-6, -6}, {6, 6}}), Line(visible = true, origin = {-3.506, -9.19}, rotation = -783.662, points = {{-8.99, 10.512}, {-16.315, 36.455}, {-5.826, 8.946}}, color = {255, 255, 255}, thickness = 5, smooth = Smooth.Bezier)}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Sensors; diff --git a/BusinessSimulation/Sensors/package.order b/BusinessSimulation/Sensors/package.order new file mode 100644 index 0000000..4a52667 --- /dev/null +++ b/BusinessSimulation/Sensors/package.order @@ -0,0 +1,7 @@ +AbsoluteSensor +FlowPortSensor +FlowPortSensor_Control +StockPortSensor +StockPortSensor_Control +StockInfo +DynamicStockInfo diff --git a/BusinessSimulation/SourcesOrSinks/Cloud.mo b/BusinessSimulation/SourcesOrSinks/Cloud.mo new file mode 100644 index 0000000..6818a04 --- /dev/null +++ b/BusinessSimulation/SourcesOrSinks/Cloud.mo @@ -0,0 +1,13 @@ +within BusinessSimulation.SourcesOrSinks; + +final model Cloud "Reservoir (stock/level) with an infinite capacity" + Interfaces.Connectors.StockPort massPort "Connector for cloud" annotation(Placement(visible = true, transformation(origin = {-148.461, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {100, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + massPort.stock = 0; + massPort.stopInflow = false; + massPort.stopOutflow = false; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The Cloud is a reservoir (stock or level) with an infinite capacty. It is used at a system's border to provide a source for incoming or a sink for outgoing \"matter\".

+"), __Wolfram(itemFlippingEnabled = true), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, origin = {50, 0}, rotation = -90, lineColor = {255, 0, 0}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-50, 50}, {50, -50}}), Line(visible = true, origin = {50.361, -1.132}, points = {{-19.013, -1.251}, {-19.013, 5.61}, {-13.146, 10.097}, {-4.518, 6.3}, {3.107, -1.637}, {9.976, -6.855}, {16.533, -6.855}, {19.639, -3.018}, {19.639, 4.92}, {13.107, 11.132}, {6.525, 8.716}, {3.107, 3.145}, {-4.173, -6.855}, {-14.872, -8.539}, {-19.013, -1.251}, {-19.013, -1.251}}, color = {255, 0, 0}, thickness = 3, smooth = Smooth.Bezier)}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Cloud; diff --git a/BusinessSimulation/SourcesOrSinks/Decline.mo b/BusinessSimulation/SourcesOrSinks/Decline.mo new file mode 100644 index 0000000..7d79f1d --- /dev/null +++ b/BusinessSimulation/SourcesOrSinks/Decline.mo @@ -0,0 +1,33 @@ +within BusinessSimulation.SourcesOrSinks; + +model Decline "A stock is drained at a given rate" + import BusinessSimulation.Units.Rate; + extends Interfaces.Basics.GenericSourceOrSink; + extends Icons.Sink; + Interfaces.Connectors.RealInput u if not hasConstantRate "Rate of decline given as exogenous input" annotation(Placement(visible = true, transformation(origin = {-140, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-50, 100}, extent = {{-10, 10}, {10, -10}}, rotation = 270))); + parameter OutputType rate = 0 "Constant rate of decline (optional)" annotation(Dialog(enable = hasConstantRate)); + parameter Boolean hasConstantRate = false "= true, if the constant rate is used instead of an exogenous input u" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); +protected + Converters.ConstantConverter parConstantRate(value = rate) if hasConstantRate "Constante rate of decline (optional)" annotation(Placement(visible = true, transformation(origin = {-110, 70}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Flows.Unidirectional.Transition decreasing "Process of linear delince" annotation(Placement(visible = true, transformation(origin = {0, 0}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Cloud cloud "System boundary" annotation(Placement(visible = true, transformation(origin = {-50, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(massPort, decreasing.portA) annotation(Line(visible = true, origin = {85, 0}, points = {{75, 0}, {-75, 0}}, color = {128, 0, 128})); + connect(decreasing.y2, y) annotation(Line(visible = true, origin = {52.625, 12.5}, points = {{-42.125, -17.5}, {-32.625, -17.5}, {-32.625, 17.5}, {107.375, 17.5}}, color = {1, 37, 163})); + connect(decreasing.y2, y1) annotation(Line(visible = true, origin = {52.625, 32.5}, points = {{-42.125, -37.5}, {-32.625, -37.5}, {-32.625, 37.5}, {107.375, 37.5}}, color = {1, 37, 163})); + connect(decreasing.y2, y2) annotation(Line(visible = true, origin = {52.625, -27.5}, points = {{-42.125, 22.5}, {-32.625, 22.5}, {-32.625, -22.5}, {107.375, -22.5}}, color = {1, 37, 163})); + connect(parConstantRate.y, decreasing.u) annotation(Line(visible = true, origin = {-32.18, 50}, points = {{-74.359, 20}, {37.18, 20}, {37.18, -40}}, color = {1, 37, 163})); + connect(u, decreasing.u) annotation(Line(visible = true, origin = {-43.333, 30}, points = {{-96.667, 10}, {48.333, 10}, {48.333, -20}}, color = {1, 37, 163})); + connect(decreasing.portB, cloud.massPort) annotation(Line(visible = true, origin = {-25, 0}, points = {{15, 0}, {-15, 0}}, color = {128, 0, 128})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Decline can be used to model an outflow from a stock into a sink with infinite capacity outside the border of the system in focus. The rate of flow can either be set by the real input u (hasConstantRate = false) or by the parameter rate (hasConstantRate = true).

+

Notes

+ +

See also

+

GrowthExogenousChange 

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {25.628, -73.291}, textColor = {0, 0, 128}, extent = {{-48.638, -12}, {48.638, 12}}, textString = "rate", fontName = "Lato", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {0, 75}, textColor = {0, 128, 0}, extent = {{-100, -12}, {100, 12}}, textString = "Decline", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Line(visible = true, origin = {-5.154, -19.63}, rotation = 5.306, points = {{36.522, -45.771}, {43.438, -34.535}, {45.906, -7.964}}, color = {0, 0, 128}, thickness = 2.5, arrowSize = 0, smooth = Smooth.Bezier), Polygon(visible = true, origin = {41, -26.925}, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, points = {{0, 9}, {5, -5}, {-5, -5}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Decline; diff --git a/BusinessSimulation/SourcesOrSinks/ExogenousChange.mo b/BusinessSimulation/SourcesOrSinks/ExogenousChange.mo new file mode 100644 index 0000000..ab4f157 --- /dev/null +++ b/BusinessSimulation/SourcesOrSinks/ExogenousChange.mo @@ -0,0 +1,23 @@ +within BusinessSimulation.SourcesOrSinks; + +model ExogenousChange "A stock is filled or drained at a given rate" + extends Interfaces.Basics.GenericSourceOrSink; + extends Icons.SourceOrSink; + extends Interfaces.Basics.SingleInput; +protected + Flows.Bidirectional.Switching switching annotation(Placement(visible = true, transformation(origin = {0, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Cloud cloud annotation(Placement(visible = true, transformation(origin = {-30, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(switching.portB, massPort) annotation(Line(visible = true, origin = {85, 0}, points = {{-75, 0}, {75, 0}}, color = {128, 0, 128})); + connect(cloud.massPort, switching.portA) annotation(Line(visible = true, origin = {-15, 0}, points = {{-5, 0}, {5, 0}}, color = {128, 0, 128})); + connect(switching.y, y1) annotation(Line(visible = true, origin = {54.667, 50.133}, points = {{-49.667, -39.733}, {-49.667, 19.867}, {105.333, 19.867}}, color = {0, 0, 127})); + connect(switching.y, y) annotation(Line(visible = true, origin = {54.667, 23.467}, points = {{-49.667, -13.067}, {-49.667, 6.533}, {105.333, 6.533}}, color = {0, 0, 127})); + connect(switching.y1, y2) annotation(Line(visible = true, origin = {69.237, -28.5}, points = {{-58.737, 23.5}, {30.763, 23.5}, {30.763, -21.5}, {90.763, -21.5}}, color = {0, 0, 127})); + connect(u, switching.u) annotation(Line(visible = true, origin = {-50, 30}, points = {{-90, 10}, {45, 10}, {45, -20}}, color = {0, 0, 127})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

ExogenousChange can be used to model an inflow to a stock from a source or an outflow from a stock to a sink. In either case it is assumed, that the source or sink has infinite capacity and thus lies outside the border of the system in focus. By convention, a positive rate will fill the connected stock, while a negative rate will drain it. The rate of flow is determined by the real input u.

+

See also

+

GrowthDecline

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {20, -75.803}, textColor = {0, 0, 128}, extent = {{-53.428, -12}, {53.428, 12}}, textString = "rate", fontName = "Lato", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {0, 75}, textColor = {0, 128, 0}, extent = {{-100, -12}, {100, 12}}, textString = "Change", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Line(visible = true, origin = {-15.154, -19.63}, rotation = 5.306, points = {{36.522, -45.771}, {43.438, -34.535}, {45.906, -7.964}}, color = {0, 0, 128}, thickness = 2.5, arrowSize = 0, smooth = Smooth.Bezier), Polygon(visible = true, origin = {31, -26.925}, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, points = {{0, 9}, {5, -5}, {-5, -5}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end ExogenousChange; diff --git a/BusinessSimulation/SourcesOrSinks/ExponentialChange.mo b/BusinessSimulation/SourcesOrSinks/ExponentialChange.mo new file mode 100644 index 0000000..ff658e1 --- /dev/null +++ b/BusinessSimulation/SourcesOrSinks/ExponentialChange.mo @@ -0,0 +1,42 @@ +within BusinessSimulation.SourcesOrSinks; + +model ExponentialChange "Exponential growth or decline of connected stock" + extends Interfaces.Basics.GenericSourceOrSink; + extends Icons.SourceOrSink; + extends Interfaces.Basics.SingleInput; + parameter Boolean isCCR = true "= true, if the factional rate given is assumed to be a continuously compounding rate else the rate will be converted" annotation(Dialog(group = "Structural Parameters")); +protected + Cloud cloud annotation(Placement(visible = true, transformation(origin = {-50, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Flows.Bidirectional.Switching changing annotation(Placement(visible = true, transformation(origin = {0, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Sensors.FlowPortSensor stockLevel "LEvel of connected stock" annotation(Placement(visible = true, transformation(origin = {105, 10}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Product_2 changingRate annotation(Placement(visible = true, transformation(origin = {-5, 25}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.PassThrough indicatedFractionalRate if isCCR "Output is equal to input" annotation(Placement(visible = true, transformation(origin = {-70, 70}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ForceOfInterest ccRate if not isCCR "Continuously Compounding Rate" annotation(Placement(visible = true, transformation(origin = {-70, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(cloud.massPort, changing.portA) annotation(Line(visible = true, origin = {-25, 0}, points = {{-15, 0}, {15, 0}}, color = {128, 0, 128})); + connect(changing.portB, massPort) annotation(Line(visible = true, origin = {85, 0}, points = {{-75, 0}, {75, 0}}, color = {128, 0, 128})); + connect(stockLevel.flowPort, massPort) annotation(Line(visible = true, origin = {123.333, 2.328}, points = {{-18.333, 7.672}, {-18.333, -2.328}, {25.001, -2.328}}, color = {128, 0, 128})); + connect(stockLevel.stock, changingRate.u1) annotation(Line(visible = true, origin = {52.524, 33.5}, points = {{52.524, -12.5}, {52.524, 6.5}, {-52.524, 6.5}, {-52.524, -0.5}}, color = {1, 37, 163})); + connect(changing.y, y1) annotation(Line(visible = true, origin = {56.667, 50.133}, points = {{-51.667, -39.733}, {-51.667, 19.867}, {103.333, 19.867}}, color = {1, 37, 163})); + connect(changing.y, y) annotation(Line(visible = true, origin = {56.667, 23.467}, points = {{-51.667, -13.067}, {-51.667, 6.533}, {103.333, 6.533}}, color = {1, 37, 163})); + connect(changing.y1, y2) annotation(Line(visible = true, origin = {52.625, -27.5}, points = {{-42.125, 22.5}, {-32.625, 22.5}, {-32.625, -22.5}, {107.375, -22.5}}, color = {1, 37, 163})); + connect(changingRate.y, changing.u) annotation(Line(visible = true, origin = {-5, 13.819}, points = {{0, 3.819}, {0, -3.819}}, color = {1, 37, 163})); + connect(u, ccRate.u) annotation(Line(visible = true, origin = {-124, 40}, points = {{-46, 0}, {46, 0}}, color = {1, 37, 163})); + connect(ccRate.y, changingRate.u2) annotation(Line(visible = true, origin = {-27.333, 37.667}, points = {{-34.667, 2.333}, {17.333, 2.333}, {17.333, -4.667}}, color = {1, 37, 163})); + connect(u, indicatedFractionalRate.u) annotation(Line(visible = true, origin = {-112, 55}, points = {{-58, -15}, {12, -15}, {12, 15}, {34, 15}}, color = {1, 37, 163})); + connect(indicatedFractionalRate.y, changingRate.u2) annotation(Line(visible = true, origin = {-27.333, 57.667}, points = {{-34.667, 12.333}, {17.333, 12.333}, {17.333, -24.667}}, color = {1, 37, 163})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

ExponentialChange will fill (or drain) the connected stock from a source (or into a sink) with infinite capacity at a rate that is determined at any time as the product of the current amount in the connected stock and the fractional rate given by the real input u. By convention, a positive rate will fill the stock, while a negative rate will drain it.

+

Notes

+ + +

See also

+

ExponentialGrowthExponentialDecline, ExponentialDecay

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, 75}, textColor = {0, 128, 0}, extent = {{-100, -12}, {100, 12}}, textString = "EXP Change", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {-5.081, -78.316}, textColor = {0, 0, 128}, extent = {{-76.882, -12}, {76.882, 12}}, textString = "fractional rate", fontName = "Lato", textStyle = {TextStyle.Bold}), Line(visible = true, origin = {63.558, -10.273}, rotation = -5.306, points = {{32.722, 10.515}, {13.878, -30.192}, {-7.496, -34.124}, {-24.956, -15.69}}, color = {0, 0, 128}, thickness = 2.5, arrowSize = 0, smooth = Smooth.Bezier), Line(visible = true, origin = {-32.154, -19.63}, rotation = 5.306, points = {{27.907, -47.216}, {36.663, -27.43}, {51.602, -8.364}}, color = {0, 0, 128}, thickness = 2.5, arrowSize = 0, smooth = Smooth.Bezier), Polygon(visible = true, origin = {39.835, -26.283}, rotation = 30, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, points = {{0, 9}, {5, -5}, {-5, -5}}), Polygon(visible = true, origin = {19.113, -25.409}, rotation = -30, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, points = {{0, 9}, {-5, -5}, {5, -5}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end ExponentialChange; diff --git a/BusinessSimulation/SourcesOrSinks/ExponentialDecay.mo b/BusinessSimulation/SourcesOrSinks/ExponentialDecay.mo new file mode 100644 index 0000000..a56a313 --- /dev/null +++ b/BusinessSimulation/SourcesOrSinks/ExponentialDecay.mo @@ -0,0 +1,40 @@ +within BusinessSimulation.SourcesOrSinks; + +model ExponentialDecay "A stock is drained at a rate proportional to its content" + import BusinessSimulation.Units.Time; + extends Interfaces.Basics.GenericSourceOrSink; + extends Icons.Sink; + Interfaces.Connectors.RealInput u if not hasConstantResidenceTime "Residence time input" annotation(Placement(visible = true, transformation(origin = {-140, 60}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-50, 100}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + parameter Boolean hasConstantResidenceTime = false "= true, if the constant residence time is used instead of the real input u" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Time residenceTime(min = 0, unit = "s") = 1 "Constant time of average residence (optional) (decaying.residenceTime)" annotation(Dialog(enable = hasConstantResidenceTime)); +protected + Converters.ConstantConverterTime parResidenceTime(value = residenceTime) if hasConstantResidenceTime "Constant residence time (optional)" annotation(Placement(visible = true, transformation(origin = {-120, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Flows.Unidirectional.Decay decaying(hasConstantResidenceTime = false, residenceTime = residenceTime) annotation(Placement(visible = true, transformation(origin = {0, 0}, extent = {{-10, 10}, {10, -10}}, rotation = 540))); + Cloud drainedMaterial "System boundary - the stock will be assumed to have infinite capacity" annotation(Placement(visible = true, transformation(origin = {-50, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(massPort, decaying.portA) annotation(Line(visible = true, origin = {85, 0}, points = {{75, 0}, {-75, 0}}, color = {128, 0, 128})); + connect(decaying.portB, drainedMaterial.massPort) annotation(Line(visible = true, origin = {-25, 0}, points = {{15, 0}, {-15, 0}}, color = {128, 0, 128})); + connect(u, decaying.u) annotation(Line(visible = true, origin = {-43.333, 43.333}, points = {{-96.667, 16.667}, {48.333, 16.667}, {48.333, -33.333}}, color = {1, 37, 163})); + connect(decaying.y, y1) annotation(Line(visible = true, origin = {50, 50.133}, points = {{-55, -39.733}, {-55, 19.867}, {110, 19.867}}, color = {1, 37, 163})); + connect(decaying.y, y) annotation(Line(visible = true, origin = {50, 23.467}, points = {{-55, -13.067}, {-55, 6.533}, {110, 6.533}}, color = {1, 37, 163})); + connect(decaying.y2, y2) annotation(Line(visible = true, origin = {52.625, -27.5}, points = {{-42.125, 22.5}, {-32.625, 22.5}, {-32.625, -22.5}, {107.375, -22.5}}, color = {1, 37, 163})); + connect(parResidenceTime.y, decaying.u) annotation(Line(visible = true, origin = {-35, 30}, points = {{-80, 10}, {40, 10}, {40, -20}}, color = {1, 37, 163})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

ExponentialDecay is identical to →ExponentialDecline, e.g. the connected stock is drained at a rate proportional to its content into a sink with infinite capacity outside the border of the system in focus. Instead of using a fractional rate λ to describe the process, we are using the mean residence time τ (aka mean lifetime or the exponential time constant) to parameterize the process:

+

\"tau

+

The mean residence time can be given either as a constant parameter (residenceTime) or as a continuous time input u.

+

The effective rate of decay with respect to a connected stock x at any time will be given by

+

\"dx/dt

+

Notes

+ + +

See also

+

ExponentialDecline, DecayExponentialChange

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, 75}, textColor = {0, 128, 0}, extent = {{-100, -12}, {100, 12}}, textString = "EXP Decay", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {0, -75.728}, textColor = {0, 0, 128}, extent = {{-75.716, -11.684}, {75.716, 11.684}}, textString = "residence time", fontSize = 60, textStyle = {TextStyle.Bold}), Line(visible = true, origin = {63.558, -10.273}, rotation = -5.306, points = {{32.722, 10.515}, {27.406, -27.31}, {3.18, -33.132}, {-12.083, -16.513}}, color = {0, 0, 128}, thickness = 2.5, arrowSize = 0, smooth = Smooth.Bezier), Line(visible = true, origin = {-22.154, -19.63}, rotation = 5.306, points = {{26.276, -45.045}, {36.663, -27.43}, {51.602, -8.364}}, color = {0, 0, 128}, thickness = 2.5, arrowSize = 0, smooth = Smooth.Bezier), Polygon(visible = true, origin = {51.134, -25.316}, rotation = 30, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, points = {{0, 9}, {5, -5}, {-5, -5}}), Polygon(visible = true, origin = {29.113, -25.409}, rotation = -30, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, points = {{0, 9}, {-5, -5}, {5, -5}})})); +end ExponentialDecay; diff --git a/BusinessSimulation/SourcesOrSinks/ExponentialDecline.mo b/BusinessSimulation/SourcesOrSinks/ExponentialDecline.mo new file mode 100644 index 0000000..b49b873 --- /dev/null +++ b/BusinessSimulation/SourcesOrSinks/ExponentialDecline.mo @@ -0,0 +1,41 @@ +within BusinessSimulation.SourcesOrSinks; + +model ExponentialDecline "Exponential decline of connected stock" + import BusinessSimulation.Units.Rate; + extends Interfaces.Basics.GenericSourceOrSink; + extends Icons.Sink; + Interfaces.Connectors.RealInput u if not hasConstantRate "Fractional rate given as exogenous input" annotation(Placement(visible = true, transformation(origin = {-145, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-50, 100}, extent = {{-10, 10}, {10, -10}}, rotation = 270))); + parameter OutputType fractionalRate(min = 0) = 0 "Constant fractional rate to be used if chosen" annotation(Dialog(enable = hasConstantRate)); + parameter Boolean isCCR = true "= true, if the factional rate given is assumed to be a continuously compounding rate else the rate will be converted" annotation(Dialog(group = "Structural Parameters")); + parameter Boolean hasConstantRate = false "= true, if the constant fractional rate is used instead of the real input u" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); +protected + Flows.Unidirectional.ProportionalTransition decreasing annotation(Placement(visible = true, transformation(origin = {0, 0}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Cloud cloud "System boundary" annotation(Placement(visible = true, transformation(origin = {-30, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ConstantConverter parFractionalRate(value = fractionalRate) if hasConstantRate "Constant rate (optional)" annotation(Placement(visible = true, transformation(origin = {-110, 70}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.PassThrough indicatedRate if isCCR "Indicated fractional rate" annotation(Placement(visible = true, transformation(origin = {-70, 50}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ForceOfInterest convertedRate if not isCCR "Continuously compounding rate" annotation(Placement(visible = true, transformation(origin = {-70, 70}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + connect(massPort, decreasing.portA) annotation(Line(visible = true, origin = {85, 0}, points = {{75, 0}, {-75, 0}}, color = {128, 0, 128})); + connect(decreasing.portB, cloud.massPort) annotation(Line(visible = true, origin = {-15, 0}, points = {{5, 0}, {-5, 0}}, color = {128, 0, 128})); + connect(parFractionalRate.y, convertedRate.u) annotation(Line(visible = true, origin = {-92.269, 70}, points = {{-14.269, 0}, {14.269, 0}}, color = {1, 37, 163})); + connect(indicatedRate.y, decreasing.u) annotation(Line(visible = true, origin = {-17.546, 36.667}, points = {{-45.092, 13.333}, {22.546, 13.333}, {22.546, -26.667}}, color = {1, 37, 163})); + connect(u, convertedRate.u) annotation(Line(visible = true, origin = {-109.5, 55}, points = {{-35.5, -15}, {14.5, -15}, {14.5, 15}, {31.5, 15}}, color = {1, 37, 163})); + connect(parFractionalRate.y, indicatedRate.u) annotation(Line(visible = true, origin = {-91.135, 60}, points = {{-15.404, 10}, {1.135, 10}, {1.135, -10}, {13.135, -10}}, color = {1, 37, 163})); + connect(u, indicatedRate.u) annotation(Line(visible = true, origin = {-107, 45}, points = {{-38, -5}, {17, -5}, {17, 5}, {29, 5}}, color = {1, 37, 163})); + connect(convertedRate.y, decreasing.u) annotation(Line(visible = true, origin = {-17.546, 50}, points = {{-45.092, 20}, {22.546, 20}, {22.546, -40}}, color = {1, 37, 163})); + connect(decreasing.y2, y) annotation(Line(visible = true, origin = {52.625, 12.5}, points = {{-42.125, -17.5}, {-32.625, -17.5}, {-32.625, 17.5}, {107.375, 17.5}}, color = {1, 37, 163})); + connect(decreasing.y2, y2) annotation(Line(visible = true, origin = {52.625, -27.5}, points = {{-42.125, 22.5}, {-32.625, 22.5}, {-32.625, -22.5}, {107.375, -22.5}}, color = {1, 37, 163})); + connect(decreasing.y2, y1) annotation(Line(visible = true, origin = {52.625, 32.5}, points = {{-42.125, -37.5}, {-32.625, -37.5}, {-32.625, 37.5}, {107.375, 37.5}}, color = {1, 37, 163})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

ExponentialDecline will drain the connected stock into a sink with infinite capacity at a rate that is determined at any time as the product of the current amount in the connected stock and the fractional rate given. The rate can either be given as a constant parameter fractionalRate or as a real input u, making it variable in time.

+

Notes

+ +

See also

+

ExponentialGrowth, ExponentialDecayExponentialChange

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, 75}, textColor = {0, 128, 0}, extent = {{-100, -12}, {100, 12}}, textString = "EXP Decline", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Line(visible = true, origin = {63.558, -10.273}, rotation = -5.306, points = {{32.722, 10.515}, {27.406, -27.31}, {3.18, -33.132}, {-12.083, -16.513}}, color = {0, 0, 128}, thickness = 2.5, arrowSize = 0, smooth = Smooth.Bezier), Text(visible = true, origin = {0, -78.316}, textColor = {0, 0, 128}, extent = {{-71.945, -12}, {71.945, 12}}, textString = "fractional rate", fontName = "Lato", textStyle = {TextStyle.Bold}), Line(visible = true, origin = {-22.154, -19.63}, rotation = 5.306, points = {{36.522, -45.771}, {36.663, -27.43}, {51.602, -8.364}}, color = {0, 0, 128}, thickness = 2.5, arrowSize = 0, smooth = Smooth.Bezier), Polygon(visible = true, origin = {51.134, -25.316}, rotation = 30, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, points = {{0, 9}, {5, -5}, {-5, -5}}), Polygon(visible = true, origin = {29.113, -25.409}, rotation = -30, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, points = {{0, 9}, {-5, -5}, {5, -5}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end ExponentialDecline; diff --git a/BusinessSimulation/SourcesOrSinks/ExponentialGrowth.mo b/BusinessSimulation/SourcesOrSinks/ExponentialGrowth.mo new file mode 100644 index 0000000..35cd47f --- /dev/null +++ b/BusinessSimulation/SourcesOrSinks/ExponentialGrowth.mo @@ -0,0 +1,47 @@ +within BusinessSimulation.SourcesOrSinks; + +model ExponentialGrowth "Exponential growth of connected stock" + import BusinessSimulation.Units.Rate; + extends Interfaces.Basics.GenericSourceOrSink; + extends Icons.Source; + Interfaces.Connectors.RealInput u if not hasConstantRate "Fractional rate given as exogenous input" annotation(Placement(visible = true, transformation(origin = {-145, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-50, 100}, extent = {{-10, 10}, {10, -10}}, rotation = 270))); + parameter OutputType fractionalRate(min = 0) = 0 "Constant fractional rate to be used if chosen" annotation(Dialog(enable = hasConstantRate)); + parameter Boolean isCCR = true "= true, if the factional rate given is assumed to be a continuously compounding rate else the rate will be converted" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean hasConstantRate = false "= true, if the constant fractional rate is used instead of the real input u" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); +protected + Cloud cloud "System boundary" annotation(Placement(visible = true, transformation(origin = {-50, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Flows.Unidirectional.Transition growing "Inflow to connected stock" annotation(Placement(visible = true, transformation(origin = {0, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Sensors.FlowPortSensor stockLevel "Report amount in connected stock" annotation(Placement(visible = true, transformation(origin = {90, 10}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Product_2 rate "Rate of growth is proportional to level of connected stock" annotation(Placement(visible = true, transformation(origin = {-5, 25}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.ConstantConverter parFractionalRate(value = fractionalRate) if hasConstantRate "Constant rate (optional)" annotation(Placement(visible = true, transformation(origin = {-130, 70}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.PassThrough indicatedFractionalRate if isCCR "Output is equal to input" annotation(Placement(visible = true, transformation(origin = {-50, 70}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ForceOfInterest ccRate if not isCCR "Continuously Compounding Rate" annotation(Placement(visible = true, transformation(origin = {-50, 50}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + // positive rate grows the connected stock + connect(stockLevel.flowPort, massPort) annotation(Line(visible = true, origin = {135, 5}, points = {{-45, 5}, {-45, -5}, {25, -5}}, color = {128, 0, 128})); + connect(growing.portB, massPort) annotation(Line(visible = true, origin = {85, 0}, points = {{-75, 0}, {75, 0}}, color = {128, 0, 128})); + connect(stockLevel.stock, rate.u1) annotation(Line(visible = true, origin = {45.024, 33.5}, points = {{45.024, -12.5}, {45.024, 6.5}, {-45.024, 6.5}, {-45.024, -0.5}}, color = {1, 37, 163})); + connect(rate.y, growing.u) annotation(Line(visible = true, origin = {-5, 13.819}, points = {{0, 3.819}, {0, -3.819}}, color = {1, 37, 163})); + connect(cloud.massPort, growing.portA) annotation(Line(visible = true, origin = {-25, 0}, points = {{-15, 0}, {15, 0}}, color = {128, 0, 128})); + connect(growing.y, y1) annotation(Line(visible = true, origin = {56.667, 50.133}, points = {{-51.667, -39.733}, {-51.667, 19.867}, {103.333, 19.867}}, color = {1, 37, 163})); + connect(growing.y, y) annotation(Line(visible = true, origin = {56.667, 23.467}, points = {{-51.667, -13.067}, {-51.667, 6.533}, {103.333, 6.533}}, color = {1, 37, 163})); + connect(growing.y1, y2) annotation(Line(visible = true, origin = {52.625, -27.5}, points = {{-42.125, 22.5}, {-32.625, 22.5}, {-32.625, -22.5}, {107.375, -22.5}}, color = {1, 37, 163})); + connect(parFractionalRate.y, indicatedFractionalRate.u) annotation(Line(visible = true, origin = {-92.269, 70}, points = {{-34.269, 0}, {34.269, 0}}, color = {1, 37, 163})); + connect(indicatedFractionalRate.y, rate.u2) annotation(Line(visible = true, origin = {-20.879, 57.667}, points = {{-21.758, 12.333}, {10.879, 12.333}, {10.879, -24.667}}, color = {1, 37, 163})); + connect(parFractionalRate.y, ccRate.u) annotation(Line(visible = true, origin = {-103.25, 60}, points = {{-21.75, 10}, {-11.75, 10}, {-11.75, -10}, {45.25, -10}}, color = {1, 37, 163})); + connect(ccRate.y, rate.u2) annotation(Line(visible = true, origin = {-20.667, 44.333}, points = {{-21.333, 5.667}, {10.667, 5.667}, {10.667, -11.333}}, color = {1, 37, 163})); + connect(u, ccRate.u) annotation(Line(visible = true, origin = {-107, 45}, points = {{-38, -5}, {7, -5}, {7, 5}, {49, 5}}, color = {1, 37, 163})); + connect(u, indicatedFractionalRate.u) annotation(Line(visible = true, origin = {-97.43, 55}, points = {{-47.57, -15}, {-2.57, -15}, {-2.57, 15}, {39.43, 15}}, color = {1, 37, 163})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

ExponentialGrowth will fill the connected stock from a source with infinite capacity at a rate that is determined at any time as the product of the current amount in the connected stock and the fractional rate given. The rate can either be given as a constant parameter fractionalRate or as a real input u, making it variable in time.

+

Notes

+ +

See also

+

ExponentialDecline, DecayExponentialChange

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, 75}, textColor = {0, 128, 0}, extent = {{-100, -12}, {100, 12}}, textString = "EXP Growth", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Line(visible = true, origin = {63.558, -10.273}, rotation = -5.306, points = {{32.722, 10.515}, {13.878, -30.192}, {-15.693, -37.076}, {-32.22, -15.961}}, color = {0, 0, 128}, thickness = 2.5, arrowSize = 0, smooth = Smooth.Bezier), Line(visible = true, origin = {-42.154, -19.63}, rotation = 5.306, points = {{36.522, -45.771}, {36.663, -27.43}, {51.602, -8.364}}, color = {0, 0, 128}, thickness = 2.5, arrowSize = 0, smooth = Smooth.Bezier), Text(visible = true, origin = {6.087, -78}, textColor = {0, 0, 128}, extent = {{-81.281, -12}, {81.281, 12}}, textString = "fractional rate", fontName = "Lato", textStyle = {TextStyle.Bold}), Polygon(visible = true, origin = {31.134, -25.316}, rotation = 30, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, points = {{0, 9}, {5, -5}, {-5, -5}}), Polygon(visible = true, origin = {9.113, -25.409}, rotation = -30, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, points = {{0, 9}, {-5, -5}, {5, -5}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end ExponentialGrowth; diff --git a/BusinessSimulation/SourcesOrSinks/Growth.mo b/BusinessSimulation/SourcesOrSinks/Growth.mo new file mode 100644 index 0000000..adad9e9 --- /dev/null +++ b/BusinessSimulation/SourcesOrSinks/Growth.mo @@ -0,0 +1,33 @@ +within BusinessSimulation.SourcesOrSinks; + +model Growth "A stock is filled at a given rate" + import BusinessSimulation.Units.Rate; + extends Interfaces.Basics.GenericSourceOrSink; + extends Icons.Source; + Interfaces.Connectors.RealInput u if not hasConstantRate "Rate of growth given as exogenous input" annotation(Placement(visible = true, transformation(origin = {-140, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-50, 100}, extent = {{-10, 10}, {10, -10}}, rotation = 270))); + parameter OutputType rate = 0 "Constant rate of growth (optional)" annotation(Dialog(enable = hasConstantRate)); + parameter Boolean hasConstantRate = false "= true, if the constant rate is used instead of an exogenous input u" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); +protected + Converters.ConstantConverter parConstantRate(value = rate) if hasConstantRate "Constante rate of growth (optional)" annotation(Placement(visible = true, transformation(origin = {-110, 70}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Flows.Unidirectional.Transition growing(hasConstantRate = false) annotation(Placement(visible = true, transformation(origin = {0, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Cloud cloud annotation(Placement(visible = true, transformation(origin = {-50, 0}, extent = {{-10, 10}, {10, -10}}, rotation = 0))); +equation + connect(cloud.massPort, growing.portA) annotation(Line(visible = true, origin = {-25, 0}, points = {{-15, 0}, {15, 0}}, color = {128, 0, 128})); + connect(growing.portB, massPort) annotation(Line(visible = true, origin = {79.167, 0}, points = {{-69.167, 0}, {69.167, 0}}, color = {128, 0, 128})); + connect(growing.y, y1) annotation(Line(visible = true, origin = {56.667, 50.133}, points = {{-51.667, -39.733}, {-51.667, 19.867}, {103.333, 19.867}}, color = {0, 0, 127})); + connect(growing.y, y) annotation(Line(visible = true, origin = {56.667, 23.467}, points = {{-51.667, -13.067}, {-51.667, 6.533}, {103.333, 6.533}}, color = {0, 0, 127})); + connect(growing.y1, y2) annotation(Line(visible = true, origin = {-10.763, -28.5}, points = {{21.263, 23.5}, {30.763, 23.5}, {30.763, -21.5}, {170.763, -21.5}}, color = {0, 0, 127})); + connect(parConstantRate.y, growing.u) annotation(Line(visible = true, origin = {-38.333, 50}, points = {{-66.667, 20}, {33.333, 20}, {33.333, -40}}, color = {1, 37, 163})); + connect(u, growing.u) annotation(Line(visible = true, origin = {-50, 30}, points = {{-90, 10}, {45, 10}, {45, -20}}, color = {1, 37, 163})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Growth can be used to model an inflow to a stock from a source with infinite capacity outside the border of the system in focus. The rate of flow can either be set by the real input u (hasConstantRate = false) or by the parameter rate (hasConstantRate = true).

+

Notes

+ +

See also

+

DeclineExogenousChange 

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, 75}, textColor = {0, 128, 0}, extent = {{-100, -12}, {100, 12}}, textString = "Growth", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {14.095, -73.77}, textColor = {0, 0, 128}, extent = {{-34.095, -12}, {34.095, 12}}, textString = "rate", fontName = "Lato", textStyle = {TextStyle.Bold}), Line(visible = true, origin = {-22.154, -19.63}, rotation = 5.306, points = {{36.522, -45.771}, {43.438, -34.535}, {45.906, -7.964}}, color = {0, 0, 128}, thickness = 2.5, arrowSize = 0, smooth = Smooth.Bezier), Polygon(visible = true, origin = {24, -26.925}, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, points = {{0, 9}, {5, -5}, {-5, -5}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Growth; diff --git a/BusinessSimulation/SourcesOrSinks/LogisticGrowth.mo b/BusinessSimulation/SourcesOrSinks/LogisticGrowth.mo new file mode 100644 index 0000000..4d511bd --- /dev/null +++ b/BusinessSimulation/SourcesOrSinks/LogisticGrowth.mo @@ -0,0 +1,69 @@ +within BusinessSimulation.SourcesOrSinks; + +model LogisticGrowth "Logistic growth model" + extends Interfaces.Basics.GenericSourceOrSink; + extends Icons.Source; + import BusinessSimulation.Units.Rate; + Interfaces.Connectors.RealMultiInput u[2] if not hasConstantInputs "[1] maximum fractional growth rate [2] carrying capacity" annotation(Placement(visible = true, transformation(origin = {-145, -0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-50, 100}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + parameter OutputType r(min = 0) "Maximum fractional growth rate" annotation(Dialog(enable = hasConstantInputs)); + parameter Real K(min = 0) "Carrying capacity or maximum sustainable amount for the connected stock (>0)" annotation(Dialog(enable = hasConstantInputs)); + parameter Boolean isCCR = true "= true, if the maximum fractional rate given is assumed to be a continuously compounding rate else the rate will be converted" annotation(Dialog(group = "Structural Parameters")); + parameter Boolean hasConstantInputs = false "= true, if constant parameters aure to be used instead of the real inputs u[1] and u[2]" annotation(Dialog(group = "Structural Parameters")); +protected + Sensors.FlowPortSensor population "Current level of the connected stock" annotation(Placement(visible = true, transformation(origin = {120, 15}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Cloud cloud "System boundary" annotation(Placement(visible = true, transformation(origin = {-30, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Flows.Bidirectional.Switching growing "Process of logistic growth" annotation(Placement(visible = true, transformation(origin = {10, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Product_2 fractionalGrowthRate "Actual fractional rate of growth" annotation(Placement(visible = true, transformation(origin = {-5, 51.657}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.Division_Guarded relativePopulation(outputIfZero = 1) "Population as percentage of carrying capacity" annotation(Placement(visible = true, transformation(origin = {47.913, 95}, extent = {{-10, 10}, {10, -10}}, rotation = 540))); + Converters.Gap residualCapacity "Percentage of the carrying capacity left for growth" annotation(Placement(visible = true, transformation(origin = {10, 77.089}, extent = {{10, -10}, {-10, 10}}, rotation = 90))); + Converters.ConstantConverter one(value = 1) "100 percent" annotation(Placement(visible = true, transformation(origin = {-52.239, 90}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Product_2 growthRate "Rate of growth" annotation(Placement(visible = true, transformation(origin = {5, 22.515}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.ConstantConverter carryingCapacity(value = K) if hasConstantInputs "Constant carrying capacity (optional)" annotation(Placement(visible = true, transformation(origin = {-107.784, -35}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ConstantConverter maxFractionalGrowthRate(value = r) if hasConstantInputs "Constant maximum rate of growth (optional)" annotation(Placement(visible = true, transformation(origin = {-120, 65}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ForceOfInterest convertedRate if not isCCR "Discrete compounding rate being converted to CCR" annotation(Placement(visible = true, transformation(origin = {-90, 90}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.PassThrough identicalRate if isCCR "Use indicated rate if it is continuously compounding" annotation(Placement(visible = true, transformation(origin = {-90, 50}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +equation + assert(relativePopulation.u2 > 0, "Carrying capacity must be larger than zero"); + connect(population.flowPort, massPort) annotation(Line(visible = true, origin = {146.667, 10}, points = {{-26.667, 5}, {1.667, 5}, {1.667, -10}}, color = {128, 0, 128})); + connect(cloud.massPort, growing.portA) annotation(Line(visible = true, origin = {-10, 0}, points = {{-10, 0}, {10, 0}}, color = {128, 0, 128})); + connect(growing.y1, y2) annotation(Line(visible = true, origin = {65.125, -27.5}, points = {{-44.625, 22.5}, {-25.125, 22.5}, {-25.125, -22.5}, {94.875, -22.5}}, color = {1, 37, 163})); + connect(growing.y1, y) annotation(Line(visible = true, origin = {65.125, 12.5}, points = {{-44.625, -17.5}, {-25.125, -17.5}, {-25.125, 17.5}, {94.875, 17.5}}, color = {1, 37, 163})); + connect(growing.y1, y1) annotation(Line(visible = true, origin = {65.125, 32.5}, points = {{-44.625, -37.5}, {-25.125, -37.5}, {-25.125, 37.5}, {94.875, 37.5}}, color = {1, 37, 163})); + connect(growing.portB, massPort) annotation(Line(visible = true, origin = {90, 0}, points = {{-70, 0}, {70, 0}}, color = {128, 0, 128})); + connect(residualCapacity.y, fractionalGrowthRate.u1) annotation(Line(visible = true, origin = {5, 64.89}, points = {{5, 4.836}, {5, 0.199}, {-5, 0.199}, {-5, -5.234}}, color = {1, 37, 163})); + connect(relativePopulation.y, residualCapacity.u2) annotation(Line(visible = true, origin = {23.517, 91.696}, points = {{17.034, 3.304}, {-8.517, 3.304}, {-8.517, -6.607}}, color = {1, 37, 163})); + connect(one.y, residualCapacity.u1) annotation(Line(visible = true, origin = {-12.926, 88.363}, points = {{-35.852, 1.637}, {17.926, 1.637}, {17.926, -3.274}}, color = {1, 37, 163})); + connect(population.stock, relativePopulation.u1) annotation(Line(visible = true, origin = {98.67, 75.333}, points = {{21.379, -49.333}, {21.379, 24.667}, {-42.757, 24.667}}, color = {1, 37, 163})); + connect(fractionalGrowthRate.y, growthRate.u2) annotation(Line(visible = true, origin = {-2.5, 38.531}, points = {{-2.5, 5.764}, {-2.5, 1.126}, {2.5, 1.126}, {2.5, -8.015}}, color = {1, 37, 163})); + connect(population.stock, growthRate.u1) annotation(Line(visible = true, origin = {65.024, 36.629}, points = {{55.025, -10.629}, {55.025, 13.371}, {-55.024, 13.371}, {-55.024, -6.114}}, color = {1, 37, 163})); + connect(growthRate.y, growing.u) annotation(Line(visible = true, origin = {5, 12.576}, points = {{0, 2.576}, {0, -2.576}}, color = {1, 37, 163})); + connect(u[2], relativePopulation.u2) "Carrying capacity" annotation(Line(visible = true, origin = {-48.011, 8.75}, points = {{-96.989, -8.75}, {-91.989, -8.75}, {-91.989, -28.75}, {-31.989, -28.75}, {-31.989, -43.75}, {128.011, -43.75}, {128.011, 81.25}, {103.924, 81.25}}, color = {1, 37, 163})); + connect(carryingCapacity.y, relativePopulation.u2) annotation(Line(visible = true, origin = {26.094, 10.637}, points = {{-130.417, -45.637}, {-41.863, -45.637}, {53.906, -45.637}, {53.906, 79.363}, {29.819, 79.363}}, color = {1, 37, 163})); + connect(maxFractionalGrowthRate.y, convertedRate.u) annotation(Line(visible = true, origin = {-108.635, 77.5}, points = {{-7.904, -12.5}, {-1.365, -12.5}, {-1.365, 12.5}, {10.635, 12.5}}, color = {1, 37, 163})); + connect(convertedRate.y, fractionalGrowthRate.u2) annotation(Line(visible = true, origin = {-46.528, 75.931}, points = {{-36.11, 14.069}, {-18.472, 14.069}, {-18.472, -5.931}, {36.528, -5.931}, {36.528, -16.274}}, color = {1, 37, 163})); + connect(maxFractionalGrowthRate.y, identicalRate.u) annotation(Line(visible = true, origin = {-106.135, 57.5}, points = {{-10.404, 7.5}, {1.135, 7.5}, {1.135, -7.5}, {8.135, -7.5}}, color = {1, 37, 163})); + connect(identicalRate.y, fractionalGrowthRate.u2) annotation(Line(visible = true, origin = {-46.528, 59.931}, points = {{-36.11, -9.931}, {-18.472, -9.931}, {-18.472, 10.069}, {36.528, 10.069}, {36.528, -0.274}}, color = {1, 37, 163})); + connect(u[1], identicalRate.u) "Continuous input of maximum fractional growth rate" annotation(Line(visible = true, origin = {-117, 25}, points = {{-28, -25}, {12, -25}, {12, 25}, {19, 25}}, color = {1, 37, 163})); + connect(u[1], convertedRate.u) "Continuous input of fractional growth rate that needs to be converted" annotation(Line(visible = true, origin = {-117, 45}, points = {{-28, -45}, {12, -45}, {12, 45}, {19, 45}}, color = {1, 37, 163})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

LogisticGrowth describes the growth of some population that is limited by the availability of some finite resource. While the population starts to grow exponentially at first at a given fractional rate of growth (either given by the constant parameter r or by the time-variant input u[1]), its growth rate will continously diminish until the population reaches its sustainable level (either given by the constant parameter K or the time-variant input u[2]), which is called the carrying capacity.

+

The rate of inflow to a connected stock is given by the so called Verhulst equation:

+

\"dx/dt

+

 The diagram below shows the s-shaped growth for a population x for different rates of growth:

+ + + + + + +
LogisticGrowth for Different Rates r (x0 = 0.1)
\"Plot.svg\"
+

Notes

+ +

Acknowledgements

+

The logistic growth equation is originally due to the Belgian mathematican Pierre-François Verhulst (1804 - 1849).

+"), __Wolfram(itemFlippingEnabled = true), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, 75}, textColor = {0, 128, 0}, extent = {{-100, -12}, {100, 12}}, textString = "Logistic Growth", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {60, -80}, textColor = {0, 0, 128}, extent = {{-16.681, -12}, {16.681, 12}}, textString = "K", fontName = "Lato", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {-40, -68.863}, textColor = {0, 0, 128}, extent = {{-5.153, -12}, {5.153, 12}}, textString = "r", fontName = "Lato", textStyle = {TextStyle.Bold}), Line(visible = true, origin = {63.558, -10.273}, rotation = -5.306, points = {{32.722, 10.515}, {13.878, -30.192}, {-15.693, -37.076}, {-32.22, -15.961}}, color = {0, 0, 128}, thickness = 2.5, arrowSize = 0, smooth = Smooth.Bezier), Line(visible = true, origin = {-42.154, -19.63}, rotation = 5.306, points = {{9.831, -44.191}, {31.025, -33.382}, {47.07, -12.788}}, color = {0, 0, 128}, thickness = 2.5, arrowSize = 0, smooth = Smooth.Bezier), Polygon(visible = true, origin = {31.134, -25.316}, rotation = 30, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, points = {{0, 9}, {5, -5}, {-5, -5}}), Polygon(visible = true, origin = {5.5, -27.794}, rotation = -30, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, points = {{0, 9}, {-5, -5}, {5, -5}}), Line(visible = true, origin = {-31.891, -23.609}, points = {{77.861, -51.711}, {56.151, -35.748}, {51.602, -8.364}}, color = {0, 0, 128}, thickness = 2.5, arrowSize = 0, smooth = Smooth.Bezier), Polygon(visible = true, origin = {20, -29}, lineColor = {0, 0, 128}, fillColor = {0, 0, 128}, fillPattern = FillPattern.Solid, points = {{0, 9}, {-5, -5}, {5, -5}})})); +end LogisticGrowth; diff --git a/BusinessSimulation/SourcesOrSinks/package.mo b/BusinessSimulation/SourcesOrSinks/package.mo new file mode 100644 index 0000000..d43225b --- /dev/null +++ b/BusinessSimulation/SourcesOrSinks/package.mo @@ -0,0 +1,38 @@ +within BusinessSimulation; + +package SourcesOrSinks "Flows into or out of a stock with infinite capacity at a system's boundary" + extends Icons.Package; + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, origin = {72.114, -0.25}, rotation = -450, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-22.295, -7.943}, {22.191, -7.943}, {0.104, 15.886}}), Line(visible = true, origin = {27.342, -10}, points = {{-39.852, 0}, {39.852, 0}}, color = {255, 255, 255}, thickness = 5), Line(visible = true, origin = {28.79, 11.777}, points = {{-41.21, 0}, {41.21, 0}}, color = {255, 255, 255}, thickness = 5), Rectangle(visible = true, origin = {-51.38, -0.345}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-38.62, -38.62}, {38.62, 38.62}}), Ellipse(visible = true, origin = {28.899, 0}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 5, extent = {{-15.107, -15.107}, {15.107, 15.107}}), Line(visible = true, origin = {-54.639, -1.132}, points = {{-19.013, -1.251}, {-19.013, 5.61}, {-13.146, 10.097}, {-4.518, 6.3}, {3.107, -1.637}, {9.976, -6.855}, {16.533, -6.855}, {19.639, -3.018}, {19.639, 4.92}, {13.107, 11.132}, {6.525, 8.716}, {3.107, 3.145}, {-4.173, -6.855}, {-14.872, -8.539}, {-19.013, -1.251}, {-19.013, -1.251}}, color = {76, 112, 136}, thickness = 4, smooth = Smooth.Bezier), Bitmap(visible = true, origin = {149.207, -5.816}, fileName = "", imageSource = "iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAACXBIWXMAAAsTAAALEwEAmpwYAAAABGdBTUEAALGeYUxB9wAAACBjSFJNAAB6JQAAgIMAAPn/AACA6AAAUggAARVYAAA6lwAAF2/XWh+QAAAB7klEQVR42mJsufTiPwMZACCAWP5//4Fd4tcnBsndRQzyn/aA+Q/5XBieu/Yx/GHjA/MBAojl3zfsGmWOlDHo/N7DoKEA4Qu83MPAfKCM4Z7NBDAfIIBY/uKwUebtDrAmDlYIX0OcgeHDgx0Mt6HqAQKI5Q8OjbgATD1AALH8xuHUJ8IeDDde7gDbBAI3XkLEYOoBAojlF5Dx69dvhrev34MFePm4GXh4uRkuCqcw/P39B+g8ROBcAYrBNAIEEMuXT18Y3rx6z2Ctp8hgoCbNMHfTcYY/QIM4uTgYTgjlgDEc/AIREI0AAcTy+uU7BjtDZYZkP0uGn7/+MOSFOzBMXHGA4dfP3wzs7KwM////Z/j06SvDnz9/wRp4eLjA4gABxGRvpMKQEWjN8PfvPzCWEOJjSAPyQbZ+/vyN4cOHLwwC3BwMsV5mDN7W2gw/f/wEiwMEEOOPn7///wDa9PP3bwYwDcQg+tGLdwwLt55kYGVlYQhxNADb9gNo2Kt3nxkOXbjLABBATH/+AW0C4j9QG2G0iAAPQ5iLETDg/jDce/oGIg5Ux83FzmCqJccAEEBMCMX/Ic5FMkiIj4vBz06X4fiVBwwPnr+Fe4eLnY0BIIBYYDaAFf/7B5f8CzVMgJeTwcdGG+yFPyDDoeoAAgwAAiQQgeLRB5kAAAAASUVORK5CYII=", extent = {{-0.793, -0.07}, {0.793, 0.07}})}), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This pacakge contains sources or sinks with regard to the flow of conserved matter or information (\"mass flows\"). While in the narrow sense only a cloud (i.e. a stock with infinite capacity) is a source or sink, in this library we will extend the definition of a source or sink to also pertain to inflows from or outflows into a stock with infinite capacity, e.g. the cloud will be integrated into a flow element with a single flow port.

+

Notes

+

The direction of flow will not always be clear for SourcesOrSinks elements. For a constant or an exogenous input given the rate of flow these sign conventions are to be observed:

+ + + + + + + + + + + + + + + + + + + +
ElementBehavior for positive rate
SinkDRAIN connected stock
SourceFILL connected stock
SourceOrSinkFILL connected stock
+

See also

+

+Tutorial.ElementaryBuildingBlocks +

+
+
+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+"), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end SourcesOrSinks; diff --git a/BusinessSimulation/SourcesOrSinks/package.order b/BusinessSimulation/SourcesOrSinks/package.order new file mode 100644 index 0000000..146f013 --- /dev/null +++ b/BusinessSimulation/SourcesOrSinks/package.order @@ -0,0 +1,9 @@ +Cloud +Decline +ExogenousChange +ExponentialChange +ExponentialDecay +ExponentialDecline +ExponentialGrowth +Growth +LogisticGrowth diff --git a/BusinessSimulation/Stocks/CapacityRestrictedStock.mo b/BusinessSimulation/Stocks/CapacityRestrictedStock.mo new file mode 100644 index 0000000..70cff90 --- /dev/null +++ b/BusinessSimulation/Stocks/CapacityRestrictedStock.mo @@ -0,0 +1,78 @@ +within BusinessSimulation.Stocks; + +model CapacityRestrictedStock "Material stock, that cannot be drained or filled beyond its capacity limits" + import BusinessSimulation.Constants.{small,zero}; + import BusinessSimulation.Types.InitializationOptions; + extends Interfaces.PartialStocks.BasicStock(initialValue(min = 0), minValue(min = zero) = zero, useAssert = false); + extends Icons.MaterialStockIndicator; + extends Icons.CapacityLabel; + Interfaces.Connectors.RealInput u_min if hasVariableAdmissableRange "Variable minimum value to be monitored" annotation(Placement(visible = true, transformation(origin = {-145, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-50, 100}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Interfaces.Connectors.RealInput u_max if hasVariableAdmissableRange "Maximum value input" annotation(Placement(visible = true, transformation(origin = {-145, 70}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {0, 100}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + parameter Boolean hasVariableAdmissableRange = false "=true, if capacity restrictions are to be given by the variable inputs u_min and u_max" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean reinitializeStock = false "= true, if the stock is to be reinitalized to guarante nonnegativity" annotation(Evaluate = true, Dialog(tab = "Advanced")); +protected + Converters.Special.VariableRangeAssert variableRangeControl(causeError = causeError) if useAssert and hasVariableAdmissableRange "Use assert() to check admissable values" annotation(Placement(visible = true, transformation(origin = {-50, 65}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + OutputType minCapacity = if hasVariableAdmissableRange then u_min else minValue "Minimum capacity"; + OutputType maxCapacity = if hasVariableAdmissableRange then u_max else maxValue "Maximum capacity"; +initial equation + // properly initialize discrete vars with fixed = false + // provide Boolean signal when above capacity + pre(inflow.stopInflow) = not x < maxCapacity - BusinessSimulation.Constants.small; + pre(outflow.stopInflow) = inflow.stopInflow; + // provide Boolean signal when below capacity + pre(inflow.stopOutflow) = not x > minCapacity + BusinessSimulation.Constants.small; + pre(outflow.stopOutflow) = pre(inflow.stopOutflow); +equation + // provide Boolean signal when above capacity + inflow.stopInflow = not x < maxCapacity - BusinessSimulation.Constants.small; + outflow.stopInflow = inflow.stopInflow; + // provide Boolean signal when below capacity + inflow.stopOutflow = not x > minCapacity + BusinessSimulation.Constants.small; + outflow.stopOutflow = inflow.stopOutflow; + // optional reinitialize stock to zero if negative // + if reinitializeStock then + when x < 0 then + reinit(x, 0); + end when; + end if; + assert(minCapacity < maxCapacity, "Minimum capacity must be smaller than maximum capacity"); + connect(y1, variableRangeControl.u) annotation(Line(visible = true, origin = {20.4, 74}, points = {{139.6, -4}, {139.6, 11}, {-100.4, 11}, {-100.4, -9}, {-78.4, -9}}, color = {1, 37, 163})); + connect(u_max, variableRangeControl.u_max) annotation(Line(visible = true, origin = {-101.5, 70}, points = {{-43.5, 0}, {43.5, 0}}, color = {0, 0, 128})); + connect(u_min, variableRangeControl.u_min) annotation(Line(visible = true, origin = {-110.313, 50}, points = {{-34.687, -10}, {10.313, -10}, {10.313, 10}, {52.313, 10}}, color = {0, 0, 128})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This is a restricted reservoir of the System Dynamics methodology, which accumulates material  (i.e. countable entities, some kind of mass) transported by flow components connected to the component's StockPorts. Like a MaterialStock the CapacityRestrictedStock can never become negative—we are not collecting \"antimatter\"—and will prevent connected flow components from draining its value below zero. Unlike other stocks, minCapacity and maxCapacity are seen as capacity restrictions that for \"physical\" reasons cannot be violated—the restrictions can be given as either constant parameters (minValue, maxValue) or as variable inputs (u_min, u_max). Accordingly, the component will signal flow restrictions via its port that must be observed by connected flow components.

+

Implementation

+

The value of the stock will be set to zero if the calculated value x is less than a very small positive amount and if reinitializeStock = true is chosen in the Advanced tab:

+
  if reinitializeStock then
+    when x < 0 then
+      reinit(x, 0);
+    end when;
+  end if;
+

CapacityRestrictedStock components will prevent connected flows from draining the stock via their →StockPort connectors' Boolean flags, should the calculated state variable x be less than a very small positive amount:

+
+
  inflow.stopInflow = not x < maxCapacity - BusinessSimulation.Constants.small;
+  outflow.stopInflow = inflow.stopInflow;

+
  inflow.stopOutflow = not x > minCapacity + BusinessSimulation.Constants.small;
+  outflow.stopOutflow = inflow.stopOutflow;

+

Notes

+ + + +

See also

+

MaterialStockInformationLevel

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, origin = {-80.87, 0}, lineColor = {192, 192, 192}, fillColor = {192, 192, 192}, fillPattern = FillPattern.Solid, points = {{-2.435, 13.229}, {-2.435, -13.344}, {4.87, 0.115}}), Polygon(visible = true, origin = {-70.87, 0}, lineColor = {192, 192, 192}, fillColor = {192, 192, 192}, fillPattern = FillPattern.Solid, points = {{-2.435, 13.229}, {-2.435, -13.344}, {4.87, 0.115}}), Polygon(visible = true, origin = {70.439, 0}, lineColor = {192, 192, 192}, fillColor = {192, 192, 192}, fillPattern = FillPattern.Solid, points = {{-2.435, 13.229}, {-2.435, -13.344}, {4.87, 0.115}}), Polygon(visible = true, origin = {80.439, 0}, lineColor = {192, 192, 192}, fillColor = {192, 192, 192}, fillPattern = FillPattern.Solid, points = {{-2.435, 13.229}, {-2.435, -13.344}, {4.87, 0.115}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end CapacityRestrictedStock; diff --git a/BusinessSimulation/Stocks/Conveyor.mo b/BusinessSimulation/Stocks/Conveyor.mo new file mode 100644 index 0000000..19d9a4a --- /dev/null +++ b/BusinessSimulation/Stocks/Conveyor.mo @@ -0,0 +1,150 @@ +within BusinessSimulation.Stocks; + +model Conveyor "Conveyor delay (aka pipeline ~) with variable delay time" + import BusinessSimulation.Types.InitializationOptions; + import BusinessSimulation.Units.{Rate,Time}; + import BusinessSimulation.Constants.small; + extends Icons.Conveyor; + extends Icons.DiscreteStockLabel; + extends Interfaces.Basics.GenericStock_Special(hasStockInfoOutput = false, init = modelSettings.init); + Interfaces.Connectors.RealInput u(quantity = "Time") if not hasConstantDelayTime "Delay time input (optional)" annotation(Placement(visible = true, transformation(origin = {-145, 60}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-50, 100}, extent = {{-10, 10}, {10, -10}}, rotation = 270))); + parameter OutputType initialValue(min = 0) = 0 "Initial load"; + parameter Time delayTime(min = 0, max = maxDelayTime) "Constant delay time (optional)" annotation(Dialog(enable = hasConstantDelayTime)); + parameter Time maxDelayTime(min = 0) = 10 "Maximum delay time (to restrict memory usage)" annotation(Evaluate = true); + parameter Time samplingPeriod(min = small, max = modelSettings.dt) = modelSettings.samplingPeriod "Sampling period for discrete behavior (should be smaller than dt/2)" annotation(Evaluate = true, Dialog(tab = "Advanced")); + parameter Boolean hasConstantDelayTime = true "= true, if the delay time is to be given by a constant parameter" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean hasExogenousHistory = false "=true, if the outflow-profile for the initial load is to be given by an external lookup function" annotation(Evaluate = true, Dialog(enable = false, group = "Structural Parameters")); + parameter Boolean strict = true "= true, if strict limits with noEvent(..) (clippedDelayTime.strict)" annotation(Evaluate = true, Dialog(tab = "Advanced")); + outer ModelSettings modelSettings; +protected + parameter Integer n = integer(ceil(maxDelayTime / samplingPeriod)) "Array dimensions for storing the loaded material" annotation(Evaluate = true, Dialog(tab = "Initialization", enable = false)); + // discrete vars + discrete Rate[n] conveyor "Storage boxes for the incoming rates"; + discrete OutputType load(start = initialValue) "Sum of material in the conveyor" annotation(Dialog(enable = false, tab = "Initialization")); + discrete Rate carry "Material that is leaving the conveyor prematurely due to decreases in delay time"; + discrete Time actDelayTime "Actual delay time"; + discrete Rate currentInflowRate "Rate of flow at current time"; + discrete Rate rateToStore "Average rate to store in the conveyor"; + discrete Rate outflowRate "Rate of outflow from the conveyor"; + discrete Integer i_start "Index of the first box corresponding to the actual delay time"; + discrete Integer shiftIndex "Positive or negative index difference due to changes in delay time"; + // components + Converters.ConstantConverterTime parDelayTime(value = delayTime) if hasConstantDelayTime "Constant delay time" annotation(Placement(visible = true, transformation(origin = {-120, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.Clip clippedDelayTime(minValue = modelSettings.dt, maxValue = maxDelayTime, strict = strict) "Valid delay time to use" annotation(Placement(visible = true, transformation(origin = {-80, 60}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Sensors.DynamicStockInfo dynamicStockInfo if hasStockInfoOutput "Report infos for StockInfoPort" annotation(Placement(visible = true, transformation(origin = {0, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +initial equation + // properly initialize discrete vars with fixed = false + pre(inflow.stopInflow) = false; + pre(inflow.stopOutflow) = true; +initial algorithm + // initialize the conveyor + conveyor := zeros(n); + currentInflowRate := inflow.rate; + actDelayTime := clippedDelayTime.y; + // determine the initial load + if init == InitializationOptions.FixedValue then + load := initialValue; + elseif init == InitializationOptions.SteadyState then + // use Little's Law + load := actDelayTime * currentInflowRate; + end if; + // calculate the start index for storing the initial rates (may be larger than n, if delay time is zero) + i_start := n - integer(ceil(actDelayTime / samplingPeriod)) + 1; + rateToStore := if actDelayTime > 0 then load / (n - i_start + 1) / samplingPeriod else load / samplingPeriod; + // as in the PureDelay the last package goes out immediately so one box less needed for storing + for i in i_start + 1:n loop + if not hasExogenousHistory then + // constant value + conveyor[i] := rateToStore; + else + /* + use initial load profile in future versions + conveyor[i] := initialLoad.y[i] / samplingPeriod; + */ + conveyor[i] := rateToStore; + end if; + end for; + // if the delay time is zero then the currentInflowRate should be added to the outflowRate + outflowRate := rateToStore; + if i_start > n then + outflowRate := outflowRate + currentInflowRate; + else + // store inflowRate + conveyor[i_start] := currentInflowRate; + end if; + shiftIndex := 0; + carry := 0; +algorithm + // series of events starting at modelStartTime + samplingPeriod then every samplingPeriod + when sample(modelSettings.modelStartTime + samplingPeriod, samplingPeriod) then + // get current values + actDelayTime := clippedDelayTime.y; + currentInflowRate := inflow.rate; + // set rateToStore in order to have equations balance out + rateToStore := 0; + // check for a change in delay time + i_start := n - integer(ceil(actDelayTime / samplingPeriod)) + 1; + shiftIndex := i_start - pre(i_start); + // shift conveyor +1 for sampling time having passed and and additional +shiftIndex for chane of delay time + (conveyor, carry) := Functions.shiftList(conveyor, shiftIndex + 1); + outflowRate := carry; + // load must count current outflow rate + load := (sum(conveyor) + outflowRate) * samplingPeriod; + // put inflowRate on the conveyor belt + if i_start > n then + outflowRate := outflowRate + currentInflowRate; + else + conveyor[i_start] := conveyor[i_start] + currentInflowRate; + // conveyor[i_start] should be zero + end if; + end when; +equation + // textual equations + inflow.stopInflow = false; + inflow.stopOutflow = true; + inflow.stock = load; + outflow.data = outflowRate; + // report current load + y = inflow.stock; + y1 = inflow.stock; + y2 = inflow.stock; + // connect equations + connect(u, clippedDelayTime.u) annotation(Line(visible = true, origin = {-116.5, 60}, points = {{-28.5, 0}, {28.5, 0}}, color = {1, 37, 163})); + connect(parDelayTime.y, clippedDelayTime.u) annotation(Line(visible = true, origin = {-100.75, 50}, points = {{-13.25, -10}, {0.75, -10}, {0.75, 10}, {12.75, 10}}, color = {1, 37, 163})); + connect(inflow, dynamicStockInfo.inPort) annotation(Line(visible = true, origin = {-83, 0}, points = {{-77, 0}, {77, 0}}, color = {128, 0, 128})); + connect(dynamicStockInfo.outPort, outflow) annotation(Line(visible = true, origin = {83, 0}, points = {{-77, 0}, {77, 0}}, color = {128, 0, 128})); + connect(dynamicStockInfo.y_stockInfo, y_stockInfo) annotation(Line(visible = true, origin = {64, -24.8}, points = {{-64, 30.8}, {-64, 39.8}, {16, 39.8}, {16, -55.2}, {86, -55.2}}, color = {128, 0, 128})); + connect(y2, dynamicStockInfo.levelInfo) annotation(Line(visible = true, origin = {80, -37.772}, points = {{80, -12.228}, {80, -12.228}, {-80, -12.228}, {-80, 31.772}}, color = {1, 37, 163})); + connect(clippedDelayTime.y, dynamicStockInfo.residenceTimeInfo) annotation(Line(visible = true, origin = {-28.4, 14.8}, points = {{-43.6, 45.2}, {-11.6, 45.2}, {-11.6, -34.8}, {33.4, -34.8}, {33.4, -20.8}}, color = {1, 37, 163})); + // assert equations + assert(samplingPeriod < modelSettings.dt, "Sampling period should be significantly smaller than dt", level = AssertionLevel.warning); + assert(samplingPeriod > small, "Sampling period must be greater than zero", level = AssertionLevel.error); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The Conveyor (aka pipeline delay) bevhaves as one would expect a conveyor belt to work: What flows into the Conveyor will flow out after a period given by delayTime or the variable input u has passed. The order of outflow will preserve the order of inflow, i.e. when the delay time increases or decreases during the simulation, then it will affect everything that is currently \"loaded\" on the conveyor in the same way. Therefore, material might come out at the same time as material that had entered before, but it can never overtake older entries (this would be possible in a PureDelay).

+

Implementation

+

The Conveyor  will work at discrete time intervals:

+
when sample(modelSettings.modelStartTime + samplingPeriod, samplingPeriod) then
+  // load new material onto conveyor, move loaded material, unload material
+end when;
+
+

The values for the in- and outflows and the load will be kept constant between events.

+

Notes

+ +

See also

+

SimpleConveyorPureDelay, DelayFixedDelayInformation

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, -80}, textColor = {0, 0, 128}, extent = {{-100, -6}, {100, 6}}, textString = "%initialValue", fontName = "Lato")}), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 140}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Conveyor; diff --git a/BusinessSimulation/Stocks/DelayN.mo b/BusinessSimulation/Stocks/DelayN.mo new file mode 100644 index 0000000..954999f --- /dev/null +++ b/BusinessSimulation/Stocks/DelayN.mo @@ -0,0 +1,85 @@ +within BusinessSimulation.Stocks; + +model DelayN "Material delay of n-th Order" + import BusinessSimulation.Types.InitializationOptions; + import BusinessSimulation.Units.Time; + extends Icons.DelayN; + extends Interfaces.Basics.GenericStock_Special(hasStockInfoOutput = false, init = modelSettings.init); + Interfaces.Connectors.RealInput u(quantity = "Time", unit = "s") if not hasConstantDelayTime "Delay time input (optional)" annotation(Placement(visible = true, transformation(origin = {-145, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-50, 100}, extent = {{10, 10}, {-10, -10}}, rotation = -270))); + parameter Integer n(min = 1) = 3 "Order of the exponential delay" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter OutputType initialValue(min = 0) = 0 "Initial stock"; + parameter Time delayTime(min = BusinessSimulation.Constants.small) = 1 "Constant time of delay (optional)" annotation(Dialog(enable = hasConstantDelayTime)); + parameter Boolean hasConstantDelayTime = true "= true, if DelayTime is to be set by a constant parameter" annotation(Dialog(group = "Structural Parameters")); + outer ModelSettings modelSettings; +protected + OutputType x(min = 0) "Total material in the stock"; + OutputType[n] x_hidden(each start = initialValue / n) "Hidden (internal) stocks" annotation(Dialog(enable = false, tab = "Initialization")); + Time stageDelayTime "Delay-time for the transition from internal stock_i to internal stock_i+1"; + Sensors.DynamicStockInfo dynamicStockInfo if hasStockInfoOutput "Generate information for StockInfoOutput" annotation(Placement(visible = true, transformation(origin = {-0, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ConstantConverterTime parDelayTime(value = delayTime) if hasConstantDelayTime "Constant delay time (optional)" annotation(Placement(visible = true, transformation(origin = {-110, 30}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ClipProcessTime actualDelayTime "Delay time" annotation(Placement(visible = true, transformation(origin = {-68.47, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +initial equation + // set up in steady state or use fixed value + if init == InitializationOptions.FixedValue then + x_hidden[1:n] = array(initialValue / n for i in 1:n); + elseif init == InitializationOptions.SteadyState then + // make use of Little's Law + x_hidden[1:n] = array(inflow.rate * (actualDelayTime.y / n) for i in 1:n); + end if; + // properly initialize discrete vars with fixed = false + // inflow to stock is restricted to inflow port; no draining allowed + pre(inflow.stopInflow) = false; + pre(inflow.stopOutflow) = true; +equation + stageDelayTime = actualDelayTime.y / n; + // equations for the n hidden 'in-transit' stocks + der(x_hidden[1]) = inflow.rate - x_hidden[1] / stageDelayTime; + for i in 2:n loop + der(x_hidden[i]) = (x_hidden[i - 1] - x_hidden[i]) / stageDelayTime; + end for; + // total material in transit + x = sum(x_hidden); + // DelayN will signal outflow rate at its outflow-side via SpecialFlowPort + outflow.data = x_hidden[end] / stageDelayTime; + // set the inflow.stock value + inflow.stock = x; + // inflow to stock is restricted to inflow port; no draining allowed + inflow.stopInflow = false; + inflow.stopOutflow = true; + // report current value of stock via output connectors + y = inflow.stock; + y1 = inflow.stock; + y2 = inflow.stock; + // connect equations for StockInformationPort (conditional) + connect(inflow, dynamicStockInfo.inPort) annotation(Line(visible = true, origin = {-83, 0}, points = {{-77, 0}, {77, 0}}, color = {128, 0, 128})); + connect(dynamicStockInfo.outPort, outflow) annotation(Line(visible = true, origin = {83, 0}, points = {{-77, 0}, {77, 0}}, color = {128, 0, 128})); + connect(y2, dynamicStockInfo.levelInfo) annotation(Line(visible = true, origin = {53.333, -35.333}, points = {{106.667, -14.667}, {-53.333, -14.667}, {-53.333, 29.333}}, color = {1, 37, 163})); + connect(parDelayTime.y, actualDelayTime.u) annotation(Line(visible = true, origin = {-92.618, 35}, points = {{-11.382, -5}, {-2.382, -5}, {-2.382, 5}, {16.148, 5}}, color = {1, 37, 163})); + connect(actualDelayTime.y, dynamicStockInfo.residenceTimeInfo) annotation(Line(visible = true, origin = {-21.118, 6.8}, points = {{-39.99, 33.2}, {-6.123, 33.2}, {-6.123, -26.8}, {26.118, -26.8}, {26.118, -12.8}}, color = {1, 37, 163})); + connect(dynamicStockInfo.y_stockInfo, y_stockInfo) annotation(Line(visible = true, origin = {56, -24.8}, points = {{-56, 30.8}, {-56, 39.8}, {4, 39.8}, {4, -55.2}, {94, -55.2}}, color = {128, 0, 128})); + connect(u, actualDelayTime.u) annotation(Line(visible = true, origin = {-110.735, 40}, points = {{-34.265, 0}, {34.265, 0}}, color = {1, 37, 163})); + // assert + assert(n > 0, "Order of the delay must be at least 1"); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The DelayN is a →MaterialStock with inherent dynamic behavior that will result in a delay—which may have a constant (delayTime) or a variable delay time (u). Internally a material delay of order n is made up of a sequence of n first-order delays (→Decay ) each having a delay time of delayTime/n.

+

To better grasp the behavior of a DelayN, it helps to be aware of the fact, that given a single pulse input (e.g. a Dirac delta function) as inflow to a DelayN with constant delay time, its outflow will correspond to an Exponential distribution for n = 1 and more generally to an Erlang distribution of order k = n for n ≥ 1. In other words, the time of residence within the stock is distributed according to an Erlang distribution with the mean residence time corresponding to the delay time and a diminishing variance as n increases—in the limit, as n approaches infinity, the DelayN will be equivalent to the →PureDelay (aka pipeline delay). For more detail, see Sterman [3, Chapter 11].

+

Notes

+ + + +

See also

+

MaterialStock, PureDelay, Converters.DiscreteDelay

+"), __Wolfram(itemFlippingEnabled = true), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {62.999, 75}, textColor = {255, 0, 0}, extent = {{-24.503, -12}, {24.503, 12}}, textString = "%n", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {0, -80}, textColor = {0, 0, 128}, extent = {{-100, -6}, {100, 6}}, textString = "%initialValue", fontName = "Lato"), Text(visible = true, origin = {0, 75}, textColor = {255, 0, 0}, extent = {{-50, -12}, {50, 12}}, textString = "Delay", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end DelayN; diff --git a/BusinessSimulation/Stocks/HinesCoflow.mo b/BusinessSimulation/Stocks/HinesCoflow.mo new file mode 100644 index 0000000..75890fc --- /dev/null +++ b/BusinessSimulation/Stocks/HinesCoflow.mo @@ -0,0 +1,48 @@ +within BusinessSimulation.Stocks; + +model HinesCoflow "Accounting for changes in average quality of a stock as new entries with different characteristic flow in" + extends Interfaces.Basics.GenericStock(hasStockInfoOutput = false, y.start = initialValue); + extends Icons.Stock; + extends Icons.FlowIndicators; + Interfaces.Connectors.StockInfoInput u_stockInfo "Stock information input port" annotation(Placement(visible = true, transformation(origin = {-145, 90}, extent = {{-10, -10}, {10, 10}}, rotation = -360), iconTransformation(origin = {0, 100}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Interfaces.Connectors.RealInput u "Characteristic of new elements flowing into the stock of fundamental quality" annotation(Placement(visible = true, transformation(origin = {-145, 45}, extent = {{10, -10}, {-10, 10}}, rotation = -540), iconTransformation(origin = {-50, 100}, extent = {{-10, 10}, {10, -10}}, rotation = -90))); + parameter OutputType initialValue = 0 "Initial value for average characteristic"; +protected + InformationLevel avgCharacteristic(redeclare final type OutputType = OutputType, initialValue = initialValue) "Average characteristic" annotation(Placement(visible = true, transformation(origin = {50, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + SourcesOrSinks.ExogenousChange changing "Change in the average characteristic" annotation(Placement(visible = true, transformation(origin = {10, 20}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + MoleculesOfStructure.Policy.CloseGap rateOfChange(hasConstantAdjTime = false) "Rate of change is given as a first-order smooth" annotation(Placement(visible = true, transformation(origin = {-10, 45}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + MoleculesOfStructure.InformationProcessing.ResidenceTime dilutionTime(durationAtZeroRate = 0) "Time to dilute the average characteristic" annotation(Placement(visible = true, transformation(origin = {-50, 20}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Sensors.AbsoluteSensor absoluteSensor annotation(Placement(visible = true, transformation(origin = {-110, 37.865}, extent = {{10, -10}, {-10, 10}}, rotation = 180))); +equation + connect(avgCharacteristic.y, y) annotation(Line(visible = true, origin = {90, 23.467}, points = {{-35, -13.067}, {-35, 6.533}, {70, 6.533}}, color = {0, 0, 127})); + connect(avgCharacteristic.y, y1) annotation(Line(visible = true, origin = {90, 50.133}, points = {{-35, -39.733}, {-35, 19.867}, {70, 19.867}}, color = {0, 0, 127})); + connect(avgCharacteristic.y1, y2) annotation(Line(visible = true, origin = {69.237, -28.5}, points = {{-8.737, 23.5}, {30.763, 23.5}, {30.763, -21.5}, {90.763, -21.5}}, color = {0, 0, 127})); + connect(outflow, avgCharacteristic.outflow) annotation(Line(visible = true, origin = {104.232, 0}, points = {{44.232, 0}, {-44.232, 0}}, color = {128, 0, 128})); + connect(inflow, avgCharacteristic.inflow) annotation(Line(visible = true, origin = {-50, -8.333}, points = {{-98.205, 8.333}, {-70, 8.333}, {80, 8.333}, {90, 8.333}}, color = {128, 0, 128})); + connect(changing.massPort, avgCharacteristic.inflow) annotation(Line(visible = true, origin = {34.275, 10}, points = {{-14.275, 10}, {-1.625, 10}, {-1.625, -10}, {5.725, -10}}, color = {128, 0, 128})); + connect(u_stockInfo, absoluteSensor.u_stockInfo) annotation(Line(visible = true, origin = {-60, 88.5}, points = {{-85, 1.5}, {-85, 1.5}, {-50, 1.5}, {-50, -46.635}}, color = {128, 0, 128})); + connect(absoluteSensor.stock, dilutionTime.u_level) annotation(Line(visible = true, origin = {-96.961, 27.955}, points = {{-17.991, 5.91}, {-17.991, -2.955}, {35.981, -2.955}}, color = {1, 37, 163})); + connect(u_stockInfo, y_stockInfo) annotation(Line(visible = true, origin = {64, 21}, points = {{-209, 69}, {16, 69}, {16, -101}, {86, -101}}, color = {128, 0, 128})); + connect(dilutionTime.y, rateOfChange.u_adjTime) annotation(Line(visible = true, origin = {-28.38, 37.884}, points = {{-10.362, -17.884}, {-1.62, -17.884}, {-1.62, 2.116}, {7.38, 2.116}}, color = {0, 0, 127})); + connect(rateOfChange.y, changing.u) annotation(Line(visible = true, origin = {3.667, 40}, points = {{-2.667, 5}, {1.333, 5}, {1.333, -10}}, color = {1, 37, 163})); + connect(u, rateOfChange.u_reference) annotation(Line(visible = true, origin = {-59, 52.5}, points = {{-86, -7.5}, {24, -7.5}, {24, -7.5}, {38, -7.5}}, color = {0, 0, 128})); + connect(avgCharacteristic.y, rateOfChange.u_current) annotation(Line(visible = true, origin = {22.5, 49.1}, points = {{32.5, -38.7}, {32.5, 15.9}, {-32.5, 15.9}, {-32.5, 6.9}}, color = {1, 37, 163})); + connect(absoluteSensor.inFlow, dilutionTime.u_rate) annotation(Line(visible = true, origin = {-107.342, 24.433}, points = {{-12.658, 9.432}, {-12.658, -9.433}, {46.319, -9.433}}, color = {1, 37, 163})); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The HinesCoflow is a modification of the classical coflow structure used in System Dynamics [6, pp. 50f.]. The traditional coflow is a model of a stock's average quality (e.g. age, weight, price, income etc.) changing, as new entities with different characteristics u flow in while older entities flow out—in which case we assume, that the outflowing entities have an average quality [3, pp. 497-511].

+

The HinesCoflow makes use of the fact, that the average quality of the entities in the stock is diluted by inflowing entities of different quality, i.e. the process is a smooth with a variable time constant. The benefit of this formulation is, that the average quality of the stock is directly modeled by a stock, so that processes that change the average (e.g. gaining experience over the time of residence for a stock of workers) can be directly modeled as in- or outflows to the HinesCoflow.

+

Notes

+ + +

Acknowledgements

+

The Hines Coflow is explicitly named after its creator, James Hines. More information can be found on his website.

+

See also

+

InformationLevel 

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, 75}, textColor = {255, 0, 0}, extent = {{-100, -12}, {100, 12}}, textString = "Mean Quality", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Text(visible = true, origin = {0, -80}, textColor = {0, 0, 128}, extent = {{-100, -6}, {100, 6}}, textString = "%initialValue", fontName = "Lato")}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end HinesCoflow; diff --git a/BusinessSimulation/Stocks/InformationLevel.mo b/BusinessSimulation/Stocks/InformationLevel.mo new file mode 100644 index 0000000..88f9079 --- /dev/null +++ b/BusinessSimulation/Stocks/InformationLevel.mo @@ -0,0 +1,39 @@ +within BusinessSimulation.Stocks; + +model InformationLevel "Unrestricted reservoir to store information" + extends Interfaces.PartialStocks.BasicStock; + import BusinessSimulation.Types.InitializationOptions; +initial equation + // properly initialize discrete vars with fixed = false + pre(inflow.stopInflow) = false; + pre(outflow.stopInflow) = false; + pre(inflow.stopOutflow) = false; + pre(outflow.stopOutflow) = false; +equation + // inflow to and outflow from stock are unrestricted + inflow.stopInflow = false; + outflow.stopInflow = false; + inflow.stopOutflow = false; + outflow.stopOutflow = false; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This is the general, unrestricted reservoir of the System Dynamics methodology, it accumulates information transported by flow components connected to the StockPorts. The InformationLevel can become negative.

+

Notes

+ + +

See also

+

MaterialStockCapacityRestrictedStock

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end InformationLevel; diff --git a/BusinessSimulation/Stocks/MaterialStock.mo b/BusinessSimulation/Stocks/MaterialStock.mo new file mode 100644 index 0000000..3f216f8 --- /dev/null +++ b/BusinessSimulation/Stocks/MaterialStock.mo @@ -0,0 +1,64 @@ +within BusinessSimulation.Stocks; + +model MaterialStock "Reservoir that cannot be drained below zero" + import BusinessSimulation.Constants.{small,zero}; + import BusinessSimulation.Types.InitializationOptions; + extends Interfaces.PartialStocks.BasicStock(initialValue(min = 0), minValue = zero); + extends Icons.MaterialStockIndicator; + parameter Boolean reinitializeStock = false "= true, if the stock is to be reinitalized to guarante nonnegativity" annotation(Evaluate = true, Dialog(tab = "Advanced")); +initial equation + // properly initialize discrete vars with fixed = false + // inflow to stock is unrestricted + pre(inflow.stopInflow) = false; + pre(outflow.stopInflow) = false; + // provide Boolean signal in case of negative stock + pre(inflow.stopOutflow) = not x > small; + pre(outflow.stopOutflow) = pre(inflow.stopOutflow); +equation + // inflow to stock is unrestricted + inflow.stopInflow = false; + outflow.stopInflow = false; + // provide Boolean signal in case of negative stock + inflow.stopOutflow = not x > small; + outflow.stopOutflow = inflow.stopOutflow; + // optional reinitialize stock to zero if negative // + if reinitializeStock then + when x < 0 then + reinit(x, 0); + end when; + end if; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This is a restricted reservoir of the System Dynamics methodology, which accumulates material  (i.e. countable entities, some kind of mass) transported by flow components connected to the component's StockPorts. The MaterialStock can never become negative – we are not collecting \"antimatter\" – and will prevent connected flow components from draining its value below zero.

+

Implementation

+

The value of the stock will be set to zero if the calculated value x is less than a very small positive amount and if reinitializeStock = true is chosen in the Advanced tab:

+
  if reinitializeStock then
+    when x < 0 then
+      reinit(x, 0);
+    end when;
+  end if;
+

MaterialStock components will prevent connected flows from draining the stock via their →StockPort connectors' Boolean flags, should the calculated value x be less than a very small positive amount:

+
  inflow.stopOutflow = not x > small;
+  outflow.stopOutflow = inflow.stopOutflow;

+

Notes

+ + + +

See also

+

+InformationLevelCapacityRestrictedStock

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, origin = {-80.87, 0}, lineColor = {192, 192, 192}, fillColor = {192, 192, 192}, fillPattern = FillPattern.Solid, points = {{-2.435, 13.229}, {-2.435, -13.344}, {4.87, 0.115}}), Polygon(visible = true, origin = {-70.87, 0}, lineColor = {192, 192, 192}, fillColor = {192, 192, 192}, fillPattern = FillPattern.Solid, points = {{-2.435, 13.229}, {-2.435, -13.344}, {4.87, 0.115}}), Polygon(visible = true, origin = {70.439, 0}, lineColor = {192, 192, 192}, fillColor = {192, 192, 192}, fillPattern = FillPattern.Solid, points = {{-2.435, 13.229}, {-2.435, -13.344}, {4.87, 0.115}}), Polygon(visible = true, origin = {80.439, 0}, lineColor = {192, 192, 192}, fillColor = {192, 192, 192}, fillPattern = FillPattern.Solid, points = {{-2.435, 13.229}, {-2.435, -13.344}, {4.87, 0.115}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end MaterialStock; diff --git a/BusinessSimulation/Stocks/Oven.mo b/BusinessSimulation/Stocks/Oven.mo new file mode 100644 index 0000000..718bb0a --- /dev/null +++ b/BusinessSimulation/Stocks/Oven.mo @@ -0,0 +1,186 @@ +within BusinessSimulation.Stocks; + +model Oven "Batch processing of inflow (aka batch delay)" + import BusinessSimulation.Types.InitializationOptions; + import BusinessSimulation.Units.Time; + import BusinessSimulation.Constants.{inf,INF}; + extends Icons.Oven; + extends Interfaces.Basics.GenericStock_Special(final init = InitializationOptions.FixedValue, hasStockInfoOutput = false); + + expandable connector InputConnector "Named inputs for the component" + extends Icons.DataInPort; + OutputType u_BatchSize "Size of batch to be processed"; + Time u_processingTime "Time to process batch"; + Time u_maxLoadingTime "Maximum allowed duration for loading"; + Time u_setupTime "Time for preparing the next operation"; + Time u_unloadingTime "Time needed to unload"; + end InputConnector; + + expandable connector OutputConnector + extends Icons.DataOutPort; + OutputType y_load "Current load"; + discrete Time y_leadTime "Manufacturing lead time (time from first unit enters to last unit exits on a batch)"; + discrete Time y_processingTime "Effective processing time for the batch process or per unit loaded"; + discrete Time y_setupTime "Effective setup time"; + discrete Time y_loadingTime "Effective loading time"; + discrete Time y_unloadingTime "Effective unloading time"; + end OutputConnector; + + InputConnector dataIn if not (hasConstantLoadingTime and hasConstantBatchSize and hasConstantProcessingTime and hasConstantSetupTime and hasConstantUnloadingTime) "Expandable connector for inputs" annotation(Placement(visible = true, transformation(origin = {0, 85}, extent = {{-10, -10}, {10, 10}}, rotation = -90), iconTransformation(origin = {-50, 100}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + OutputConnector dataOut "Expandable connector for outputs" annotation(Placement(visible = true, transformation(origin = {40, 85}, extent = {{-10, -10}, {10, 10}}, rotation = -270), iconTransformation(origin = {0, 104}, extent = {{-10, -10}, {10, 10}}, rotation = -270))); + parameter OutputType initialLoad(min = 0) = 0 "Amount loaded at start time"; + parameter Time initialLoadingTime(min = 0) = 0 "Time that has already passed to load the initial load at start time"; + parameter OutputType batchSize(min = 0) = 10 "Constant number of units processed in one batch (optional)" annotation(Dialog(enable = hasConstantBatchSize)); + parameter Time maxLoadingTime(min = 0) = inf "Constant maximum allowed time for loading (optional)" annotation(Dialog(enable = hasConstantLoadingTime)); + parameter Time processingTime(min = 0) = 1 "Constant processing time for the batch process or per unit loaded (optional)" annotation(Dialog(enable = hasConstantProcessingTime)); + parameter Time setupTime(min = 0) = 0 "Time needed after processing is finished before loading can start (set to zero for simultaneous loading and unloading)" annotation(Dialog(enable = hasConstantSetupTime)); + parameter Time unloadingTime(min = 0) = modelSettings.dt "Time needed to unload" annotation(Dialog(enable = hasConstantUnloadingTime)); + parameter Boolean hasFixedProcessingTime = true "= true, if the processing time is given for the process, otherwise it is the time per unit loaded" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean hasConstantLoadingTime = true "= true, if the maximum allowed time for loading is to be given by the parameter" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean hasConstantBatchSize = true "= true, if the batch size is to be given by the parameter" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean hasConstantProcessingTime = true "= true, if the processing time is to be given by the parameter" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean hasConstantSetupTime = true "= true, if the setup time is to be given by a parameter" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + parameter Boolean hasConstantUnloadingTime = true "= true, if the unloading time is to be given as a parameter" annotation(Evaluate = true, Dialog(group = "Structural Parameters")); + outer ModelSettings modelSettings; +protected + // converters + Converters.ConstantConverterTime parMaxLoadingTime(value = maxLoadingTime) if hasConstantLoadingTime "Constant max loading time" annotation(Placement(visible = true, transformation(origin = {-90, 50}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.ConstantConverterTime parProcessingTime(value = processingTime) if hasConstantProcessingTime "Constant processing time" annotation(Placement(visible = true, transformation(origin = {30, 50}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.ConstantConverter parBatchSize(value = batchSize) if hasConstantBatchSize "Constant batch size" annotation(Placement(visible = true, transformation(origin = {120, 50}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.PassThrough u_maxLoadingTime if not hasConstantLoadingTime "Variable input of loading time" annotation(Placement(visible = true, transformation(origin = {-65, 50}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.PassThrough u_processingTime if not hasConstantProcessingTime "Variable input of processing time" annotation(Placement(visible = true, transformation(origin = {60, 48.274}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.PassThrough u_BatchSize if not hasConstantBatchSize "Variable batch size" annotation(Placement(visible = true, transformation(origin = {90, 50}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.ConstantConverterTime parSetupTime(value = setupTime) if hasConstantSetupTime "Constant setup time (optional)" annotation(Placement(visible = true, transformation(origin = {-135, 50}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.PassThrough u_setupTime if not hasConstantSetupTime "Variable input of setup time" annotation(Placement(visible = true, transformation(origin = {-110, 50}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.ClipProcessTime actualMaxLoadingTime "Maximum allowed loading time" annotation(Placement(visible = true, transformation(origin = {-50, 20}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ClipProcessTime actualProcessingTime "Processing time" annotation(Placement(visible = true, transformation(origin = {10, 20}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Converters.ZeroIfNegative actualBatchSize "Batch size to be processed" annotation(Placement(visible = true, transformation(origin = {70, 10}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Converters.ZeroIfNegative actualSetupTime "Setup time for further calculations" annotation(Placement(visible = true, transformation(origin = {-90, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Sensors.DynamicStockInfo dynamicStockInfo1 if hasStockInfoOutput annotation(Placement(visible = true, transformation(origin = {-0, -20}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.PassThrough residenceTimeInfo "Residence time info for StockInfoPort" annotation(Placement(visible = true, transformation(origin = {-80, -47.043}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ClipProcessTime actualUnloadingTime "Unloading time" annotation(Placement(visible = true, transformation(origin = {0, -60}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.PassThrough u_unloadingTime if not hasConstantUnloadingTime "Variable input of unloading time" annotation(Placement(visible = true, transformation(origin = {-35, 50}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Converters.ConstantConverterTime parUnloadingTime(value = unloadingTime) if hasConstantUnloadingTime "Constant unloading time" annotation(Placement(visible = true, transformation(origin = {-15, 50}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + // local vars + Real x(min = 0) "Load"; + discrete Time latestStartTime "Time at which the process will commence latest"; + discrete Time lastStartLoading "Time at which the process finished last"; + discrete Time lastStartTime "Time at which the process actually started last"; + discrete Time nextStartLoading "Time at which the process will restart loading next"; + discrete Time fixedProcessingTime "The value for processing time used in current or last process"; + discrete Time fixedLoadingTime "The value for loading time used in the current or last process"; + discrete Time fixedSetupTime "The value for unloading time used in the current or last process"; + discrete Time fixedMaxLoadingTime "Maximum allowed loading time using for current calculations"; + discrete Time fixedUnloadingTime "The value for unloading time used in the current or last process"; +initial equation + // find an initial value for the lastStartLoading of the process + x = initialLoad; + outflow.data = 0; + // properly initialize discrete vars with fixed = false + // oven may be filled at inflow-port, but never drained + pre(inflow.stopOutflow) = true; + pre(fixedMaxLoadingTime) = actualMaxLoadingTime.y; + pre(lastStartTime) = -1; + pre(nextStartLoading) = inf; + // we don't know yet + pre(fixedLoadingTime) = -1; + // fix initial values + pre(fixedProcessingTime) = if not hasFixedProcessingTime then actualBatchSize.y * actualProcessingTime.y else actualProcessingTime.y; + pre(fixedSetupTime) = actualSetupTime.y; + pre(fixedUnloadingTime) = actualUnloadingTime.y; + // take the min(initialLoadingTime, actualLoadingTime) to calculate the lastStartLoading initially + pre(lastStartLoading) = if initialLoadingTime < fixedMaxLoadingTime then time - initialLoadingTime else time - fixedMaxLoadingTime; + pre(latestStartTime) = lastStartLoading + fixedMaxLoadingTime; + // no setup time included in the initial case + pre(inflow.stopInflow) = if initialLoad < actualBatchSize.y then false else true; + pre(inflow.stopOutflow) = true; + pre(dataOut.y_leadTime) = fixedSetupTime + fixedLoadingTime + fixedProcessingTime + fixedLoadingTime; + pre(dataOut.y_processingTime) = fixedProcessingTime; + pre(dataOut.y_loadingTime) = fixedLoadingTime; + pre(dataOut.y_setupTime) = fixedSetupTime; +algorithm + // in this section event-based, discrete behavior takes place + // check wheter production can start + when time >= pre(latestStartTime) or x > actualBatchSize.y then + inflow.stopInflow := true; + // no more inflow + lastStartTime := time; + // update the last time the process started + // fix all variable 'parameters' + fixedProcessingTime := if not hasFixedProcessingTime then x * actualProcessingTime.y else actualProcessingTime.y; + fixedSetupTime := actualSetupTime.y; + fixedLoadingTime := time - lastStartLoading; + fixedUnloadingTime := actualUnloadingTime.y; + nextStartLoading := time + fixedProcessingTime + fixedSetupTime; + lastStartLoading := nextStartLoading; + end when; + //check whether production is done + when time >= pre(lastStartTime) + pre(fixedProcessingTime) then + outflow.data := x / fixedUnloadingTime; + // drain the stock in minimum time dt + // check whether loading can commence + elsewhen time >= pre(lastStartTime) + pre(fixedProcessingTime) + pre(fixedUnloadingTime) then + outflow.data := 0; + end when; + // check whether loading can start + when time >= pre(nextStartLoading) then + inflow.stopInflow := false; + fixedMaxLoadingTime := actualMaxLoadingTime.y; + latestStartTime := lastStartLoading + fixedMaxLoadingTime; + end when; + /* TO DO: + Processing Time should be a fixed amount or a variable amount (x * processTime) depending upon a switch + Batch Size should also be a fixed variable to make this easier to understand + */ +equation + // basic idendities + dataOut.y_load = y; + dataOut.y_leadTime = fixedSetupTime + fixedLoadingTime + fixedProcessingTime + fixedLoadingTime; + dataOut.y_processingTime = fixedProcessingTime; + dataOut.y_loadingTime = fixedLoadingTime; + dataOut.y_setupTime = fixedSetupTime; + residenceTimeInfo.u = fixedSetupTime + (fixedLoadingTime + fixedUnloadingTime) / 2 + fixedProcessingTime; + // textual equations + der(x) = inflow.rate + outflow.rate; + inflow.stock = x; + // outflow.info = 1; + // data will always be the rate to drain the stock + inflow.stopOutflow = true; + // oven must never be drained via inflow-port + // report current load via output connectors + y = inflow.stock; + y1 = inflow.stock; + y2 = inflow.stock; + // connect equations + connect(u_maxLoadingTime.u, dataIn.u_maxLoadingTime) "External input of maximum allowed loading time" annotation(Line(visible = true, origin = {-30, 72}, points = {{-35, -14}, {-35, -2}, {30, -2}, {30, 13}}, color = {1, 37, 163})); + connect(u_processingTime.u, dataIn.u_processingTime) "External input of processing time" annotation(Line(visible = true, origin = {15, 72}, points = {{45, -15.726}, {45, -2}, {-15, -2}, {-15, 13}}, color = {1, 37, 163})); + connect(u_BatchSize.u, dataIn.u_BatchSize) "External input of batch size" annotation(Line(visible = true, origin = {40, 72}, points = {{50, -14}, {50, -2}, {-40, -2}, {-40, 13}}, color = {1, 37, 163})); + connect(parMaxLoadingTime.y, actualMaxLoadingTime.u) annotation(Line(visible = true, origin = {-79.333, 28}, points = {{-10.667, 16}, {-10.667, -8}, {21.333, -8}}, color = {1, 37, 163})); + connect(u_maxLoadingTime.y, actualMaxLoadingTime.u) annotation(Line(visible = true, origin = {-62.667, 27.333}, points = {{-2.333, 14.667}, {-2.333, -7.333}, {4.667, -7.333}}, color = {1, 37, 163})); + connect(parProcessingTime.y, actualProcessingTime.u) annotation(Line(visible = true, origin = {26, 28}, points = {{4, 16}, {4, -8}, {-8, -8}}, color = {1, 37, 163})); + connect(u_processingTime.y, actualProcessingTime.u) annotation(Line(visible = true, origin = {46, 26.758}, points = {{14, 13.516}, {14, -6.758}, {-28, -6.758}}, color = {1, 37, 163})); + connect(u_BatchSize.y, actualBatchSize.u) annotation(Line(visible = true, origin = {86, 20.879}, points = {{4, 21.758}, {4, -10.879}, {-8, -10.879}}, color = {1, 37, 163})); + connect(parBatchSize.y, actualBatchSize.u) annotation(Line(visible = true, origin = {106, 21.667}, points = {{14, 23.333}, {14, -11.667}, {-28, -11.667}}, color = {1, 37, 163})); + connect(u_setupTime.u, dataIn.u_setupTime) "Input of variable unloading time" annotation(Line(visible = true, origin = {-60, 72}, points = {{-50, -14}, {-50, -2}, {60, -2}, {60, 13}}, color = {1, 37, 163})); + connect(parSetupTime.y, actualSetupTime.u) annotation(Line(visible = true, origin = {-122.667, 14.667}, points = {{-12.333, 29.333}, {-12.333, -14.667}, {24.667, -14.667}}, color = {1, 37, 163})); + connect(actualSetupTime.u, u_setupTime.y) annotation(Line(visible = true, origin = {-106, 14}, points = {{8, -14}, {-4, -14}, {-4, 28}}, color = {1, 37, 163})); + connect(inflow, dynamicStockInfo1.inPort) annotation(Line(visible = true, origin = {-114, -10}, points = {{-46, 10}, {-31, 10}, {-31, -10}, {108, -10}}, color = {128, 0, 128})); + connect(dynamicStockInfo1.outPort, outflow) annotation(Line(visible = true, origin = {101.996, -10}, points = {{-95.996, -10}, {18.004, -10}, {18.004, 10}, {58.004, 10}}, color = {128, 0, 128})); + connect(dynamicStockInfo1.y_stockInfo, y_stockInfo) annotation(Line(visible = true, origin = {48, -36.8}, points = {{-48, 22.8}, {-48, 31.8}, {-8, 31.8}, {-8, -43.2}, {102, -43.2}}, color = {128, 0, 128})); + connect(y2, dynamicStockInfo1.levelInfo) annotation(Line(visible = true, origin = {80, -39}, points = {{80, -11}, {80, -1}, {-80, -1}, {-80, 13}}, color = {1, 37, 163})); + connect(u_unloadingTime.y, actualUnloadingTime.u) annotation(Line(visible = true, origin = {-26, -26}, points = {{-9, 68}, {-9, -34}, {18, -34}}, color = {1, 37, 163})); + connect(parUnloadingTime.y, actualUnloadingTime.u) annotation(Line(visible = true, origin = {-12.667, -25.333}, points = {{-2.333, 69.333}, {-2.333, -34.667}, {4.667, -34.667}}, color = {1, 37, 163})); + connect(residenceTimeInfo.y, dynamicStockInfo1.residenceTimeInfo) annotation(Line(visible = true, origin = {-20.879, -40.029}, points = {{-51.758, -7.014}, {25.879, -7.014}, {25.879, 14.029}}, color = {1, 37, 163})); + connect(u_unloadingTime.u, dataIn.u_unloadingTime) "Input unloading time" annotation(Line(visible = true, origin = {-20, 72}, points = {{-15, -14}, {-15, -2}, {20, -2}, {20, 13}}, color = {1, 37, 163})); + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, -80}, textColor = {0, 0, 128}, extent = {{-100, -6}, {100, 6}}, textString = "%initialLoad", fontName = "Lato")}), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

An oven (aka batch delay) can be seen as an idealized model of a batch process, e.g. cookies are put on a baking tray, the oven is loaded, the cookies are baked for some time, and finally the oven is unloaded (the process may then start over again).

+

The parameters or inputs batchSize, maxLoadingTime, processingTime, and setupTime specify the behavior of the batch process. The oven is loaded by a flow connected to its inflow port (usually from a cloud or another stock representing a buffer stock) until either the batchSize is reached (the oven's capacity) or the time since the loading of the oven commenced has reached the maxLoadingTime. It will then close and prevent further inflow for the duration of the processingTime. The unloading of the finished \"material\" will take place in dt time - a global variable that indicates the shortest possible durationa of any process in a model. The reloading can commence after setupTime has passed since the process has ended. For setupTime = 0 simulatenous loading and unloading will take place.

+

To initialize the oven, an initialLoad and an initialLoadingTime (e.g. how much time has already passed loading the oven when the simulation starts) have to be given.

+

Notes

+ +"), Diagram(coordinateSystem(extent = {{-150, -87.876}, {147.976, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Oven; diff --git a/BusinessSimulation/Stocks/PureDelay.mo b/BusinessSimulation/Stocks/PureDelay.mo new file mode 100644 index 0000000..e703b59 --- /dev/null +++ b/BusinessSimulation/Stocks/PureDelay.mo @@ -0,0 +1,137 @@ +within BusinessSimulation.Stocks; + +model PureDelay "Delay the flow of material for a fixed (but variable) delay time" + import BusinessSimulation.Types.InitializationOptions; + import BusinessSimulation.Units.{Time,Rate}; + import BusinessSimulation.Constants.small; + extends Icons.DelayN; + extends Icons.DiscreteStockLabel; + extends Interfaces.Basics.GenericStock_Special(hasStockInfoOutput = false, init = modelSettings.init); + Interfaces.Connectors.RealInput u(quantity = "Time") if not hasConstantDelayTime "Delay time input (optional)" annotation(Placement(visible = true, transformation(origin = {-145, 60}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-50, 100}, extent = {{-10, 10}, {10, -10}}, rotation = 270))); + parameter OutputType initialValue(min = 0) = 0 "Initial load"; + parameter Time delayTime(min = 0, max = maxDelayTime) = 1 "Constant delay time (optional)" annotation(Dialog(enable = hasConstantDelayTime)); + parameter Time maxDelayTime(min = 0) = 10 "Maximum delay time (to restrict memory usage)" annotation(Evaluate = true); + parameter Time samplingPeriod(min = small, max = modelSettings.dt) = modelSettings.samplingPeriod "Sampling period for discrete behavior (should be smaller than dt/2)" annotation(Evaluate = true, Dialog(tab = "Advanced")); + parameter Boolean hasConstantDelayTime = true "= true, if the delay time is to be given by a constant parameter" annotation(Dialog(group = "Structural Parameters")); + parameter Boolean hasExogenousHistory = false "=true, if the outflow-profile for the initial load is to be given by an external lookup function" annotation(Evaluate = true, Dialog(enable = false, group = "Structural Parameters")); + parameter Boolean strict = true "= true, if strict limits with noEvent(..) (clippedDelayTime.strict)" annotation(Evaluate = true, Dialog(tab = "Advanced")); + outer ModelSettings modelSettings; +protected + parameter Integer n = integer(ceil(maxDelayTime / samplingPeriod)) "Array dimensions for storage of loaded material" annotation(Dialog(tab = "Initialization", enable = false)); + // discrete vars + discrete Rate[n] storage "Storage compartments for incoming rates"; + discrete OutputType load(start = initialValue) "Sum of material in the storage" annotation(Dialog(tab = "Initialization", enable = false)); + discrete Time actDelayTime "Actual delay time"; + discrete Rate currentInflowRate "Rate of flow at current time"; + discrete Rate rateToStore "The average rate to store in the storage"; + discrete Rate outflowRate "Rate of outflow from the storage"; + discrete Integer i_store "Index where to store flow rate"; + // converters + Converters.Clip clippedDelayTime(minValue = modelSettings.dt, maxValue = maxDelayTime, strict = strict) "Current delay time" annotation(Placement(visible = true, transformation(origin = {-80, 60}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ConstantConverterTime parDelayTime(value = delayTime) if hasConstantDelayTime "Constant delay time (optional)" annotation(Placement(visible = true, transformation(origin = {-120, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Sensors.DynamicStockInfo dynamicStockInfo1 if hasStockInfoOutput annotation(Placement(visible = true, transformation(origin = {-0, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); +initial equation + // properly initialize discrete vars with fixed = false + pre(inflow.stopInflow) = false; + pre(inflow.stopOutflow) = true; +initial algorithm + storage := zeros(n); + currentInflowRate := inflow.rate; + // set actDelayTime to clipped actual delay time + actDelayTime := clippedDelayTime.y; + // determine the initial load + if init == InitializationOptions.FixedValue then + load := initialValue; + elseif init == InitializationOptions.SteadyState then + // use Little's Law + load := actDelayTime * currentInflowRate; + end if; + // calculate index for storing actual rate and store historical rate (equally distributed load is assumed) + i_store := n - integer(ceil(actDelayTime / samplingPeriod)) + 1; + // start-index matching the initial delay time + rateToStore := if actDelayTime > 0 then load / (n - i_store + 1) / samplingPeriod else load / samplingPeriod; + // one compartment less is needed, as the last package will immediately go out again + for i in i_store + 1:n loop + storage[i] := rateToStore; + end for; + // the last package is to flow out + outflowRate := rateToStore; + // if the index is larger than n then there is no delay for the currentInflow + if i_store > n then + outflowRate := outflowRate + currentInflowRate; + else + // store inflow rate + storage[i_store] := storage[i_store] + currentInflowRate; + end if; +algorithm + // series of events starting at modelStartTime + samplingPeriod and then every samplingPeriod + when sample(modelSettings.modelStartTime + samplingPeriod, samplingPeriod) then + // get current values + currentInflowRate := inflow.rate; + rateToStore := currentInflowRate; + actDelayTime := clippedDelayTime.y; + // shift storage + outflowRate := storage[end]; + storage[2:end] := storage[1:end - 1]; + storage[1] := 0; + // load should count the current rate + load := (sum(storage) + outflowRate) * samplingPeriod; + // calculate storage-index + i_store := n + 1 - integer(ceil(actDelayTime / samplingPeriod)); + if i_store > n then + outflowRate := outflowRate + rateToStore; + else + // store rate + storage[i_store] := storage[i_store] + rateToStore; + end if; + end when; +equation + // connect equations + connect(u, clippedDelayTime.u) annotation(Line(visible = true, origin = {-116.5, 60}, points = {{-28.5, 0}, {28.5, 0}}, color = {1, 37, 163})); + connect(parDelayTime.y, clippedDelayTime.u) annotation(Line(visible = true, origin = {-99.899, 50}, points = {{-14.101, -10}, {-0.101, -10}, {-0.101, 10}, {11.899, 10}}, color = {1, 37, 163})); + connect(dynamicStockInfo1.outPort, outflow) annotation(Line(visible = true, origin = {83, 0}, points = {{-77, 0}, {77, -0}}, color = {128, 0, 128})); + connect(dynamicStockInfo1.inPort, inflow) annotation(Line(visible = true, origin = {-83, 0}, points = {{77, 0}, {-77, -0}}, color = {128, 0, 128})); + connect(y2, dynamicStockInfo1.levelInfo) annotation(Line(visible = true, origin = {80, -34}, points = {{80, -16}, {80, -6}, {-80, -6}, {-80, 28}}, color = {1, 37, 163})); + connect(dynamicStockInfo1.y_stockInfo, y_stockInfo) annotation(Line(visible = true, origin = {48, -24.8}, points = {{-48, 30.8}, {-48, 39.8}, {-8, 39.8}, {-8, -55.2}, {102, -55.2}}, color = {128, 0, 128})); + connect(clippedDelayTime.y, dynamicStockInfo1.residenceTimeInfo) annotation(Line(visible = true, origin = {-36.4, 14.8}, points = {{-35.6, 45.2}, {-23.6, 45.2}, {-23.6, -34.8}, {41.4, -34.8}, {41.4, -20.8}}, color = {1, 37, 163})); + // textual equations + inflow.stopInflow = false; + inflow.stopOutflow = true; + outflow.data = outflowRate; + inflow.stock = load; + // report current load + y = inflow.stock; + y1 = inflow.stock; + y2 = inflow.stock; + // assert statements + assert(samplingPeriod > small, "Sampling period must be larger than zero"); + assert(samplingPeriod < modelSettings.dt, "Sampling period should be significantly smaller than det", level = AssertionLevel.warning); + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

At any given time, the inflow to the PureDelay is delayed by an exact amount of time given either by the parameter delayTime or the continuous input u. Changes in the delay time will only affect the current or later inflow, i.e. whatever is already in the process of being delayed will not be affected.

+

Implementation

+

The PureDelay  will work at discrete time intervals:

+
when sample(modelSettings.modelStartTime + samplingPeriod, samplingPeriod) then
+  // load new material into the stock, move loaded material, unload material
+end when;
+
+

The values for the in- and outflows and the load will be kept constant between events.

+

Notes

+ +

See also

+

SimpleConveyor, Conveyor, DelayNDelayFixedDelayInformation

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Text(visible = true, origin = {0, -80}, textColor = {0, 0, 128}, extent = {{-100, -6}, {100, 6}}, textString = "%initialValue", fontName = "Lato"), Text(visible = true, origin = {0, 75}, textColor = {255, 0, 0}, extent = {{-100, -12}, {100, 12}}, textString = "Pure Delay", fontName = "Lato Black", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end PureDelay; diff --git a/BusinessSimulation/Stocks/SimpleConveyor.mo b/BusinessSimulation/Stocks/SimpleConveyor.mo new file mode 100644 index 0000000..c7b03bd --- /dev/null +++ b/BusinessSimulation/Stocks/SimpleConveyor.mo @@ -0,0 +1,80 @@ +within BusinessSimulation.Stocks; + +model SimpleConveyor "Conveyor (aka pipeline delay) with constant delay time and no leakage" + import BusinessSimulation.Types.InitializationOptions; + import BusinessSimulation.Units.{Time,Rate}; + extends Icons.Conveyor; + extends Interfaces.Basics.GenericStock_Special(hasStockInfoOutput = false, init = modelSettings.init); + parameter OutputType initialValue(min = 0) = 0 "Initial load"; + parameter Time delayTime(min = 0) = 1 "Time of residence in the stock"; +protected + outer ModelSettings modelSettings; + parameter Time clippedDelayTime = max(modelSettings.dt, delayTime) "Delay time should not be less than dt" annotation(Dialog(tab = "Initialization", enable = false)); + parameter Rate initialFlow(fixed = false) "Constant initial outflow" annotation(Dialog(tab = "Initialization", enable = false)); + Real x(start = initialValue, min = 0) "Initial load" annotation(Dialog(tab = "Initialization", enable = false)); + Real delayedFlow "Shifted inflow"; + Sensors.DynamicStockInfo dynamicStockInfo if hasStockInfoOutput "Generate stock information data" annotation(Placement(visible = true, transformation(origin = {0, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Converters.ConstantConverterTime reportedDelayTime(value = clippedDelayTime) annotation(Placement(visible = true, transformation(origin = {50, -30}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); +initial equation + // initialize the stock by finding a valid initial value, by using a given initialValue, or by trying to find a steady state solution + if init == InitializationOptions.FixedValue then + x = initialValue; + elseif init == InitializationOptions.SteadyState then + x = clippedDelayTime * inflow.rate; + // use Little's law + end if; + initialFlow = x / clippedDelayTime; + // properly initialize discrete vars with fixed = false + // inflow to stock is restricted to inflow port + pre(inflow.stopInflow) = false; + pre(inflow.stopOutflow) = true; +equation + delayedFlow = delay(inflow.rate, clippedDelayTime); + // conveyor will signal outflow rate at its outflow-side + outflow.data = if time - modelSettings.modelStartTime < clippedDelayTime then initialFlow else delayedFlow; + // set the inflow.stock value + inflow.stock = x; + // the stock equations determine the current load x + der(x) = inflow.rate + outflow.rate; + // inflow to stock is restricted to inflow port + inflow.stopInflow = false; + inflow.stopOutflow = true; + // report current value of stock via output connectors + y = inflow.stock "Current load"; + y1 = inflow.stock "Current load"; + y2 = inflow.stock "Current load"; + // connect equations + connect(inflow, dynamicStockInfo.inPort) annotation(Line(visible = true, origin = {-83, 0}, points = {{-77, 0}, {77, 0}}, color = {128, 0, 128})); + connect(dynamicStockInfo.outPort, outflow) annotation(Line(visible = true, origin = {83, 0}, points = {{-77, 0}, {77, 0}}, color = {128, 0, 128})); + connect(dynamicStockInfo.y_stockInfo, y_stockInfo) annotation(Line(visible = true, origin = {64, -24.8}, points = {{-64, 30.8}, {-64, 39.8}, {16, 39.8}, {16, -55.2}, {96, -55.2}}, color = {128, 0, 128})); + connect(dynamicStockInfo.levelInfo, y2) annotation(Line(visible = true, origin = {53.333, -35.333}, points = {{-53.333, 29.333}, {-53.333, -14.667}, {106.667, -14.667}}, color = {1, 37, 163})); + connect(reportedDelayTime.y, dynamicStockInfo.residenceTimeInfo) annotation(Line(visible = true, origin = {18.333, -22}, points = {{26.667, -8}, {-13.333, -8}, {-13.333, 16}}, color = {1, 37, 163})); + // assert statements + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The SimpleConveyor (aka pipeline delay) bevhaves as one would expect a conveyor belt to work:  What flows into the SimpleConveyor will flow out after a period given by the parameter delayTime has elapsed. The delayTime will be clipped, so that it can never be smaller than the global parameter modelSettings.dt.

+

Implementation

+

The Conveyor internally uses Modelica's delay() function with a constant time of delay to delay the rate of inflow.

+

Notes

+ + + +

See also

+

ConveyorPureDelay, DelayFixedDelayInformation

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, origin = {240.961, -10}, fillColor = {255, 255, 255}, extent = {{-0.961, -0}, {0.961, 0}}), Text(visible = true, origin = {0, -80}, textColor = {0, 0, 128}, extent = {{-100, -6}, {100, 6}}, textString = "%initialValue", fontName = "Lato")}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end SimpleConveyor; diff --git a/BusinessSimulation/Stocks/package.mo b/BusinessSimulation/Stocks/package.mo new file mode 100644 index 0000000..bb66e7d --- /dev/null +++ b/BusinessSimulation/Stocks/package.mo @@ -0,0 +1,25 @@ +within BusinessSimulation; + +package Stocks "Containers (\"reservoirs\") used to represent entities that have been stored in a specific state" + extends Icons.Package annotation(Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, origin = {0, 5}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, lineThickness = 10, extent = {{-50, -50}, {50, 50}})}), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This package contains stock (\"reservoirs\") elements of the System Dynamics method.

+

Technical Notes

+

While stocks do have an inflow and an outflow port (indicated by two small arrows pointing into and out of the component respectively), this designation will in general not be relevant for their behavior with regard to flows:

+

A stock may be filled or drained on either side - the flow element connected to a stock will determine the direction of flow!

+

Nevertheless, it is good modeling practice to follow the convention of connecting flows that are strictly inflows or outflows to the corresponding stock port.

+

There are two important cases, where closely sticking to the inflow and outflow designations is very important:

+ +

See also

+

+Tutorial.ElementaryBuildingBlocks +

+
+
+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+")); +end Stocks; diff --git a/BusinessSimulation/Stocks/package.order b/BusinessSimulation/Stocks/package.order new file mode 100644 index 0000000..459d1cb --- /dev/null +++ b/BusinessSimulation/Stocks/package.order @@ -0,0 +1,9 @@ +InformationLevel +MaterialStock +CapacityRestrictedStock +HinesCoflow +DelayN +SimpleConveyor +Conveyor +PureDelay +Oven diff --git a/BusinessSimulation/Types/AggregateFunctions.mo b/BusinessSimulation/Types/AggregateFunctions.mo new file mode 100644 index 0000000..93c33ad --- /dev/null +++ b/BusinessSimulation/Types/AggregateFunctions.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Types; + +type AggregateFunctions = enumeration(minimum "Minimum value", geometricMean "Geometric mean", arithmeticMean "Arithmetic mean", maximum "Maximum value") "Functions that can be used to aggregate performance indicators" annotation(Icon(coordinateSystem(preserveAspectRatio = false, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {76, 112, 136}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-100, -100}, {100, 100}}), Text(visible = true, textColor = {76, 112, 136}, extent = {{-90, -50}, {90, 50}}, textString = "1..n", fontName = "Lato", textStyle = {TextStyle.Bold})})); diff --git a/BusinessSimulation/Types/BasicOrientors.mo b/BusinessSimulation/Types/BasicOrientors.mo new file mode 100644 index 0000000..61eeed1 --- /dev/null +++ b/BusinessSimulation/Types/BasicOrientors.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Types; + +type BasicOrientors = enumeration(existence "Existence", effectiveness "Effectiveness (including efficiency)", freedom "Freedom of action", security "Security", adaptability "Adaptability", coexistence "Coexistence") "Basic orientors for sustainable development" annotation(Icon(coordinateSystem(preserveAspectRatio = false, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {76, 112, 136}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-100, -100}, {100, 100}}), Text(visible = true, textColor = {76, 112, 136}, extent = {{-90, -50}, {90, 50}}, textString = "1..n", fontName = "Lato", textStyle = {TextStyle.Bold})})); diff --git a/BusinessSimulation/Types/Booleans.mo b/BusinessSimulation/Types/Booleans.mo new file mode 100644 index 0000000..86d5415 --- /dev/null +++ b/BusinessSimulation/Types/Booleans.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Types; + +type Booleans = Boolean "Basic Boolean type with proper icon" annotation(Icon(coordinateSystem(preserveAspectRatio = false, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {76, 112, 136}, fillColor = {255, 255, 255}, pattern = LinePattern.None, extent = {{-100, -100}, {100, 100}}), Text(visible = true, textColor = {76, 112, 136}, extent = {{-90, -50}, {90, 50}}, textString = "B", fontName = "Lato", textStyle = {TextStyle.Bold})})); diff --git a/BusinessSimulation/Types/InitializationOptions.mo b/BusinessSimulation/Types/InitializationOptions.mo new file mode 100644 index 0000000..f4924e4 --- /dev/null +++ b/BusinessSimulation/Types/InitializationOptions.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Types; + +type InitializationOptions = enumeration(Free "No initial conditions", FixedValue "Specify initial value", SteadyState "Try to set up model in steady state") "How to initialize a stock" annotation(Icon(coordinateSystem(preserveAspectRatio = false, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {76, 112, 136}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-100, -100}, {100, 100}}), Text(visible = true, textColor = {76, 112, 136}, extent = {{-90, -50}, {90, 50}}, textString = "1..n", fontName = "Lato", textStyle = {TextStyle.Bold})})); diff --git a/BusinessSimulation/Types/Integers.mo b/BusinessSimulation/Types/Integers.mo new file mode 100644 index 0000000..8b2614f --- /dev/null +++ b/BusinessSimulation/Types/Integers.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Types; + +type Integers = Integer "Basic Integer type with proper icon" annotation(Icon(coordinateSystem(preserveAspectRatio = false, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {76, 112, 136}, fillColor = {255, 255, 255}, pattern = LinePattern.None, extent = {{-100, -100}, {100, 100}}), Text(visible = true, textColor = {76, 112, 136}, extent = {{-90, -50}, {90, 50}}, textString = "I", fontName = "Lato", textStyle = {TextStyle.Bold})})); diff --git a/BusinessSimulation/Types/MembershipFunctionTypes.mo b/BusinessSimulation/Types/MembershipFunctionTypes.mo new file mode 100644 index 0000000..7d24796 --- /dev/null +++ b/BusinessSimulation/Types/MembershipFunctionTypes.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Types; + +type MembershipFunctionTypes = enumeration(ramp "Bounded ramp function", triangular "Triangular function", trapezoidal "Trapezoidal function", sshaped "S-shaped function", sigmoidal "Sigmoidal membership function", pishaped "Pi-shaped membership function", psigmoidal "Product of two sigmoidal membership functions", gaussian "Gaussian membership function", bell "Bell-shaped membership function") "Basic functions to represent the degree of membership in a set" annotation(Icon(coordinateSystem(preserveAspectRatio = false, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {76, 112, 136}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-100, -100}, {100, 100}}), Text(visible = true, textColor = {76, 112, 136}, extent = {{-90, -50}, {90, 50}}, textString = "1..n", fontName = "Lato", textStyle = {TextStyle.Bold})})); diff --git a/BusinessSimulation/Types/Reals.mo b/BusinessSimulation/Types/Reals.mo new file mode 100644 index 0000000..b61357e --- /dev/null +++ b/BusinessSimulation/Types/Reals.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Types; + +type Reals = Real "Basic Real type with proper icon" annotation(Icon(coordinateSystem(preserveAspectRatio = false, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {76, 112, 136}, fillColor = {255, 255, 255}, pattern = LinePattern.None, extent = {{-100, -100}, {100, 100}}), Text(visible = true, textColor = {76, 112, 136}, extent = {{-90, -50}, {90, 50}}, textString = "R", fontName = "Lato", textStyle = {TextStyle.Bold})})); diff --git a/BusinessSimulation/Types/StockInformation.mo b/BusinessSimulation/Types/StockInformation.mo new file mode 100644 index 0000000..4d8d92a --- /dev/null +++ b/BusinessSimulation/Types/StockInformation.mo @@ -0,0 +1,54 @@ +within BusinessSimulation.Types; + +record StockInformation "Record of information that can be collectecd from a stock" + import BusinessSimulation.Units.{Time,Rate}; + Real infoLevel "Current Level of stock"; + Rate infoInflow(min = 0) "Current rate of inflow"; + Rate infoOutflow(min = 0) "Current rate of outflow"; + Rate infoNetFlow(min = 0) "Net-rate of flow"; + Time infoMeanResidenceTime "Mean time of residence for elements in the stock (-1 indicates infinite time for zero outflow)"; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

A record of stock-related information. It groups that following variables:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Variable (Type) +

Description

+
infoLevel (Real) +

Current amount in the stock or level

+
infoInflow (Rate) +

Current rate of total inflow into stock

+
infoOutflow (Rate) +

Current rate of total outflow from the stock

+
infoNetFlow (Rate) +

Current net-rate of flow (> 0 inflow, < 0 outflow)

+
infoMeanResidenceTime (Time)  +

Current average time of residence for elements in the stock (if there is no outflow, -1 is to be reported)

+
+"), Icon(coordinateSystem(preserveAspectRatio = false, extent = {{-100, -100}, {100, 100}}, initialScale = 0.2, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, pattern = LinePattern.None, extent = {{-100, -100}, {100, 100}})})); +end StockInformation; diff --git a/BusinessSimulation/Types/Strings.mo b/BusinessSimulation/Types/Strings.mo new file mode 100644 index 0000000..fc50fb1 --- /dev/null +++ b/BusinessSimulation/Types/Strings.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Types; + +type Strings = String "Basic Strings type with proper icon" annotation(Icon(coordinateSystem(preserveAspectRatio = false, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {76, 112, 136}, fillColor = {255, 255, 255}, pattern = LinePattern.None, extent = {{-100, -100}, {100, 100}}), Text(visible = true, textColor = {76, 112, 136}, extent = {{-90, -50}, {90, 50}}, textString = "S", fontName = "Lato", textStyle = {TextStyle.Bold})})); diff --git a/BusinessSimulation/Types/TimeBases.mo b/BusinessSimulation/Types/TimeBases.mo new file mode 100644 index 0000000..02032d8 --- /dev/null +++ b/BusinessSimulation/Types/TimeBases.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Types; + +final type TimeBases = enumeration(seconds "Standard unit of time", minutes "60 s", hours "3'600 s", days "86'400 s", weeks "604'800 s (7 days)", months "2'628'000 s (365/12 days)", quarters "7'884'000 s (3 months)", years "31'536'000 s (365 days)") "Time bases for business simulations" annotation(Icon(coordinateSystem(preserveAspectRatio = false, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {76, 112, 136}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, extent = {{-100, -100}, {100, 100}}), Text(visible = true, textColor = {76, 112, 136}, extent = {{-90, -50}, {90, 50}}, textString = "1..n", fontName = "Lato", textStyle = {TextStyle.Bold})})); diff --git a/BusinessSimulation/Types/package.mo b/BusinessSimulation/Types/package.mo new file mode 100644 index 0000000..e8232b8 --- /dev/null +++ b/BusinessSimulation/Types/package.mo @@ -0,0 +1,12 @@ +within BusinessSimulation; + +package Types "Package of Types" + extends Icons.TypesPackage; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This package contains types.

+
+
+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Types; diff --git a/BusinessSimulation/Types/package.order b/BusinessSimulation/Types/package.order new file mode 100644 index 0000000..5017f48 --- /dev/null +++ b/BusinessSimulation/Types/package.order @@ -0,0 +1,10 @@ +AggregateFunctions +BasicOrientors +InitializationOptions +MembershipFunctionTypes +TimeBases +StockInformation +Reals +Booleans +Integers +Strings diff --git a/BusinessSimulation/Units/Amount.mo b/BusinessSimulation/Units/Amount.mo new file mode 100644 index 0000000..84e3228 --- /dev/null +++ b/BusinessSimulation/Units/Amount.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type Amount = Types.Reals(quantity = "Amount", unit = "each") "Counting amounts of entities or substance (base unit = 'each')"; diff --git a/BusinessSimulation/Units/Angle.mo b/BusinessSimulation/Units/Angle.mo new file mode 100644 index 0000000..c329f91 --- /dev/null +++ b/BusinessSimulation/Units/Angle.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type Angle = Types.Reals(quantity = "Angle", unit = "rad", displayUnit = "deg") "Angle in rad, entered and displayed in deg)"; diff --git a/BusinessSimulation/Units/AngularMomentum.mo b/BusinessSimulation/Units/AngularMomentum.mo new file mode 100644 index 0000000..1b6c182 --- /dev/null +++ b/BusinessSimulation/Units/AngularMomentum.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type AngularMomentum = Types.Reals(quantity = "AngularMomentum", unit = "kg.m2/s") "Angular momentum measured in kg.m2/s"; diff --git a/BusinessSimulation/Units/AngularMomentumFlowRate.mo b/BusinessSimulation/Units/AngularMomentumFlowRate.mo new file mode 100644 index 0000000..6f8be80 --- /dev/null +++ b/BusinessSimulation/Units/AngularMomentumFlowRate.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type AngularMomentumFlowRate = Rate(quantity = "AngularMomentumFlowRate", unit = "kg.m2/s2") "Angular momentum flow rate (aka torque) measured in kg.m2/s2"; diff --git a/BusinessSimulation/Units/Area.mo b/BusinessSimulation/Units/Area.mo new file mode 100644 index 0000000..3178c18 --- /dev/null +++ b/BusinessSimulation/Units/Area.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type Area = Types.Reals(quantity = "Area", unit = "m2") "Area measured in m2"; diff --git a/BusinessSimulation/Units/Dimensionless.mo b/BusinessSimulation/Units/Dimensionless.mo new file mode 100644 index 0000000..b063670 --- /dev/null +++ b/BusinessSimulation/Units/Dimensionless.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type Dimensionless = Information(unit = "1") "Information that is dimensionless (e.g. utility)"; diff --git a/BusinessSimulation/Units/Energy.mo b/BusinessSimulation/Units/Energy.mo new file mode 100644 index 0000000..77ee0b7 --- /dev/null +++ b/BusinessSimulation/Units/Energy.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type Energy = Types.Reals(quantity = "Energy", unit = "J") "Energy measured in Joule (W.s)"; diff --git a/BusinessSimulation/Units/EnergyFlowRate.mo b/BusinessSimulation/Units/EnergyFlowRate.mo new file mode 100644 index 0000000..3d47b1b --- /dev/null +++ b/BusinessSimulation/Units/EnergyFlowRate.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type EnergyFlowRate = Rate(quantity = "Power", unit = "W") "Rate of energy transfer (power) usually measured in watt (W) or joule per second (J/s)"; diff --git a/BusinessSimulation/Units/Fraction.mo b/BusinessSimulation/Units/Fraction.mo new file mode 100644 index 0000000..700a0e1 --- /dev/null +++ b/BusinessSimulation/Units/Fraction.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type Fraction = Information(min = 0, max = 1) "Information given as a proper fraction between 0 and 1"; diff --git a/BusinessSimulation/Units/Goods.mo b/BusinessSimulation/Units/Goods.mo new file mode 100644 index 0000000..a8acec5 --- /dev/null +++ b/BusinessSimulation/Units/Goods.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type Goods = Material "Finished or intermediary goods"; diff --git a/BusinessSimulation/Units/Information.mo b/BusinessSimulation/Units/Information.mo new file mode 100644 index 0000000..c8f8be7 --- /dev/null +++ b/BusinessSimulation/Units/Information.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type Information = Types.Reals(quantity = "Information") "Information that may have an arbitrary unit (base unit = '1')"; diff --git a/BusinessSimulation/Units/IntangibleAssets.mo b/BusinessSimulation/Units/IntangibleAssets.mo new file mode 100644 index 0000000..53214fc --- /dev/null +++ b/BusinessSimulation/Units/IntangibleAssets.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type IntangibleAssets = Types.Reals(quantity = "IntangibleAssets") "Intangible assets like computerized information, R & D, economic competencies, and other innovative properties"; diff --git a/BusinessSimulation/Units/Labor.mo b/BusinessSimulation/Units/Labor.mo new file mode 100644 index 0000000..ba30a36 --- /dev/null +++ b/BusinessSimulation/Units/Labor.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type Labor = Types.Reals(quantity = "Labor", unit = "FTE") "Labor as production factor measured in FTE"; diff --git a/BusinessSimulation/Units/Length.mo b/BusinessSimulation/Units/Length.mo new file mode 100644 index 0000000..0f4bd38 --- /dev/null +++ b/BusinessSimulation/Units/Length.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type Length = Types.Reals(quantity = "Length", unit = "m") "Length (or width/breadth, height/depth) measured in m"; diff --git a/BusinessSimulation/Units/Mass.mo b/BusinessSimulation/Units/Mass.mo new file mode 100644 index 0000000..2cae2bb --- /dev/null +++ b/BusinessSimulation/Units/Mass.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type Mass = Types.Reals(quantity = "Mass", unit = "kg") "Mass measured in kg"; diff --git a/BusinessSimulation/Units/MassFlowRate.mo b/BusinessSimulation/Units/MassFlowRate.mo new file mode 100644 index 0000000..3682bc1 --- /dev/null +++ b/BusinessSimulation/Units/MassFlowRate.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type MassFlowRate = Rate(quantity = "MassFlowRate", unit = "kg/s") "Mass flow rate measured in kg/s"; diff --git a/BusinessSimulation/Units/Material.mo b/BusinessSimulation/Units/Material.mo new file mode 100644 index 0000000..1d94517 --- /dev/null +++ b/BusinessSimulation/Units/Material.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type Material = Types.Reals(quantity = "Material") "Primary commodities and unprocessed material"; diff --git a/BusinessSimulation/Units/Momentum.mo b/BusinessSimulation/Units/Momentum.mo new file mode 100644 index 0000000..9f72915 --- /dev/null +++ b/BusinessSimulation/Units/Momentum.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type Momentum = Types.Reals(quantity = "Momentum", unit = "kg.m/s") "Momentum measured in kg.m/s"; diff --git a/BusinessSimulation/Units/MomentumFlowRate.mo b/BusinessSimulation/Units/MomentumFlowRate.mo new file mode 100644 index 0000000..27fc615 --- /dev/null +++ b/BusinessSimulation/Units/MomentumFlowRate.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type MomentumFlowRate = Rate(quantity = "MomentumFlowRate", unit = "kg.m/s2") "Momentum flow rate (aka force) measured in kg.m/s2"; diff --git a/BusinessSimulation/Units/Money.mo b/BusinessSimulation/Units/Money.mo new file mode 100644 index 0000000..b4cd4c0 --- /dev/null +++ b/BusinessSimulation/Units/Money.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type Money = Types.Reals(quantity = "Money", unit = "CU") "Cash and other forms of financial capital accounted for in currency units [CU]"; diff --git a/BusinessSimulation/Units/Money_EUR.mo b/BusinessSimulation/Units/Money_EUR.mo new file mode 100644 index 0000000..63e34f6 --- /dev/null +++ b/BusinessSimulation/Units/Money_EUR.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type Money_EUR = Money(unit = "EUR") "Money accounted for in EUR"; diff --git a/BusinessSimulation/Units/Money_GBP.mo b/BusinessSimulation/Units/Money_GBP.mo new file mode 100644 index 0000000..8021941 --- /dev/null +++ b/BusinessSimulation/Units/Money_GBP.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type Money_GBP = Money(unit = "GBP") "Money accounted for in GBP"; diff --git a/BusinessSimulation/Units/Money_JPY.mo b/BusinessSimulation/Units/Money_JPY.mo new file mode 100644 index 0000000..5c55a12 --- /dev/null +++ b/BusinessSimulation/Units/Money_JPY.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type Money_JPY = Money(unit = "JPY") "Money accounted for in JPY"; diff --git a/BusinessSimulation/Units/Money_USD.mo b/BusinessSimulation/Units/Money_USD.mo new file mode 100644 index 0000000..5b8a9ad --- /dev/null +++ b/BusinessSimulation/Units/Money_USD.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type Money_USD = Money(unit = "USD") "Money accounted for in USD"; diff --git a/BusinessSimulation/Units/Orders.mo b/BusinessSimulation/Units/Orders.mo new file mode 100644 index 0000000..1c68878 --- /dev/null +++ b/BusinessSimulation/Units/Orders.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type Orders = Types.Reals(quantity = "Orders") "Orders are an operational stock used to model the delay between a stated need and its fulfillment"; diff --git a/BusinessSimulation/Units/People.mo b/BusinessSimulation/Units/People.mo new file mode 100644 index 0000000..8b5aec9 --- /dev/null +++ b/BusinessSimulation/Units/People.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type People = Population(quantity = "HumanPopulation") "Some human population (#people)"; diff --git a/BusinessSimulation/Units/Population.mo b/BusinessSimulation/Units/Population.mo new file mode 100644 index 0000000..5039ff6 --- /dev/null +++ b/BusinessSimulation/Units/Population.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type Population = Types.Reals(quantity = "Population") "A population of individuals or organisms belonging to the same group or species"; diff --git a/BusinessSimulation/Units/Probability.mo b/BusinessSimulation/Units/Probability.mo new file mode 100644 index 0000000..a7d5ce6 --- /dev/null +++ b/BusinessSimulation/Units/Probability.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type Probability = Dimensionless(min = 0, max = 1) "Probability between zero and one"; diff --git a/BusinessSimulation/Units/Rate.mo b/BusinessSimulation/Units/Rate.mo new file mode 100644 index 0000000..a017e70 --- /dev/null +++ b/BusinessSimulation/Units/Rate.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type Rate = Types.Reals(quantity = "Rate", unit = "1/s") "Fractional rate per unit of time"; diff --git a/BusinessSimulation/Units/TangibleAssets.mo b/BusinessSimulation/Units/TangibleAssets.mo new file mode 100644 index 0000000..0c8940b --- /dev/null +++ b/BusinessSimulation/Units/TangibleAssets.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type TangibleAssets = Types.Reals(quantity = "TangibleAssets") "Tangible assets like buildings and structure, machinery and equipment, and cultivated assets"; diff --git a/BusinessSimulation/Units/Time.mo b/BusinessSimulation/Units/Time.mo new file mode 100644 index 0000000..a69aefc --- /dev/null +++ b/BusinessSimulation/Units/Time.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type Time = Types.Reals(quantity = "Time", unit = "s") "Time in seconds [s]"; diff --git a/BusinessSimulation/Units/Time_days.mo b/BusinessSimulation/Units/Time_days.mo new file mode 100644 index 0000000..c278b1f --- /dev/null +++ b/BusinessSimulation/Units/Time_days.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type Time_days = Time(displayUnit = "d") "Time entered and displayed in days [d]"; diff --git a/BusinessSimulation/Units/Time_hours.mo b/BusinessSimulation/Units/Time_hours.mo new file mode 100644 index 0000000..85c92cd --- /dev/null +++ b/BusinessSimulation/Units/Time_hours.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type Time_hours = Time(displayUnit = "h") "Time entered and displayed in hours [h]"; diff --git a/BusinessSimulation/Units/Time_minutes.mo b/BusinessSimulation/Units/Time_minutes.mo new file mode 100644 index 0000000..c6a21a1 --- /dev/null +++ b/BusinessSimulation/Units/Time_minutes.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type Time_minutes = Time(displayUnit = "min") "Time entered and displayed in minutes [min]"; diff --git a/BusinessSimulation/Units/Time_months.mo b/BusinessSimulation/Units/Time_months.mo new file mode 100644 index 0000000..7b101aa --- /dev/null +++ b/BusinessSimulation/Units/Time_months.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type Time_months = Time(displayUnit = "mo") "Time entered and displayed in months [mo]"; diff --git a/BusinessSimulation/Units/Time_quarters.mo b/BusinessSimulation/Units/Time_quarters.mo new file mode 100644 index 0000000..0c67357 --- /dev/null +++ b/BusinessSimulation/Units/Time_quarters.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type Time_quarters = Time(displayUnit = "qtr") "Time entered and displayed in quarter years [qtr]"; diff --git a/BusinessSimulation/Units/Time_weeks.mo b/BusinessSimulation/Units/Time_weeks.mo new file mode 100644 index 0000000..0757e41 --- /dev/null +++ b/BusinessSimulation/Units/Time_weeks.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type Time_weeks = Time(displayUnit = "wk") "Time entered and displayed in weeks [wk]"; diff --git a/BusinessSimulation/Units/Time_years.mo b/BusinessSimulation/Units/Time_years.mo new file mode 100644 index 0000000..615e69c --- /dev/null +++ b/BusinessSimulation/Units/Time_years.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type Time_years = Time(displayUnit = "yr") "Time entered and displayed in years [yr]"; diff --git a/BusinessSimulation/Units/Velocity.mo b/BusinessSimulation/Units/Velocity.mo new file mode 100644 index 0000000..9ccb970 --- /dev/null +++ b/BusinessSimulation/Units/Velocity.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type Velocity = Rate(quantity = "Velocity", unit = "m/s") "Velocity given in m/s"; diff --git a/BusinessSimulation/Units/Volume.mo b/BusinessSimulation/Units/Volume.mo new file mode 100644 index 0000000..5a1764d --- /dev/null +++ b/BusinessSimulation/Units/Volume.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type Volume = Types.Reals(quantity = "Volume", unit = "m3") "Volume measured in m3"; diff --git a/BusinessSimulation/Units/VolumeFlowRate.mo b/BusinessSimulation/Units/VolumeFlowRate.mo new file mode 100644 index 0000000..effe22f --- /dev/null +++ b/BusinessSimulation/Units/VolumeFlowRate.mo @@ -0,0 +1,3 @@ +within BusinessSimulation.Units; + +type VolumeFlowRate = Rate(quantity = "VolumeFlowRate", unit = "m3/s") "Volume flow rate measured in m3/s"; diff --git a/BusinessSimulation/Units/package.mo b/BusinessSimulation/Units/package.mo new file mode 100644 index 0000000..d067b31 --- /dev/null +++ b/BusinessSimulation/Units/package.mo @@ -0,0 +1,16 @@ +within BusinessSimulation; + +package Units "Typical quantities used in models" + extends Icons.UnitsPackage; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This package contains types to represent SI-units and (quite often) non-SIunits used in modeling social and ecological systems.

+

See also

+

+Tutorial.UnitsInBusinessSimulations +

+
+
+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+"), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Units; diff --git a/BusinessSimulation/Units/package.order b/BusinessSimulation/Units/package.order new file mode 100644 index 0000000..8ce2826 --- /dev/null +++ b/BusinessSimulation/Units/package.order @@ -0,0 +1,41 @@ +Information +Fraction +Dimensionless +Probability +Amount +Money +Money_USD +Money_EUR +Money_JPY +Money_GBP +Population +People +Labor +TangibleAssets +IntangibleAssets +Material +Goods +Orders +Volume +Mass +Energy +Momentum +AngularMomentum +Angle +Length +Area +Time +Time_minutes +Time_hours +Time_days +Time_weeks +Time_months +Time_quarters +Time_years +Rate +VolumeFlowRate +MassFlowRate +EnergyFlowRate +MomentumFlowRate +AngularMomentumFlowRate +Velocity diff --git a/BusinessSimulation/UsersGuide/Contact.mo b/BusinessSimulation/UsersGuide/Contact.mo new file mode 100644 index 0000000..cb1875f --- /dev/null +++ b/BusinessSimulation/UsersGuide/Contact.mo @@ -0,0 +1,57 @@ +within BusinessSimulation.UsersGuide; + +final class Contact "Contact Information" + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+
+
+
+
+

This page contains the contact information for the library's main author and a list of contributors.

+

Main Author

+

\"BSL_Schriftzug.png\"

+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Name +Guido Wolf Reichert
Address 

+

+Schauenburgerstr. 116 +
+24118 Kiel  +
+Germany 

+
Phone+49 431 5606-855
Fax+49 431 5606-856
E-Mailgwr@bsl-support.de
Webhttps://www.bsl-support.de
+
+
+
+
+"), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(preserveAspectRatio = false, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {56, 56, 56}, fillColor = {230, 230, 230}, fillPattern = FillPattern.Solid, extent = {{-100, -72}, {100, 70}}), Polygon(visible = true, lineColor = {56, 56, 56}, fillColor = {230, 230, 230}, fillPattern = FillPattern.Solid, points = {{-100, -72}, {100, -72}, {0, 20}, {-100, -72}}), Polygon(visible = true, lineColor = {64, 64, 64}, fillColor = {244, 244, 244}, fillPattern = FillPattern.Solid, points = {{-100, 70}, {100, 70}, {0, -20}, {-100, 70}})})); +end Contact; diff --git a/BusinessSimulation/UsersGuide/Licence.mo b/BusinessSimulation/UsersGuide/Licence.mo new file mode 100644 index 0000000..d41732e --- /dev/null +++ b/BusinessSimulation/UsersGuide/Licence.mo @@ -0,0 +1,10 @@ +within BusinessSimulation.UsersGuide; + +class Licence "European Union Public Licence v. 1.2 (EUPL-1.2)" + extends Icons.Info; + annotation(Diagram(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Documentation(info = " +

EUROPEAN UNION PUBLIC LICENCE v. 1.2

+

 

+
EUPL © the European Union 2007, 2016

This European Union Public Licence (the ‘EUPL’) applies to the Work (as defined
below) which is provided under the terms of this Licence. Any use of the Work,
other than as authorised under this Licence is prohibited (to the extent such
use is covered by a right of the copyright holder of the Work).

The Work is provided under the terms of this Licence when the Licensor (as
defined below) has placed the following notice immediately following the
copyright notice for the Work:

Licensed under the EUPL

or has expressed by any other means his willingness to license under the EUPL.

1. Definitions

In this Licence, the following terms have the following meaning:

- ‘The Licence’: this Licence.

- ‘The Original Work’: the work or software distributed or communicated by the
Licensor under this Licence, available as Source Code and also as Executable
Code as the case may be.

- ‘Derivative Works’: the works or software that could be created by the
Licensee, based upon the Original Work or modifications thereof. This Licence
does not define the extent of modification or dependence on the Original Work
required in order to classify a work as a Derivative Work; this extent is
determined by copyright law applicable in the country mentioned in Article 15.

- ‘The Work’: the Original Work or its Derivative Works.

- ‘The Source Code’: the human-readable form of the Work which is the most
convenient for people to study and modify.

- ‘The Executable Code’: any code which has generally been compiled and which is
meant to be interpreted by a computer as a program.

- ‘The Licensor’: the natural or legal person that distributes or communicates
the Work under the Licence.

- ‘Contributor(s)’: any natural or legal person who modifies the Work under the
Licence, or otherwise contributes to the creation of a Derivative Work.

- ‘The Licensee’ or ‘You’: any natural or legal person who makes any usage of
the Work under the terms of the Licence.

- ‘Distribution’ or ‘Communication’: any act of selling, giving, lending,
renting, distributing, communicating, transmitting, or otherwise making
available, online or offline, copies of the Work or providing access to its
essential functionalities at the disposal of any other natural or legal
person.

2. Scope of the rights granted by the Licence

The Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
sublicensable licence to do the following, for the duration of copyright vested
in the Original Work:

- use the Work in any circumstance and for all usage,
- reproduce the Work,
- modify the Work, and make Derivative Works based upon the Work,
- communicate to the public, including the right to make available or display
the Work or copies thereof to the public and perform publicly, as the case may
be, the Work,
- distribute the Work or copies thereof,
- lend and rent the Work or copies thereof,
- sublicense rights in the Work or copies thereof.

Those rights can be exercised on any media, supports and formats, whether now
known or later invented, as far as the applicable law permits so.

In the countries where moral rights apply, the Licensor waives his right to
exercise his moral right to the extent allowed by law in order to make effective
the licence of the economic rights here above listed.

The Licensor grants to the Licensee royalty-free, non-exclusive usage rights to
any patents held by the Licensor, to the extent necessary to make use of the
rights granted on the Work under this Licence.

3. Communication of the Source Code

The Licensor may provide the Work either in its Source Code form, or as
Executable Code. If the Work is provided as Executable Code, the Licensor
provides in addition a machine-readable copy of the Source Code of the Work
along with each copy of the Work that the Licensor distributes or indicates, in
a notice following the copyright notice attached to the Work, a repository where
the Source Code is easily and freely accessible for as long as the Licensor
continues to distribute or communicate the Work.

4. Limitations on copyright

Nothing in this Licence is intended to deprive the Licensee of the benefits from
any exception or limitation to the exclusive rights of the rights owners in the
Work, of the exhaustion of those rights or of other applicable limitations
thereto.

5. Obligations of the Licensee

The grant of the rights mentioned above is subject to some restrictions and
obligations imposed on the Licensee. Those obligations are the following:

Attribution right: The Licensee shall keep intact all copyright, patent or
trademarks notices and all notices that refer to the Licence and to the
disclaimer of warranties. The Licensee must include a copy of such notices and a
copy of the Licence with every copy of the Work he/she distributes or
communicates. The Licensee must cause any Derivative Work to carry prominent
notices stating that the Work has been modified and the date of modification.

Copyleft clause: If the Licensee distributes or communicates copies of the
Original Works or Derivative Works, this Distribution or Communication will be
done under the terms of this Licence or of a later version of this Licence
unless the Original Work is expressly distributed only under this version of the
Licence — for example by communicating ‘EUPL v. 1.2 only’. The Licensee
(becoming Licensor) cannot offer or impose any additional terms or conditions on
the Work or Derivative Work that alter or restrict the terms of the Licence.

Compatibility clause: If the Licensee Distributes or Communicates Derivative
Works or copies thereof based upon both the Work and another work licensed under
a Compatible Licence, this Distribution or Communication can be done under the
terms of this Compatible Licence. For the sake of this clause, ‘Compatible
Licence’ refers to the licences listed in the appendix attached to this Licence.
Should the Licensee's obligations under the Compatible Licence conflict with
his/her obligations under this Licence, the obligations of the Compatible
Licence shall prevail.

Provision of Source Code: When distributing or communicating copies of the Work,
the Licensee will provide a machine-readable copy of the Source Code or indicate
a repository where this Source will be easily and freely available for as long
as the Licensee continues to distribute or communicate the Work.

Legal Protection: This Licence does not grant permission to use the trade names,
trademarks, service marks, or names of the Licensor, except as required for
reasonable and customary use in describing the origin of the Work and
reproducing the content of the copyright notice.

6. Chain of Authorship

The original Licensor warrants that the copyright in the Original Work granted
hereunder is owned by him/her or licensed to him/her and that he/she has the
power and authority to grant the Licence.

Each Contributor warrants that the copyright in the modifications he/she brings
to the Work are owned by him/her or licensed to him/her and that he/she has the
power and authority to grant the Licence.

Each time You accept the Licence, the original Licensor and subsequent
Contributors grant You a licence to their contributions to the Work, under the
terms of this Licence.

7. Disclaimer of Warranty

The Work is a work in progress, which is continuously improved by numerous
Contributors. It is not a finished work and may therefore contain defects or
‘bugs’ inherent to this type of development.

For the above reason, the Work is provided under the Licence on an ‘as is’ basis
and without warranties of any kind concerning the Work, including without
limitation merchantability, fitness for a particular purpose, absence of defects
or errors, accuracy, non-infringement of intellectual property rights other than
copyright as stated in Article 6 of this Licence.

This disclaimer of warranty is an essential part of the Licence and a condition
for the grant of any rights to the Work.

8. Disclaimer of Liability

Except in the cases of wilful misconduct or damages directly caused to natural
persons, the Licensor will in no event be liable for any direct or indirect,
material or moral, damages of any kind, arising out of the Licence or of the use
of the Work, including without limitation, damages for loss of goodwill, work
stoppage, computer failure or malfunction, loss of data or any commercial
damage, even if the Licensor has been advised of the possibility of such damage.
However, the Licensor will be liable under statutory product liability laws as
far such laws apply to the Work.

9. Additional agreements

While distributing the Work, You may choose to conclude an additional agreement,
defining obligations or services consistent with this Licence. However, if
accepting obligations, You may act only on your own behalf and on your sole
responsibility, not on behalf of the original Licensor or any other Contributor,
and only if You agree to indemnify, defend, and hold each Contributor harmless
for any liability incurred by, or claims asserted against such Contributor by
the fact You have accepted any warranty or additional liability.

10. Acceptance of the Licence

The provisions of this Licence can be accepted by clicking on an icon ‘I agree’
placed under the bottom of a window displaying the text of this Licence or by
affirming consent in any other similar way, in accordance with the rules of
applicable law. Clicking on that icon indicates your clear and irrevocable
acceptance of this Licence and all of its terms and conditions.

Similarly, you irrevocably accept this Licence and all of its terms and
conditions by exercising any rights granted to You by Article 2 of this Licence,
such as the use of the Work, the creation by You of a Derivative Work or the
Distribution or Communication by You of the Work or copies thereof.

11. Information to the public

In case of any Distribution or Communication of the Work by means of electronic
communication by You (for example, by offering to download the Work from a
remote location) the distribution channel or media (for example, a website) must
at least provide to the public the information requested by the applicable law
regarding the Licensor, the Licence and the way it may be accessible, concluded,
stored and reproduced by the Licensee.

12. Termination of the Licence

The Licence and the rights granted hereunder will terminate automatically upon
any breach by the Licensee of the terms of the Licence.

Such a termination will not terminate the licences of any person who has
received the Work from the Licensee under the Licence, provided such persons
remain in full compliance with the Licence.

13. Miscellaneous

Without prejudice of Article 9 above, the Licence represents the complete
agreement between the Parties as to the Work.

If any provision of the Licence is invalid or unenforceable under applicable
law, this will not affect the validity or enforceability of the Licence as a
whole. Such provision will be construed or reformed so as necessary to make it
valid and enforceable.

The European Commission may publish other linguistic versions or new versions of
this Licence or updated versions of the Appendix, so far this is required and
reasonable, without reducing the scope of the rights granted by the Licence. New
versions of the Licence will be published with a unique version number.

All linguistic versions of this Licence, approved by the European Commission,
have identical value. Parties can take advantage of the linguistic version of
their choice.

14. Jurisdiction

Without prejudice to specific agreement between parties,

- any litigation resulting from the interpretation of this License, arising
between the European Union institutions, bodies, offices or agencies, as a
Licensor, and any Licensee, will be subject to the jurisdiction of the Court
of Justice of the European Union, as laid down in article 272 of the Treaty on
the Functioning of the European Union,

- any litigation arising between other parties and resulting from the
interpretation of this License, will be subject to the exclusive jurisdiction
of the competent court where the Licensor resides or conducts its primary
business.

15. Applicable Law

Without prejudice to specific agreement between parties,

- this Licence shall be governed by the law of the European Union Member State
where the Licensor has his seat, resides or has his registered office,

- this licence shall be governed by Belgian law if the Licensor has no seat,
residence or registered office inside a European Union Member State.

Appendix

‘Compatible Licences’ according to Article 5 EUPL are:

- GNU General Public License (GPL) v. 2, v. 3
- GNU Affero General Public License (AGPL) v. 3
- Open Software License (OSL) v. 2.1, v. 3.0
- Eclipse Public License (EPL) v. 1.0
- CeCILL v. 2.0, v. 2.1
- Mozilla Public Licence (MPL) v. 2
- GNU Lesser General Public Licence (LGPL) v. 2.1, v. 3
- Creative Commons Attribution-ShareAlike v. 3.0 Unported (CC BY-SA 3.0) for
works other than software
- European Union Public Licence (EUPL) v. 1.1, v. 1.2
- Québec Free and Open-Source Licence — Reciprocity (LiLiQ-R) or Strong
Reciprocity (LiLiQ-R+).

The European Commission may update this Appendix to later versions of the above
licences without producing a new version of the EUPL, as long as they provide
the rights granted in Article 2 of this Licence and protect the covered Source
Code from exclusive appropriation.

All other changes or additions to this Appendix require the production of a new
EUPL version.
+")); +end Licence; diff --git a/BusinessSimulation/UsersGuide/References.mo b/BusinessSimulation/UsersGuide/References.mo new file mode 100644 index 0000000..74d476d --- /dev/null +++ b/BusinessSimulation/UsersGuide/References.mo @@ -0,0 +1,143 @@ +within BusinessSimulation.UsersGuide; + +final class References "Bibliography" + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
[1] +

J. W. Forrester, \"Industrial dynamics: a major breakthrough for decision makers,\" Harvard Business Review, vol. 36, no. 4, pp. 37-66, 1958.

+
[2] +

J. W. Forrester, Industrial Dynamics, Cambridge, MA, USA: M.I.T. Press, 1961.

+
[3]J. D. Sterman, Business Dynamics: Systems Thinking and Modeling for a Complex World. Boston, MA, USA:  McGraw-Hill Higher Education, 2000.
[4]K. Saeed and A. A. Irdamidiris, \"Continuous non-linear functions for use in system dynamics modeling,\" DYNAMICA, vol. 10, no. 1, pp. 16-23, Summer 1984. Available: https://systemdynamics.org/wp-content/uploads/assets/dynamica/volume-10/10-1/6.pdf
[5]F. M. Bass, \"A new product growth for model consumer durables,\" Management Science, vol. 15, no. 5, pp. 215-227, Jan. 1969. 
[6] +

J. Hines, Molecules of Structure: Building Blocks for System Dynamics Models Version 2.03 (2015).

+
[7] +

J. D. W. Morecroft, “A critical review of diagramming tools for conceptualizing feedback system models,” DYNAMICA, vol. 8, no. 1, pp. 20–29, Summer 1982. Available: https://systemdynamics.org/wp-content/uploads/assets/dynamica/volume-8/8-1/5.pdf

+
[8] +

B. Richmond, An Introduction to Systems Thinking, Lebanon, NH, USA: isee systems, 2004.

+
[9] +

A. Ford, Modeling the Environment, 2nd ed. Washington, DC, USA: Island Press, 2010.

+
[10] +

H. Bossel, Systems and Models: Complexity, Dynamics, Evolution, Sustainability. Norderstedt, Germany: Books on Demand, 2007.

+
[11] +

H. Bossel, System Zoo 1 Simulation Models: Elementary Systems, Physics, Engineering. Norderstedt, Germany: Books on Demand, 2007.

+
[12] +

H. Bossel, System Zoo 2 Simulation Models: Climate, Ecosystems, Resources. Norderstedt, Germany: Books on Demand, 2007.

+
[13] +

H. Bossel, System Zoo 3 Simulation Models: Economy, Society, Development. Norderstedt, Germany: Books on Demand, 2007.

+
[14] +

R. G. Coyle, System Dynamics Modelling: A Practical Approach, 1st ed. London, UK: Chapman & Hall, 1996.

+
[15] +

K. Warren, Strategic Management Dynamics. Chichester, UK: John Wiley & Sons, 2008.

+
[16] +

M. J. Radzicki, “Dyadic processes, tempestous relationsships, and system dynamics,” System Dynamics Review, vol. 9, no. 1, pp. 79–94, 1993.

+
[17] +

F. Hoppenstedt, “Predator-prey model,” Scholarpedia, vol. 1, p. 1523, 2006. Available: http://www.scholarpedia.org/article/Predator-prey_model

+
[18] +

P. Junglas, Praxis der Simulationstechnik - Eine Einführung in signal- und objektorientierte Methoden, 1st ed. Haan-Gruiten: Verl. Europa-Lehrmittel, 2014.

+
[19] +

A. Janoschek, “Das reaktionskinetische Grundgesetz und seine Beziehungen zum Wachstums-und Ertragsgesetz,” Statistische Vierteljahresschrift, vol. 10, pp. 25–37, 1957.

+
[20] +

D. N. Ford, \"A system dynamics glossary,\" System Dynamics Review, vol. 35, no. 4, pp. 369–379, 2019. Available: https://onlinelibrary.wiley.com/doi/epdf/10.1002/sdr.1641

+
[21] +

United Nations, System of environmental-economic accounting 2012: Central framework. New York, 2014.

+
[22] +

H. Bossel, Indicators for sustainable development: Theory, method, applications; a report to the Balaton group. Winnipeg: IISD, 1999. Available: https://www.iisd.org/system/files/publications/balatonreport.pdf

+
[23] +

W. O. Kermack and A. G. McKendrick, \"A contribution to the mathematical theory of epidemics,\" Proceedings of the royal society of london. Series A, Containing papers of a mathematical and physical character, vol. 115, no. 772, pp. 700-721, 1927.

+
+"), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(preserveAspectRatio = false, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, origin = {-20, -28}, lineColor = {56, 56, 56}, fillColor = {128, 128, 128}, fillPattern = FillPattern.Solid, points = {{-70, 108}, {-80, 98}, {-80, -72}, {110, -72}, {120, -62}}), Polygon(visible = true, origin = {-60, -5}, lineColor = {56, 56, 56}, fillColor = {179, 179, 179}, fillPattern = FillPattern.Solid, points = {{0, 85}, {-30, 85}, {-30, -85}, {60, -85}}), Rectangle(visible = true, origin = {50, -5}, lineColor = {56, 56, 56}, fillColor = {244, 244, 244}, fillPattern = FillPattern.Solid, extent = {{-50, -85}, {50, 85}}), Polygon(visible = true, origin = {-20.603, -3.83}, lineColor = {56, 56, 56}, fillColor = {230, 230, 230}, fillPattern = FillPattern.Solid, points = {{20.603, 83.83}, {0.603, 103.83}, {-59.397, 103.83}, {-59.397, 103.83}, {-59.397, -66.17}, {-59.397, -66.17}, {0.603, -66.17}, {20.603, -86.17}, {20.603, -86.17}, {20.603, 83.83}}, smooth = Smooth.Bezier), Line(visible = true, origin = {50, 15}, points = {{-35, 0}, {35, 0}}, color = {56, 56, 56}), Line(visible = true, origin = {50, -20}, points = {{-35, 0}, {35, 0}}, color = {56, 56, 56}), Line(visible = true, origin = {50, -55}, points = {{-35, 0}, {35, 0}}, color = {56, 56, 56}), Line(visible = true, origin = {50, 50}, points = {{-35, 0}, {35, 0}}, color = {56, 56, 56})})); +end References; diff --git a/BusinessSimulation/UsersGuide/ReleaseNotes/Version_1_0_0.mo b/BusinessSimulation/UsersGuide/ReleaseNotes/Version_1_0_0.mo new file mode 100644 index 0000000..99e6c39 --- /dev/null +++ b/BusinessSimulation/UsersGuide/ReleaseNotes/Version_1_0_0.mo @@ -0,0 +1,18 @@ +within BusinessSimulation.UsersGuide.ReleaseNotes; + +final class Version_1_0_0 "Version 1.0.0 (2020-11-29)" + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This is the first official release of the library.

+

Notes

+ +

Acknowledgements

+

I'm deeply indebted to the excellent support that I received from Wolfram MathCore and its whole team. I would like to explicitly mention Malte Lenz, Quentin Lambert, and Ankit Naik, who patiently answered my questions and followed up on issues. Thanks a lot, guys. +

+


+

Wolfram System Modeler™ is a trademark of Wolfram Research, Inc.
Wolfram Mathematica and Mathematica™ are registered trademarks of Wolfram Research, Inc.

+"), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(preserveAspectRatio = false, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, lineColor = {56, 56, 56}, fillColor = {246, 246, 246}, fillPattern = FillPattern.Solid, points = {{-80, -100}, {-80, 100}, {20, 100}, {20, 40}, {80, 40}, {80, -100}, {-80, -100}}), Polygon(visible = true, lineColor = {56, 56, 56}, fillColor = {230, 230, 230}, fillPattern = FillPattern.Solid, points = {{20, 100}, {80, 40}, {20, 40}, {20, 100}}), Line(visible = true, points = {{2, -12}, {50, -12}}, color = {56, 56, 56}), Line(visible = true, points = {{2, -60}, {50, -60}}, color = {56, 56, 56}), Ellipse(visible = true, origin = {-35, -60}, lineColor = {56, 56, 56}, fillColor = {160, 160, 164}, fillPattern = FillPattern.Solid, extent = {{-12.5, -12.5}, {12.5, 12.5}}), Ellipse(visible = true, origin = {-35, -12.5}, lineColor = {56, 56, 56}, fillColor = {160, 160, 164}, fillPattern = FillPattern.Solid, extent = {{-12.5, -12.5}, {12.5, 12.5}})})); +end Version_1_0_0; diff --git a/BusinessSimulation/UsersGuide/ReleaseNotes/Version_1_0_1.mo b/BusinessSimulation/UsersGuide/ReleaseNotes/Version_1_0_1.mo new file mode 100644 index 0000000..8ff06e5 --- /dev/null +++ b/BusinessSimulation/UsersGuide/ReleaseNotes/Version_1_0_1.mo @@ -0,0 +1,24 @@ +within BusinessSimulation.UsersGuide.ReleaseNotes; + +final class Version_1_0_1 "Version 1.0.1 (2021-02-02)" + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This release contains fixes to the first release:

+ +"), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(preserveAspectRatio = false, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, lineColor = {56, 56, 56}, fillColor = {246, 246, 246}, fillPattern = FillPattern.Solid, points = {{-80, -100}, {-80, 100}, {20, 100}, {20, 40}, {80, 40}, {80, -100}, {-80, -100}}), Polygon(visible = true, lineColor = {56, 56, 56}, fillColor = {230, 230, 230}, fillPattern = FillPattern.Solid, points = {{20, 100}, {80, 40}, {20, 40}, {20, 100}}), Line(visible = true, points = {{2, -12}, {50, -12}}, color = {56, 56, 56}), Line(visible = true, points = {{2, -60}, {50, -60}}, color = {56, 56, 56}), Ellipse(visible = true, origin = {-35, -60}, lineColor = {56, 56, 56}, fillColor = {160, 160, 164}, fillPattern = FillPattern.Solid, extent = {{-12.5, -12.5}, {12.5, 12.5}}), Ellipse(visible = true, origin = {-35, -12.5}, lineColor = {56, 56, 56}, fillColor = {160, 160, 164}, fillPattern = FillPattern.Solid, extent = {{-12.5, -12.5}, {12.5, 12.5}})})); +end Version_1_0_1; diff --git a/BusinessSimulation/UsersGuide/ReleaseNotes/package.mo b/BusinessSimulation/UsersGuide/ReleaseNotes/package.mo new file mode 100644 index 0000000..c042924 --- /dev/null +++ b/BusinessSimulation/UsersGuide/ReleaseNotes/package.mo @@ -0,0 +1,7 @@ +within BusinessSimulation.UsersGuide; + +package ReleaseNotes "Release notes" + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+"), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(preserveAspectRatio = false, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, lineColor = {56, 56, 56}, fillColor = {246, 246, 246}, fillPattern = FillPattern.Solid, points = {{-80, -100}, {-80, 100}, {20, 100}, {20, 40}, {80, 40}, {80, -100}, {-80, -100}}), Polygon(visible = true, lineColor = {56, 56, 56}, fillColor = {230, 230, 230}, fillPattern = FillPattern.Solid, points = {{20, 100}, {80, 40}, {20, 40}, {20, 100}}), Line(visible = true, points = {{2, -12}, {50, -12}}, color = {56, 56, 56}), Line(visible = true, points = {{2, -60}, {50, -60}}, color = {56, 56, 56}), Ellipse(visible = true, origin = {-35, -60}, lineColor = {56, 56, 56}, fillColor = {160, 160, 164}, fillPattern = FillPattern.Solid, extent = {{-12.5, -12.5}, {12.5, 12.5}}), Ellipse(visible = true, origin = {-35, -12.5}, lineColor = {56, 56, 56}, fillColor = {160, 160, 164}, fillPattern = FillPattern.Solid, extent = {{-12.5, -12.5}, {12.5, 12.5}})})); +end ReleaseNotes; diff --git a/BusinessSimulation/UsersGuide/ReleaseNotes/package.order b/BusinessSimulation/UsersGuide/ReleaseNotes/package.order new file mode 100644 index 0000000..9e49e47 --- /dev/null +++ b/BusinessSimulation/UsersGuide/ReleaseNotes/package.order @@ -0,0 +1,2 @@ +Version_1_0_1 +Version_1_0_0 diff --git a/BusinessSimulation/UsersGuide/Tutorial/ElementaryBuildingBlocks.mo b/BusinessSimulation/UsersGuide/Tutorial/ElementaryBuildingBlocks.mo new file mode 100644 index 0000000..ab3e579 --- /dev/null +++ b/BusinessSimulation/UsersGuide/Tutorial/ElementaryBuildingBlocks.mo @@ -0,0 +1,331 @@ +within BusinessSimulation.UsersGuide.Tutorial; + +final class ElementaryBuildingBlocks "A quick tour introducing the library's main classes" + extends Icons.Info; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Elementary Building Blocks for Dynamic Models

+

The Business Simulation Library provides the following elementary classes to build dynamic models:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IconMain ClassDescription
\"Stocks.svg\"Stocks +

Stocks describe the states of a system, e.g. some measurable quantity, which might—at least on principle—be measured even when we (hypothetically) \"freeze the system\".

+
\"Flows.svg\"Flows +

Flows are aggregate processes that change the states of a system, i.e. they fill and drain stocks at a certain rate.

+
\"SourcesOrSinks.svg\"Sources or Sinks +

Sources or Sinks are stocks with an infinite capacity (aka \"clouds\") out of or into which elements flow at a system's boundary. The BSL extends the narrow definition of sources or sinks and also considers the combination of a stock with infinite capacity and a connected flow to describe processes of growth or decline from external sources or sinks.

+
\"Converters.svg\"Converters +

Converters can be used to model information processing on a very low level. In a converter some information input is immediately processed to provide some information output.

+
\"InformationSources.svg\"Information Sources +

Information sources describe information inputs from \"information processors\" or \"controllers\" that are outside a system's boundary.

+
\"MoleculesOfStructure.svg\"Molecules of Structure +

Pre-built components to model information processing, decision making or subsystems in general.

+
+

+→Flows
+→Sources or Sinks
+→Converters
+→Molecules of Structure +
+

+

Stocks

+
Information Levels, Material Stocks, and Capacity Restricted Stocks
+

In the System Dynamics community the terms stock and level (sometimes also: reservoir) are synonymously used to describe compartments, that store some measurable quantity during a simulation [20]. In general, these compartments can only be filled and drained over time by flows operating at a certain rate. In the Business Simulation Library we will distinguish three basic types of reservoirs

+ + + + + + + + + + + + + + + + + + + + + + + +
IconClass NameDescription
\"InformationLevel.png\"Information Level +

An InformationLevel stores information and can become negative. It is the most general kind of reservoir. For example, we may use an information level to model a company's assets, liabilities, and shareholders' equity.

+
\"MaterialStock.png\"Material Stock +

A MaterialStock will usually contain some form of matter or mass, e.g. living beings and people, raw material, finished goods, capital equipment etc. The plus sign in the upper left corner of the icon indicates, that a material stock can never become negative. If a flow tries to drain a material stock, that does not contain any element, it will be set to zero, as a flow cannot transport \"antimatter\".

+
\"CapacityRestrictedStock.png\"Capacity Restricted Stock +

The CapacityRestrictedStock is a material stock with additional restrictions regarding its capacity. It may have a maximum and a minimum level (≥ 0) which have to be observed and cannot be violated by flows draining or filling the reservoir.

+
+

Stocks—we will continue to use this as a short term for stocks/levels in general—do have an inflow and an outflow port (→StockPort) via which they can receive \"mass\" in- and outflows from connected flow components. This is indicated by the pairs of grey arrows shown within the stock icon. It should be noted though, that this indication and naming is generally only suggestive, as stocks may be filled or drained via both ports. Whenever possible, though, inflows and outflows should primarily be connected to the \"correct\" port of a stock component, as mixing in- and outflows at any port will lead to false stock information reporting by →StockInfoOutputs.

+

All stock components report the quantity that currently resides in the component via information outputs (→RealOutput).

+
Keeping Track of Mean Qualities
+

We would often like to keep track of some mean quality for entities contained in a stock: The experience of new employees or their wage level may vary during a simulation. A coflow is typically applied in these cases and can be very compactly modeled using the HinesCoflow.

+
Dynamic Stocks—Stocks With Delayed or Discrete Outflow
+

Next to the elementary types of stock, there are special kinds of stock which can best be thought of as dynamic stocks. Dynamic stocks have a special stock port (red) on their outflow side (→StockPort_Special). The special stock port indicates, that there is some process working inside the stock, which we will not model in more detail. A dynamic stock will determine the rate of outflow internally (as opposed to regular stocks, where connected flows determine the rate out outflow):

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IconClass NameDescription
 \"DelayN.png\" DelayN +

An n-th order exponential delay will delay its inflow so that the actual times of residence will be distributed around the indicated (mean) delay time. The variation for the distribution of residence times will decrease with higher delay orders (a delay of infinite order will behave exactly like a PureDelay).

+
\"PureDelay.png\"Pure Delay +

A material delay with fixed delay time that may change over time. Any changes in the delay time will only affect incoming material, so that new material may flow out earlier than material already in the stock.

+
\"SimpleConveyor.png\"Simple Conveyor +

This stock can be seen as an ideal conveyor belt, i.e. everything that enters is delayed by a fixed amount of time (which cannot change during the simulation).

+
\"Conveyor.png\"Conveyor +

This stock also models an ideal conveyor, but the discretely modeled component allows the delay time to change during the simulation. Unlike a PureDelay, the order of inflow is preserved so that material may leave the belt at the same time, but never ahead of material that has entered earlier.

+
\"Oven.png\"Oven +

The Oven (aka batch delay) is an ideal model of a batch production process:  Material will flow into the oven until its capacity is reached (or the load time is exceeded). The material will then be processed for some process time and will then be unloaded. During the processing material can neither flow in nor out of the stock.

+
+

All dynamic stocks are material stocks (e.g. there can never be negative amounts inside a process). Dynamic stocks may have additional input ports (or a DataInPort in the case of the Oven) in case process or delay times (and optionally other parameters) are to be variable during the simulation.

+

For dynamic stocks the designation of the ports is binding:  They can only be filled via the inflow port and can only be drained via the outflow port.

+

Unlike regular stocks, dynamic stocks will determine the rate of outflow, so that the rate of outflow is not set independently by the flow component connected to the outflow port of a dynamic stock. Only the →OutflowDynamicStock and the →SplitOutFlowDynamicStock components have a corresponding FlowPort_Special and can be connected to the outflow port of a dynamic stock.

+

Flows

+

Flow components are mainly responsible for dynamic behavior as they fill or drain stocks over time. There are three basic types of flows:

+ + + + + + + + + + + + + + + + + + + + + + + +
IconClass NameDescription
\"UnidirectionalFlow.png\"Unidirectional +

Unidirectional flows drain the stock connected to their portA (→FlowPort) and fill the stock connected to their portB at an identical rate. The rate will always be positive (it will be set to zero if it is negative) and the direction of flow will not change during a simulation.

+
\"BidirectionalFlow.png\"Bidirectional +

Bidirectional flows are essentially unidirectional flows that may change the direction of flow during a simulation depending on the sign of the rate:  A negative rate will transport entities from B to A, while a positive rate will transport entities from A to B.

+
\"Interaction.png\"Interaction +

Interactions model the general case of two stocks which have a bidrectional flow from/to a cloud (\"netflow\") where the rate of the netflow (a positive rate will fill the respective stock) may depend on the current amount in one or both of the connected stocks. A simple example is the →BrokenTransition, where the inflow to stock B is proportional to the rate of the outflow of stock A, i.e. here some kind of transformation is modeled rather than a mere transition.

+
+

All flow components report their current rate—or rates in the case of interactions—via information outputs (→RealOutput). They may have additional inputs (→RealInput) in the general case where variables determining the rate of flow can change during the simulation.

+

Sources or Sinks

+

Sources or Sinks are compact components that can be used to model processes of growth or decline at a system's boundary in a compact way:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
IconClass NameDescription
\"Cloud.png\"Cloud

A Cloud simply is a stock that is outside a system's boundary—here we assume that the stock has an infinite capacity. A typical example would be any model of population dynamics, where we will not model where newborns come from or what will happen to the deceased population. A cloud can be either source or sink.

\"Source.png\"Source +

A Source combines a Cloud with a unidirectional outflow that will then fill the stock connected to the component's massPort.

+
\"Sink.png\"Sink +

A Sink combines a Cloud with a unidirectional inflow that will then drain the stock connected to the component's massPort.

+
\"SourceOrSink.png\"Source or Sink +

A SourceOrSink combines a Cloud with a bidirectional flow that may fill or drain the stock connected to the component's massPort depending on the sign of the flow's rate (a positive rate by convention fills the stock).

+
+

Like flow components, sources or sink components report their current rate via information outputs (→RealOutput). They may have additional inputs (→RealInput) in the general case where variables determining the rate of flow can change during the simulation.

+

Converters

+

Converters take one or more information inputs (→RealInput), apply a real-valued function to the inputs, and then return the result as an information output (→RealOutput). Regular converters typically model basic arithmetic functions like exp, log, power, plus etc. Next to regular converters there are more specialized converter classes:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
IconPackage NameDescription
\"DiscreteDelay.svg\"Discrete Delay +

DiscreteDelay converters introduce discrete behavior or delays into information processing and typically contain an information level—which is the reason for their boxlike-appearance.

+
\"Logical.svg\"Logical +

Logical converters have Boolean outputs (→BooleanOutput) and/or inputs (→BooleanInput).

+
\"Lookup.svg\"Lookup +

Lookup converters use tabular or more elaborate parametric functions to model the transformation of information.

+
\"Lookup.svg\"Vector +

Vector converters have vector inputs and/or outputs.

+
+

Molecules of Structure

+
Information Processingand Decision Making
+

John Morecroft [7] suggested that diagrams of dynamic systems would be greatly improved, if we used more aggregate diagramming. In this library we are well advised to follow that advice: We can reduce the diagram for a system under management to show the system itself and its observable information output. We then just need two additional, rather aggregated converters:

+ + + + + + + + + + + + + + + + + +
IconPackage NameDescription
\"InformationProcessing.svg\"Information Processing +

Taking the raw information from the system and its environment and bringing it into the form needed for decision making.

+
\"Policy.svg\"Policy +

Using (preprocessed) information, we will have some decision rule that will give a decision output—usually goals and other regulations to be observed or rates for processes that change the state(s) of the system.

+
+
Subsystems—Modeling a System of Systems
+

When we look at complex systems in society or even at individual companies and markets, we are well advised to conquer their complexity by applying a hierarchical modeling approach:  We will model the system in focus as a system of systems exchanging information and/or physical entities. Jay Forrester, for example, in his seminal book \"Industrial Dynamics\" [2, Section 6.2] distinguished the \"physical\" flow of material, orders, money, personnel, and capital equipment from that of information.

+

Since a closed system, i.e. one that does not exchange anything with other systems, is rather irrelevant, we can usually assume that all subsystems will receive and/or transmit information for managerial control or just for information processing. Accordingly, all subsystems will have connectors for information input and output (typically →DataInPort and →DataOutPort).

+

We can thus best distinguish different types of subsystems by looking at the presence of stock and flow ports:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
IconSubsystem TypeDescription
\"Blocks.svg\"Blocks +

Systems or processes that do not exchange physical entities with other systems vie stock or flow ports—there is only exchange of information via DataIn- and DataOutPorts, e.g. managerial control, government, and/or information processing.

+
\"Incubators.svg\"Incubators +

Systems or processes that receive, store, and provide physical entities via multiple stock ports. There will usually be some kind of transformation during storage.

+
\"Transceivers.svg\"Transceivers +

Systems or processes that receive and store physical entities, but also move entities to/from connected systems. This is most general kind of subsystem and will have multiple stock and flow ports.

+
\"Actuators.svg\"Actuators +

Systems or processes that move physical entities to and from connected systems via multiple flow ports.

+
+
+
+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+")); +end ElementaryBuildingBlocks; diff --git a/BusinessSimulation/UsersGuide/Tutorial/StrategicBusinessSimulation.mo b/BusinessSimulation/UsersGuide/Tutorial/StrategicBusinessSimulation.mo new file mode 100644 index 0000000..235b3d4 --- /dev/null +++ b/BusinessSimulation/UsersGuide/Tutorial/StrategicBusinessSimulation.mo @@ -0,0 +1,50 @@ +within BusinessSimulation.UsersGuide.Tutorial; + +final class StrategicBusinessSimulation "From Business Process Modeling the Strategic Business Simulation" + extends Icons.Info; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

From Business Process Modeling to Strategic Business Simulation

+
Business Process Modeling
+

Business process modeling (BPM) has become an ubiquitous activity in support of management decision making and business analytics. While there are different tools and notation for BPM, event-driven process chains (EPC) offer a very general and simple way of modeling business processes. Essentially, processes always start with an event that will lead to one or more activites (functions in EPC-terminology) which again will mount into one or more events, so that in general any activity must always be braced by two events.

+

Figure 1 shows an EPC for the idealized production process of ACME, a startup that produces intruder alarm systems specifically designed to meet private home owners’ needs. The diagram is valid for a single unit produced and shows events (red hexagons) and functions (green boxes) in typical notation. 

+ + + + + + +
Figure 1: Simple Production Process
\"SimpleProductionProcess.png\"
+

While this \"discrete-event\" view of production is great for operational process improvement, it is not so well suited for for winning over investors by telling a compelling story about business development or for discussing policy-setting issues with regard to social systems and organizations. In these cases an aggregate strategic view is the better choice.

+

Aggregate View of Production

+

To go from the the familiar perspective of BPM to a more strategic one, we will look at what happens in a period. In a month there will be lots of events and actions. We can aggregate the actions and events separately:  Individual actions will thus add up to a process that produces tangible results at a certain rate(e.g. assembled units per month). In the general case the rate may be a continuously varying quantity due to external and internal disruptions or policies. Events on the other hand can be collected as the countable results of processes, e.g. finished products can be collected in an inventory.

+

Figure 2 shows, how we can move from the event-driven process chain model to a strategic model using the Business Simulation Library. As in the EPC we will start out with its dynamic equivalent, a container—called stock. The very first stock is called a source in the library, which means that we assume infinite capacity indicating our model's boundary (i.e. in our example we do not care for the source of all material, that we need to assemble products).

+ + + + + + +
Figure 2: Actions Add Up to Flows and Events to Stocks
\"ContinuousView.png\"
+

The assembly of products in our example has been aggregated to a mere process of transition from the unlimited stock of raw materials to the inventory of finished goods. Shipping products in Figure 2 has also become a mere transition at some given rate, which moves our products to the stock installedBase representing continued use during the product's useful lifetime.

+

Stocks (with red color code inherited from events) and flows (with green color code inherited from actions) are atomic systems in the library. As we can see in Figure 2, stocks and flows are connected via acausal connectors (→ StockPort, → FlowPort). Each component reports basic information about what is going on inside using output connectors (white triangles; → RealOutput):  A flow will report its current rate at any time during a simulation, whereas a stock will report the amount of entities that are inside at any time during a simulation. The numbers shown inside the stocks indicates the initial amount inside the respective stock.

+

Looking at the producing and shipping flows in Figure 2, we find, that they show a stylized pipeline (following System Dyamics conventions) with a stylized paddle wheel pump that is influenced by a variable called rate.

+ + + + + + +
Figure 3: Setting the Rate
\"SettingTheRate.png\"
+

Since there is no information input to the producing component, the rate of production in this simple case is a constant parameter. Figure 3 shows how—upon selecting the component—the rate can be set in the General tab in SystemModeler. Note, that there is also a structural parameter hasConstantRate that allows to instead of a parameter have an variable input for the rate.

+

Examples

+

This introductory example is continued in the package Examples:

+ +
+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+")); +end StrategicBusinessSimulation; diff --git a/BusinessSimulation/UsersGuide/Tutorial/UnitsInBusinessSimulations.mo b/BusinessSimulation/UsersGuide/Tutorial/UnitsInBusinessSimulations.mo new file mode 100644 index 0000000..d4bf37b --- /dev/null +++ b/BusinessSimulation/UsersGuide/Tutorial/UnitsInBusinessSimulations.mo @@ -0,0 +1,128 @@ +within BusinessSimulation.UsersGuide.Tutorial; + +final class UnitsInBusinessSimulations "How to make use of the unit framework" + extends Icons.Info; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

Units in Business Simulations

+

Units and unit checking are central to most modelers in System Dynamics and there are good reasons for this: It is all too easy to come up with nonsensical equations and mixing \"apples and oranges\". Modelica as a cyber-physical modeling language clearly encourages modelers to make use of its rather elaborate unit framework that provides the attributes quantity, unit, and displayUnit for any real valued variable in models:

+ +

While the rigor of physical models cannot be fully transfered to modeling in the social sciences and ecology, there is maybe some middle ground:

+ +

Units in the Business Simulation Library

+

Currently, units are not used for acausal connectors, i.e. the stock and the rate in a →StockPort or in a →FlowPort are simply of the predefined type Real with quantity = \"\" and unit = \"1\", making them dimensionless.

+

Quantities and units are used for the information outputs of components. In most elementary classes there is a replaceable type OutputType which can be conveniently set using a drop down list in SystemModeler. In general, the default will be one of the following types: Types.Reals, Units.Rate, or Units.Time.

+

A modeler may simply stick with say Types.Reals, which is identical to Modelica's predefined type Real, for a stock called \"personnel\" and then use the editor to modify the quantity and unit attributes:

+
Types.Reals(quantity = \"HumanPopulation\", unit = \"people\")
+

Doing so would correspond with what most dedicated System Dynamics packages allow. Nevertheless, the Business Simulation Library is designed with the following recommendations:

+
Units of Time
+

Modelica does not allow to change the unit for the built-in variable time. Accordingly, the following types all have unit = \"s\" and all models will run in seconds so that there can never be any doubt when different models are coupled:

+
Time, Time_minutes, Time_hours, Time_days, Time_weeks, Time_months, Time_quarters, Time_years
+

The type Time_years, for example, has displayUnit = \"yr\" and allows to conveniently enter 5 yr in setting the →ConstantConverterTime usefulLife in the model Examples.SimpleProductionChain.

+

Note, that we need to add custom unit conversions for the units wk, mo, qtr, yr as shown in Figure 1—but we only need to do this once.

+ + + + + + +
Figure 1: Custom Conversions for Time
\"CustomConversions_Time.png\"
+
Setting Rates
+

Using displayUnit for time is very convenient—unfortunately this flexibility is harder to transfer to entering rates: We would need to have lots of unit conversions say one for people/yr and another one for EUR/yr.

+

Given that we are most of the time simply counting some entities (like a chemist is counting different molecules) it should suffice to enter fractional rates (→Units.Rate). Then we only need to add custom unit conversions for 1/wk, 1/mo, 1/qtr, 1/yr in SystemModeler as shown in Figure 2.

+ + + + + + +
Figure 2: Custom Conversions for Rate
\"CustomConversions_Rate.png\"
+

In the example Examples.SimpleProductionChain we can set the productionRate in the ConstantConverter by leaving ValueType = Types.Reals (default) and using timeBaseString to select \"month\", so that value = 100 is then correctly shown as a fractional rate of 100 per month. Remember, that the value used in any calculations will be the corresponding rate per second.

+

Next to fractional rates we can also work with correct rates for some physical flows, e.g. VolumeFlowRate, MassFlowRate, EnergyFlowRate, MomentumFlowRate, AngularMomentumFlowRate, Velocity, which are defined as follows:

+
+  type Rate = Types.Reals(quantity = \"Rate\", unit = \"1/s\") \"Fractional rate per unit of time\";
+  type VolumeFlowRate = Rate(quantity = \"VolumeFlowRate\", unit = \"m3/s\") \"Volume flow rate measured in m3/s\";
+  type MassFlowRate = Rate(quantity = \"MassFlowRate\", unit = \"kg/s\") \"Mass flow rate measured in kg/s\";
+  type EnergyFlowRate = Rate(quantity = \"Power\", unit = \"W\") \"Rate of energy transfer (power) usually measured in watt (W) or joule per second (J/s)\";
+  type MomentumFlowRate = Rate(quantity = \"MomentumFlowRate\", unit = \"kg.m/s2\") \"Momentum flow rate (aka force) measured in kg.m/s2\";
+  type AngularMomentumFlowRate = Rate(quantity = \"AngularMomentumFlowRate\", unit = \"kg.m2/s2\") \"Angular momentum flow rate (aka torque) measured in kg.m2/s2\";
+  type Velocity = Rate(quantity = \"Velocity\", unit = \"m/s\") \"Velocity given in m/s\";
+
+

Refer to the documentation for ConstantConverterRate for more detail.

+
Other Units
+

Next to rates and times we will need appropriate units for entities accounted for in stocks and information processing in general. In the Business Simulation Library the available types, which all extend Types.Reals, can be grouped as follows:

+
Information-related Types
+

Strictly speaking, everything in a model might be considered information and thus the following definitions seem rather evident: +

+  type Information = Types.Reals(quantity = \"Information\") \"Information that may have an arbitrary unit (base unit = '1')\";
+  type Fraction = Information(min = 0, max = 1) \"Information given as a fraction between zero and one\";
+  type Dimensionless = Information(unit = \"1\") \"Information that is dimensionless (e.g. utility)\";
+  type Probability = Dimensionless(min = 0, max = 1) \"Probability between zero and one\";
+
+
+
Counting Units
+

In a model of chemical reactions we will not find unit = \"H2O\" or other molecules—which could be seen as the analogy to what is common practice in System Dynamics counting amounts of similar entities. So, it may not seem totally implausible to somewhat approach modeling in the social sciences a bit like a chemist and use counting units for some amount of similar entities contained in stocks whose instance name very likely will reflect what is counted inside. As the definition for type Amount below shows, we may even include a chemist's mol:

+
+  type Amount = Types.Reals(quantity = \"Amount\", unit = \"each\") \"Counting amounts of entities or substance (base unit = 'each')\";
+
+

Using the custom unit conversions shown in Figure 3 we can use displayUnit have large values be shown as 2 million or enter small values as 2.5 percent. The resulting value will always be a pure number since 1 each = 1.

+ + + + + + +
Figure 3: Custom Conversions for Amount
\"CustomConversions_Amount.png\"
+
Monetary Value
+

Value in economic models may be either expressed as (dimensionless) utility or in monetary terms. For the latter, the following types are defined in the Units package: +

+  type Money = Types.Reals(quantity = \"Money\", unit = \"CU\") \"Cash and other forms of financial capital accounted for in currency units [CU]\";
+  type Money_USD = Money(unit = \"USD\") \"Money accounted for in USD\";
+  type Money_EUR = Money(unit = \"EUR\") \"Money accounted for in EUR\";
+  type Money_JPY = Money(unit = \"JPY\") \"Money accounted for in JPY\";
+  type Money_GBP = Money(unit = \"GBP\") \"Money accounted for in GBP\";
+
+
+
Ecological and Economical Quantities
+

Even though, we may use counting units (see Amount above), it seems to make a lot of sense to distinguish some essential quantites and their interconnected networks of stocks and flows—similar to the way Forrester did, as mentioned before. In economic and ecological models, the following definitions may suffice for a lot of use cases:

+
 
+  type Population = Types.Reals(quantity = \"Population\") \"A population of individuals or organisms belonging to the same group or species\";
+  type People = Population(quantity = \"HumanPopulation\") \"Some human population (#people)\";
+  type Labor = Types.Reals(quantity = \"Labor\", unit = \"FTE\") \"Labor as production factor measured in FTE\";
+  type TangibleAssets = Types.Reals(quantity = \"TangibleAssets\") \"Tangible assets like buildings and structure, machinery and equipment, and cultivated assets\";
+  type IntangibleAssets = Types.Reals(quantity = \"IntangibleAssets\") \"Intangible assets like computerized information, R & D, economic competencies, and other innovative properties\";
+  type Material = Types.Reals(quantity = \"Material\") \"Primary commodities and unprocessed material\";
+  type Goods = Material \"Finished or intermediary goods\";
+  type Orders = Types.Reals(quantity = \"Orders\") \"Orders are an operational stock used to model the delay between a stated need and its fulfillment\";
+
+
+
Conserved Physical Quantities
+

In times of climate change and other questions touching global sustainability the need to combine ecological and economical thinking has led to the realization that humanity and its economic system is tightly embedded in a biological and physical environment. Therefore physical stocks and their in- and outflows have to be accounted for properly [21]. It thus seems appropriate to at least introduce some important conserved physical quantities:

+
+  type Volume = Types.Reals(quantity = \"Volume\", unit = \"m3\") \"Volume measured in m3\";
+  type Mass = Types.Reals(quantity = \"Mass\", unit = \"kg\") \"Mass measured in kg\";
+  type Energy = Types.Reals(quantity = \"Energy\", unit = \"J\") \"Energy measured in Joule (W.s)\";
+  type Momentum = Types.Reals(quantity = \"Momentum\", unit = \"kg.m/s\") \"Momentum measured in kg.m/s\";
+  type AngularMomentum = Types.Reals(quantity = \"AngularMomentum\", unit = \"kg.m2/s\") \"Angular momentum measured in kg.m2/s\";
+
+
+
Other Physical Quantities
+

Next to the physical quantites listed above, we conclude with just these additions:

+
+  type Angle = Types.Reals(quantity = \"Angle\", unit = \"rad\", displayUnit = \"deg\") \"Angle in rad, entered and displayed in deg)\";
+  type Length = Types.Reals(quantity = \"Length\", unit = \"m\") \"Length (or width/breadth, height/depth) measured in m\";
+  type Area = Types.Reals(quantity = \"Area\", unit = \"m2\") \"Area measured in m2\";
+
+
+
+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+")); +end UnitsInBusinessSimulations; diff --git a/BusinessSimulation/UsersGuide/Tutorial/package.mo b/BusinessSimulation/UsersGuide/Tutorial/package.mo new file mode 100644 index 0000000..e344c8d --- /dev/null +++ b/BusinessSimulation/UsersGuide/Tutorial/package.mo @@ -0,0 +1,16 @@ +within BusinessSimulation.UsersGuide; + +final package Tutorial "A tutorial for using the Business Simulation Library" + extends Icons.Info; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This package contains documentation files to guide users in becoming familiar with the library.

+

See also

+

+Examples +

+
+
+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+"), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end Tutorial; diff --git a/BusinessSimulation/UsersGuide/Tutorial/package.order b/BusinessSimulation/UsersGuide/Tutorial/package.order new file mode 100644 index 0000000..0f7bb55 --- /dev/null +++ b/BusinessSimulation/UsersGuide/Tutorial/package.order @@ -0,0 +1,3 @@ +StrategicBusinessSimulation +ElementaryBuildingBlocks +UnitsInBusinessSimulations diff --git a/BusinessSimulation/UsersGuide/package.mo b/BusinessSimulation/UsersGuide/package.mo new file mode 100644 index 0000000..ad1e4c1 --- /dev/null +++ b/BusinessSimulation/UsersGuide/package.mo @@ -0,0 +1,51 @@ +within BusinessSimulation; + +package UsersGuide "User's Guide to BusinessSimulation Library" + extends Icons.Info; + annotation(Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

This package contains documentation files to guide users in becoming familiar with the library:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Content +

Description

+
Tutorial +

A comprehensive tutorial introducing the user to the Business Simulation Library.

+
References +

List of numbered references that are cited in documentation pages.

+
Release Notes +

Release notes and acknowledgements.

+
Contact +

Contact info and list of contributors.

+
Licence +

Terms and conditions for using and distributing the Business Simulation Library (\"The License\").

+
+
+

Copyright © 2020 Guido Wolf Reichert
Licensed under the EUPL-1.2 or later

+"), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end UsersGuide; diff --git a/BusinessSimulation/UsersGuide/package.order b/BusinessSimulation/UsersGuide/package.order new file mode 100644 index 0000000..c23a3d0 --- /dev/null +++ b/BusinessSimulation/UsersGuide/package.order @@ -0,0 +1,5 @@ +Tutorial +Licence +References +ReleaseNotes +Contact diff --git a/BusinessSimulation/package.mo b/BusinessSimulation/package.mo new file mode 100644 index 0000000..6280e35 --- /dev/null +++ b/BusinessSimulation/package.mo @@ -0,0 +1,31 @@ +package BusinessSimulation "A library for modeling & simulation of dynamical systems in the social sciences, e.g. business/economics, and ecology using the System Dynamics metaphor." + annotation(version = "1.0.1", versionDate = "2021-02-02", revisionId = "", uses(Modelica(version = "3.2.3")), Documentation(info = " +

This information is part of the Business Simulation Library (BSL).

+

The BUSINESS SIMULATION LIBRARY (BSL) supports modeling & simulation in the social sciences and ecology. Following John Sterman [3] the name \"Busines Simulation\" was chosen in a rather broad sense since ultimately modeling in these domains is concerned with \"control\", \"decision making\", and \"management\".

+

The BSL follows the widespread System Dynamics metaphor and modeling approach introduced by Jay W. Forrester [1], [2]. System Dynamics offers a very general, low-level modeling paradigm, that lends itself perfectly to model, simulate, and analyze strategic business or public policy issues.

+

Unlike existing aproaches the BSL makes use of Modelica's acausal connectors to better distinguish material/mass flows from instantaneous information signal flows (causal connections). The approach has the additional benefit of allowing the modeler to build rather compact models in a fast and reliable fashion.

+

To get started with the library, it is recommended to have a look at:

+ +
+

Corresponding Author

+

+ +\"ContactInformation.png\" +

+
+
+

Releases

+ +
+

Copyright © 2020 Guido Wolf Reichert
Licensed unter the European Union Public Licence (EUPL), Version 1.2 or later (the \"License\")

+

You may not use this work except in compliance with the License. You may obtain a copy of the License at:
https://eur-lex.europa.eu/eli/dec_impl/2017/863/oj (the English text for EUPL-1.2 is included in the UsersGuide)

+

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either expressed or implied. See the License for the specific language governing permissions and limitations under the License.

+

Modelica© is a registered trademark of the Modelica Association.

+"), __Wolfram(itemFlippingEnabled = true), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {76, 112, 136}, fillColor = {113, 166, 201}, pattern = LinePattern.None, fillPattern = FillPattern.HorizontalCylinder, lineThickness = 4, extent = {{-100, -100}, {100, 100}}, radius = 25), Rectangle(visible = true, origin = {0.142, -2.447}, lineColor = {255, 255, 255}, fillColor = {255, 255, 255}, lineThickness = 10, extent = {{-62.191, -62.447}, {62.191, 62.447}}), Text(visible = true, origin = {0, -30}, textColor = {255, 255, 255}, extent = {{-60, -30}, {60, 30}}, textString = "BSL", fontName = "Lato Black", textStyle = {TextStyle.Bold}), Polygon(visible = true, origin = {25.123, 60}, rotation = -990, lineColor = {76, 112, 136}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-10, 10}, {10, 0}, {-10, -10}, {-10, 10}}), Polygon(visible = true, origin = {-23.947, 60}, rotation = -1170, lineColor = {255, 255, 255}, fillColor = {76, 112, 136}, fillPattern = FillPattern.Solid, points = {{-10, 10}, {10, 0}, {-10, -10}, {-10, 10}}), Rectangle(visible = true, origin = {-63.017, -0.581}, lineColor = {76, 112, 136}, fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, lineThickness = 3, extent = {{-8.5, -9.419}, {8.5, 9.419}}), Rectangle(visible = true, origin = {61.5, 0}, lineColor = {255, 255, 255}, fillColor = {76, 112, 136}, fillPattern = FillPattern.Solid, lineThickness = 3, extent = {{-8.5, -9.419}, {8.5, 9.419}})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); +end BusinessSimulation; diff --git a/BusinessSimulation/package.order b/BusinessSimulation/package.order new file mode 100644 index 0000000..a5057be --- /dev/null +++ b/BusinessSimulation/package.order @@ -0,0 +1,16 @@ +UsersGuide +ModelSettings +Examples +Stocks +Flows +SourcesOrSinks +Converters +InformationSources +MoleculesOfStructure +Sensors +Interfaces +Functions +Constants +Types +Units +Icons diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..4153cd3 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,287 @@ + EUROPEAN UNION PUBLIC LICENCE v. 1.2 + EUPL © the European Union 2007, 2016 + +This European Union Public Licence (the ‘EUPL’) applies to the Work (as defined +below) which is provided under the terms of this Licence. Any use of the Work, +other than as authorised under this Licence is prohibited (to the extent such +use is covered by a right of the copyright holder of the Work). + +The Work is provided under the terms of this Licence when the Licensor (as +defined below) has placed the following notice immediately following the +copyright notice for the Work: + + Licensed under the EUPL + +or has expressed by any other means his willingness to license under the EUPL. + +1. Definitions + +In this Licence, the following terms have the following meaning: + +- ‘The Licence’: this Licence. + +- ‘The Original Work’: the work or software distributed or communicated by the + Licensor under this Licence, available as Source Code and also as Executable + Code as the case may be. + +- ‘Derivative Works’: the works or software that could be created by the + Licensee, based upon the Original Work or modifications thereof. This Licence + does not define the extent of modification or dependence on the Original Work + required in order to classify a work as a Derivative Work; this extent is + determined by copyright law applicable in the country mentioned in Article 15. + +- ‘The Work’: the Original Work or its Derivative Works. + +- ‘The Source Code’: the human-readable form of the Work which is the most + convenient for people to study and modify. + +- ‘The Executable Code’: any code which has generally been compiled and which is + meant to be interpreted by a computer as a program. + +- ‘The Licensor’: the natural or legal person that distributes or communicates + the Work under the Licence. + +- ‘Contributor(s)’: any natural or legal person who modifies the Work under the + Licence, or otherwise contributes to the creation of a Derivative Work. + +- ‘The Licensee’ or ‘You’: any natural or legal person who makes any usage of + the Work under the terms of the Licence. + +- ‘Distribution’ or ‘Communication’: any act of selling, giving, lending, + renting, distributing, communicating, transmitting, or otherwise making + available, online or offline, copies of the Work or providing access to its + essential functionalities at the disposal of any other natural or legal + person. + +2. Scope of the rights granted by the Licence + +The Licensor hereby grants You a worldwide, royalty-free, non-exclusive, +sublicensable licence to do the following, for the duration of copyright vested +in the Original Work: + +- use the Work in any circumstance and for all usage, +- reproduce the Work, +- modify the Work, and make Derivative Works based upon the Work, +- communicate to the public, including the right to make available or display + the Work or copies thereof to the public and perform publicly, as the case may + be, the Work, +- distribute the Work or copies thereof, +- lend and rent the Work or copies thereof, +- sublicense rights in the Work or copies thereof. + +Those rights can be exercised on any media, supports and formats, whether now +known or later invented, as far as the applicable law permits so. + +In the countries where moral rights apply, the Licensor waives his right to +exercise his moral right to the extent allowed by law in order to make effective +the licence of the economic rights here above listed. + +The Licensor grants to the Licensee royalty-free, non-exclusive usage rights to +any patents held by the Licensor, to the extent necessary to make use of the +rights granted on the Work under this Licence. + +3. Communication of the Source Code + +The Licensor may provide the Work either in its Source Code form, or as +Executable Code. If the Work is provided as Executable Code, the Licensor +provides in addition a machine-readable copy of the Source Code of the Work +along with each copy of the Work that the Licensor distributes or indicates, in +a notice following the copyright notice attached to the Work, a repository where +the Source Code is easily and freely accessible for as long as the Licensor +continues to distribute or communicate the Work. + +4. Limitations on copyright + +Nothing in this Licence is intended to deprive the Licensee of the benefits from +any exception or limitation to the exclusive rights of the rights owners in the +Work, of the exhaustion of those rights or of other applicable limitations +thereto. + +5. Obligations of the Licensee + +The grant of the rights mentioned above is subject to some restrictions and +obligations imposed on the Licensee. Those obligations are the following: + +Attribution right: The Licensee shall keep intact all copyright, patent or +trademarks notices and all notices that refer to the Licence and to the +disclaimer of warranties. The Licensee must include a copy of such notices and a +copy of the Licence with every copy of the Work he/she distributes or +communicates. The Licensee must cause any Derivative Work to carry prominent +notices stating that the Work has been modified and the date of modification. + +Copyleft clause: If the Licensee distributes or communicates copies of the +Original Works or Derivative Works, this Distribution or Communication will be +done under the terms of this Licence or of a later version of this Licence +unless the Original Work is expressly distributed only under this version of the +Licence — for example by communicating ‘EUPL v. 1.2 only’. The Licensee +(becoming Licensor) cannot offer or impose any additional terms or conditions on +the Work or Derivative Work that alter or restrict the terms of the Licence. + +Compatibility clause: If the Licensee Distributes or Communicates Derivative +Works or copies thereof based upon both the Work and another work licensed under +a Compatible Licence, this Distribution or Communication can be done under the +terms of this Compatible Licence. For the sake of this clause, ‘Compatible +Licence’ refers to the licences listed in the appendix attached to this Licence. +Should the Licensee's obligations under the Compatible Licence conflict with +his/her obligations under this Licence, the obligations of the Compatible +Licence shall prevail. + +Provision of Source Code: When distributing or communicating copies of the Work, +the Licensee will provide a machine-readable copy of the Source Code or indicate +a repository where this Source will be easily and freely available for as long +as the Licensee continues to distribute or communicate the Work. + +Legal Protection: This Licence does not grant permission to use the trade names, +trademarks, service marks, or names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the copyright notice. + +6. Chain of Authorship + +The original Licensor warrants that the copyright in the Original Work granted +hereunder is owned by him/her or licensed to him/her and that he/she has the +power and authority to grant the Licence. + +Each Contributor warrants that the copyright in the modifications he/she brings +to the Work are owned by him/her or licensed to him/her and that he/she has the +power and authority to grant the Licence. + +Each time You accept the Licence, the original Licensor and subsequent +Contributors grant You a licence to their contributions to the Work, under the +terms of this Licence. + +7. Disclaimer of Warranty + +The Work is a work in progress, which is continuously improved by numerous +Contributors. It is not a finished work and may therefore contain defects or +‘bugs’ inherent to this type of development. + +For the above reason, the Work is provided under the Licence on an ‘as is’ basis +and without warranties of any kind concerning the Work, including without +limitation merchantability, fitness for a particular purpose, absence of defects +or errors, accuracy, non-infringement of intellectual property rights other than +copyright as stated in Article 6 of this Licence. + +This disclaimer of warranty is an essential part of the Licence and a condition +for the grant of any rights to the Work. + +8. Disclaimer of Liability + +Except in the cases of wilful misconduct or damages directly caused to natural +persons, the Licensor will in no event be liable for any direct or indirect, +material or moral, damages of any kind, arising out of the Licence or of the use +of the Work, including without limitation, damages for loss of goodwill, work +stoppage, computer failure or malfunction, loss of data or any commercial +damage, even if the Licensor has been advised of the possibility of such damage. +However, the Licensor will be liable under statutory product liability laws as +far such laws apply to the Work. + +9. Additional agreements + +While distributing the Work, You may choose to conclude an additional agreement, +defining obligations or services consistent with this Licence. However, if +accepting obligations, You may act only on your own behalf and on your sole +responsibility, not on behalf of the original Licensor or any other Contributor, +and only if You agree to indemnify, defend, and hold each Contributor harmless +for any liability incurred by, or claims asserted against such Contributor by +the fact You have accepted any warranty or additional liability. + +10. Acceptance of the Licence + +The provisions of this Licence can be accepted by clicking on an icon ‘I agree’ +placed under the bottom of a window displaying the text of this Licence or by +affirming consent in any other similar way, in accordance with the rules of +applicable law. Clicking on that icon indicates your clear and irrevocable +acceptance of this Licence and all of its terms and conditions. + +Similarly, you irrevocably accept this Licence and all of its terms and +conditions by exercising any rights granted to You by Article 2 of this Licence, +such as the use of the Work, the creation by You of a Derivative Work or the +Distribution or Communication by You of the Work or copies thereof. + +11. Information to the public + +In case of any Distribution or Communication of the Work by means of electronic +communication by You (for example, by offering to download the Work from a +remote location) the distribution channel or media (for example, a website) must +at least provide to the public the information requested by the applicable law +regarding the Licensor, the Licence and the way it may be accessible, concluded, +stored and reproduced by the Licensee. + +12. Termination of the Licence + +The Licence and the rights granted hereunder will terminate automatically upon +any breach by the Licensee of the terms of the Licence. + +Such a termination will not terminate the licences of any person who has +received the Work from the Licensee under the Licence, provided such persons +remain in full compliance with the Licence. + +13. Miscellaneous + +Without prejudice of Article 9 above, the Licence represents the complete +agreement between the Parties as to the Work. + +If any provision of the Licence is invalid or unenforceable under applicable +law, this will not affect the validity or enforceability of the Licence as a +whole. Such provision will be construed or reformed so as necessary to make it +valid and enforceable. + +The European Commission may publish other linguistic versions or new versions of +this Licence or updated versions of the Appendix, so far this is required and +reasonable, without reducing the scope of the rights granted by the Licence. New +versions of the Licence will be published with a unique version number. + +All linguistic versions of this Licence, approved by the European Commission, +have identical value. Parties can take advantage of the linguistic version of +their choice. + +14. Jurisdiction + +Without prejudice to specific agreement between parties, + +- any litigation resulting from the interpretation of this License, arising + between the European Union institutions, bodies, offices or agencies, as a + Licensor, and any Licensee, will be subject to the jurisdiction of the Court + of Justice of the European Union, as laid down in article 272 of the Treaty on + the Functioning of the European Union, + +- any litigation arising between other parties and resulting from the + interpretation of this License, will be subject to the exclusive jurisdiction + of the competent court where the Licensor resides or conducts its primary + business. + +15. Applicable Law + +Without prejudice to specific agreement between parties, + +- this Licence shall be governed by the law of the European Union Member State + where the Licensor has his seat, resides or has his registered office, + +- this licence shall be governed by Belgian law if the Licensor has no seat, + residence or registered office inside a European Union Member State. + +Appendix + +‘Compatible Licences’ according to Article 5 EUPL are: + +- GNU General Public License (GPL) v. 2, v. 3 +- GNU Affero General Public License (AGPL) v. 3 +- Open Software License (OSL) v. 2.1, v. 3.0 +- Eclipse Public License (EPL) v. 1.0 +- CeCILL v. 2.0, v. 2.1 +- Mozilla Public Licence (MPL) v. 2 +- GNU Lesser General Public Licence (LGPL) v. 2.1, v. 3 +- Creative Commons Attribution-ShareAlike v. 3.0 Unported (CC BY-SA 3.0) for + works other than software +- European Union Public Licence (EUPL) v. 1.1, v. 1.2 +- Québec Free and Open-Source Licence — Reciprocity (LiLiQ-R) or Strong + Reciprocity (LiLiQ-R+). + +The European Commission may update this Appendix to later versions of the above +licences without producing a new version of the EUPL, as long as they provide +the rights granted in Article 2 of this Licence and protect the covered Source +Code from exclusive appropriation. + +All other changes or additions to this Appendix require the production of a new +EUPL version. diff --git a/README.md b/README.md new file mode 100644 index 0000000..651c786 --- /dev/null +++ b/README.md @@ -0,0 +1,50 @@ +

+ +# Business Simulation Library (BSL) +A Modelica library for modeling & simulation of dynamical systems in the social sciences, e.g. business/economics, and ecology using the System Dynamics metaphor. + +## Library Description +System Dynamics offers a very general, low-level modeling paradigm, that lends itself perfectly to model, simulate, and analyze strategic business and policy issues in any kind of organization. Unlike existing aproaches the `BSL` makes use of Modelica's acausal connectors to better distinguish _material/mass_ flows from instantaneous _information_ signal flows (causal connections). The approach has the additional benefit of allowing the modeler to build more compact models in a fast and reliable fashion. + +#### Overview of the Main Classes + +| Icon | Main Class | Description | +| :-------:|:------------------|:------------| +| | __Stocks__ | Containers ("reservoirs") used to represent entities that have been stored in a specific state | +| | __Flows__ | Processes that move entities from one stock to another at a specific rate | +| | __SourcesOrSinks__ | Flows into or out of a stock with infinite capacity at a system's boundary | +| | __Converters__ | Information processing (blocks) | +| | __InformationSources__ | External information input | +| | __MoleculesOfStructure__ | Pre-built components to model _information processing_, _decision making_ and _subsystems_ in general (blocks, incubators, transceivers, and actuators) | + +Using the pre-built components modelers can start to build their own components to eventually arrive at an appropriate representation of the system in focus in a hierarchical fashion. + +## Documentation and Release Notes +You can read the documentation for the library online at:
+[https://bsl-support.de/BusinessSimulation/BusinessSimulation](https://bsl-support.de/BusinessSimulation/BusinessSimulation.html) + +[Release Notes](https://bsl-support.de/BusinessSimulation/BusinessSimulation.UsersGuide.ReleaseNotes.html) are included with the documentation and can be found there as well. + +The library was developed and tested using Wolfram System Modeler and Wolfram Mathematica.
User experience may differ when using other modeling and simulation environments. + +## License +Copyright © 2020 Guido Wolf Reichert +Licensed under the European Union Public Licence (EUPL), Version 1.2 or later (the "License") + +You may not use this work except in compliance with the License. You may obtain a copy of the License at:
+[https://eur-lex.europa.eu/eli/dec_impl/2017/863/oj](https://eur-lex.europa.eu/eli/dec_impl/2017/863/oj) + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either expressed or implied. See the License for the specific language governing permissions and limitations under the License. + + +__Modelica©__ is a registered trademark of the Modelica Association.
+__Wolfram System Modeler™__ is a trademark of Wolfram Research, Inc.
+__Wolfram Mathematica and Mathematica™__ are registered trademarks of Wolfram Research, Inc. + +## Development and Contribution +You may report bugs and other issues or simply make suggestions for future enhancements by using the Issues button. + +Please refrain from pull requests until an appropriate Contributor License Agreement (CLA) has been established. + +## Corresponding Author +

ContactInformation.png