X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.scl.tutorial%2Fscl%2FTutorial%2F3.01%20Simulation%20sequences.md;fp=bundles%2Forg.simantics.scl.tutorial%2Fscl%2FTutorial%2F3.01%20Simulation%20sequences.md;h=81108c0e7c078f56be3bcf1ce62404d23c8aa0af;hb=39fd9bd29b18a2f7abe62fb13da3359b3618dda7;hp=0000000000000000000000000000000000000000;hpb=f024c0a7208e379a82f0ab51a71a123f9bb2a2bb;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.scl.tutorial/scl/Tutorial/3.01 Simulation sequences.md b/bundles/org.simantics.scl.tutorial/scl/Tutorial/3.01 Simulation sequences.md new file mode 100644 index 000000000..81108c0e7 --- /dev/null +++ b/bundles/org.simantics.scl.tutorial/scl/Tutorial/3.01 Simulation sequences.md @@ -0,0 +1,116 @@ +# Simulation sequences + +## Sequence monad + +::data[Simantics/Sequences/Sequence] + +We call the sequence *instantious*, if its duration is zero, i.e, the sequence finishes immediately after started. + +A cooking recipe is an example of a sequence in the real world. Its return value could be for example the success +indication of the cooking process. + + instance Monad Sequence + +In order to build complex sequences from simple primitives, the sequences implement +[Monad](http://en.wikipedia.org/wiki/Monad_%28functional_programming%29) operations and +its laws. These are + +::value[Prelude/return, Prelude/>>=] + +The sequence `return v` has zero duration, it does not modify the simulator state and returns `v`. The sequence `seqA >>= f` is a sequence that first behaves like `seqA`, and when it has completed and returned a value `resultA`, continues like the sequence `f resultA`. In other words, `(>>=)` concatenates two sequences and the behavior of the latter sequence may depend on the return value of the former sequence. + +::value[Prelude/>>, Prelude/fmap, Prelude/join, Prelude/sequence, Prelude/repeatForever] + +These operations are derived from the primitive monad operations. +The sequence `seqA >> seqB` behaves first like `seqA` and when it has finished it +continues like `seqB`. The sequence `fmap f seq` maps the result of the sequence `seq` by the function +`f`. The sequence `join seq` first behaves like the sequence `seq` and then like the sequence `seq` returned. +The sequence `sequence seqs` executes every sequence in the container `seqs` sequentially. The container can be for example list or `Maybe`. The sequence `repeatForever seq` repeats the sequence `seq` forever, never returning. + +## Actions + + effect Action + +` a` is an instantious operation happening in the simulator and returning a value of type `a`. It can be a pure reading operation, but may also modify the simulator state. The duration of an action is always zero. + +::value[Simantics/Sequences/time, Simantics/Sequences/getVar, Simantics/Sequences/setVar] + +::value[Simantics/Sequences/execute] + +Multiple actions happening at the same time may be written either as separate sequences: + + mdo execute (setVar "SP1#SP_VALUE" 13) + execute (setVar "SP2#SP_VALUE" 14) + +or as one sequence with more complicated action: + + execute do + setVar "SP1#SP_VALUE" 13 + setVar "SP2#SP_VALUE" 14 + +## Controlling time + +::value[Simantics/Sequences/waitStep] + +::value[Simantics/Sequences/waitUntil, Simantics/Sequences/wait] + +::value[Simantics/Sequences/waitCondition] + +## Parallel execution + +::value[Simantics/Sequences/fork, Simantics/Sequences/halt, Simantics/Sequences/stop] + +## Semantics + +Although the simulation sequences support threading, its semantics is deterministic. This is ensured by the following equivalences: + + halt >> seqA = halt + stop >> seqA = stop + fork (execute actionA >> seqA) >> seqB = execute actionA >> fork seqA >> seqB + fork (waitStep >> seqA) >> execute actionB >> seqB = execute actionB >> fork seqA >> seqB + fork (waitStep >> seqA) >> waitStep >> seqB = waitStep >> fork seqA >> seqB + fork halt >> seqB = seqB + fork seqA >> halt = seqA + fork stop >> seqB = stop + fork (waitStep >> seqA) >> stop = stop + +## Using the sequences with Apros + +In order to run the sequence in Apros, function + +::value[Apros/Sequences/runSequence] + +has been defined. It starts automatically starts simulation, if it is not yet running. When all simulation threads are halted or some thread calls `stop` the simulation is stopped. The sequence can also aborted by aborting the SCL-command (red box in the upper right corner of the console). + + import "Apros/Sequences" + runSequence mdo + fork $ repeatForever mdo + waitCondition (getVar "TA01#TA11_LIQ_LEVEL" >= 3.0) + execute (setVar "BP01#PU11_SPEED_SET_POINT" 0.0) + wait 1 + fork $ repeatForever mdo + waitCondition (getVar "TA01#TA11_LIQ_LEVEL" <= 2.0) + execute (setVar "BP01#PU11_SPEED_SET_POINT" 100.0) + wait 1 + +## Examples + +Check that pressure of the point stays below a certain value: + + fork mdo waitCondition (getVar "POINT1#PO11_PRESSURE" > 120.0) + execute (print "Error! Error!") + stop + +Check that the valve is closed 10 seconds after the operator presses the button: + + fork $ repeatForever mdo + waitCondition (getVar "BUTTON#BINARY_VALUE") + fork mdo + wait 10 + valvePos <- execute (getVar "VALVE#VA11_POSITION") + if valvePos == 0 + then return () // OK + else mdo + execute (print "Error! Error!") + stop +