]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.tutorial/scl/Tutorial/3.01 Simulation sequences.md
Import org.simantics.scl.tutorial from incubator SVN repo
[simantics/platform.git] / bundles / org.simantics.scl.tutorial / scl / Tutorial / 3.01 Simulation sequences.md
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 (file)
index 0000000..81108c0
--- /dev/null
@@ -0,0 +1,116 @@
+# Simulation sequences\r
+\r
+## Sequence monad\r
+    \r
+::data[Simantics/Sequences/Sequence]\r
+    \r
+We call the sequence *instantious*, if its duration is zero, i.e, the sequence finishes immediately after started.\r
+\r
+A cooking recipe is an example of a sequence in the real world. Its return value could be for example the success \r
+indication of the cooking process.\r
+\r
+    instance Monad Sequence\r
+\r
+In order to build complex sequences from simple primitives, the sequences implement\r
+[Monad](http://en.wikipedia.org/wiki/Monad_%28functional_programming%29) operations and\r
+its laws. These are\r
+\r
+::value[Prelude/return, Prelude/>>=]\r
+    \r
+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. \r
+\r
+::value[Prelude/>>, Prelude/fmap, Prelude/join, Prelude/sequence, Prelude/repeatForever]\r
+    \r
+These operations are derived from the primitive monad operations.\r
+The sequence `seqA >> seqB` behaves first like `seqA` and when it has finished it\r
+continues like `seqB`. The sequence `fmap f seq` maps the result of the sequence `seq` by the function\r
+`f`. The sequence `join seq` first behaves like the sequence `seq` and then like the sequence `seq` returned.\r
+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.\r
+\r
+## Actions\r
+\r
+    effect Action\r
+    \r
+`<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.\r
+\r
+::value[Simantics/Sequences/time, Simantics/Sequences/getVar, Simantics/Sequences/setVar]\r
+    \r
+::value[Simantics/Sequences/execute]\r
+\r
+Multiple actions happening at the same time may be written either as separate sequences:\r
+\r
+    mdo execute (setVar "SP1#SP_VALUE" 13)\r
+        execute (setVar "SP2#SP_VALUE" 14)\r
+\r
+or as one sequence with more complicated action:\r
+\r
+    execute do\r
+        setVar "SP1#SP_VALUE" 13\r
+        setVar "SP2#SP_VALUE" 14\r
+\r
+## Controlling time\r
+\r
+::value[Simantics/Sequences/waitStep]\r
+\r
+::value[Simantics/Sequences/waitUntil, Simantics/Sequences/wait]\r
+    \r
+::value[Simantics/Sequences/waitCondition]\r
+\r
+## Parallel execution\r
+\r
+::value[Simantics/Sequences/fork, Simantics/Sequences/halt, Simantics/Sequences/stop]\r
+\r
+## Semantics\r
+\r
+Although the simulation sequences support threading, its semantics is deterministic. This is ensured by the following equivalences:\r
+\r
+    halt >> seqA                                       = halt\r
+    stop >> seqA                                       = stop\r
+    fork (execute actionA >> seqA) >> seqB             = execute actionA >> fork seqA >> seqB\r
+    fork (waitStep >> seqA) >> execute actionB >> seqB = execute actionB >> fork seqA >> seqB\r
+    fork (waitStep >> seqA) >> waitStep >> seqB        = waitStep >> fork seqA >> seqB\r
+    fork halt >> seqB                                  = seqB\r
+    fork seqA >> halt                                  = seqA\r
+    fork stop >> seqB                                  = stop\r
+    fork (waitStep >> seqA) >> stop                    = stop\r
+\r
+## Using the sequences with Apros\r
+\r
+In order to run the sequence in Apros, function \r
+\r
+::value[Apros/Sequences/runSequence]\r
+\r
+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).\r
+\r
+    import "Apros/Sequences"\r
+    runSequence mdo\r
+        fork $ repeatForever mdo\r
+            waitCondition (getVar "TA01#TA11_LIQ_LEVEL" >= 3.0)\r
+            execute (setVar "BP01#PU11_SPEED_SET_POINT" 0.0)\r
+            wait 1\r
+        fork $ repeatForever mdo\r
+            waitCondition (getVar "TA01#TA11_LIQ_LEVEL" <= 2.0)\r
+            execute (setVar "BP01#PU11_SPEED_SET_POINT" 100.0)\r
+            wait 1\r
+\r
+## Examples\r
+\r
+Check that pressure of the point stays below a certain value:\r
+\r
+    fork mdo waitCondition (getVar "POINT1#PO11_PRESSURE" > 120.0)\r
+             execute (print "Error! Error!")\r
+             stop\r
+\r
+Check that the valve is closed 10 seconds after the operator presses the button:\r
+\r
+    fork $ repeatForever mdo\r
+        waitCondition (getVar "BUTTON#BINARY_VALUE")\r
+        fork mdo\r
+            wait 10\r
+            valvePos <- execute (getVar "VALVE#VA11_POSITION")\r
+            if valvePos == 0\r
+            then return () // OK\r
+            else mdo\r
+                execute (print "Error! Error!")\r
+                stop\r
+\r