# 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