Seth on Simulink

August 20th, 2009

A Better If-Else Construct

In a previous post, I answered a question about how to model an If-Else behavior.  Here I will restate the algorithm I want to create:

if(sel==0)
out = 2*in1;
elseif (sel==1)
out = 3*in2;

The first answer I gave relied upon a Switch block and the Conditional Input Branch Execution optimization to get an efficient If-Else construct in the model.  While this works, I don’t like reliance on an optimization to provide good behavior.  Sometimes, small changes to the model prevent Simulink from applying an optimization.  I think it is best to implement requirements explicitly.  In this post, I want to show you a way to model explicitly an If-Else conditional execution behavior.

Conditionally Executed Subsystems and Merge

The If-Else construct requires decision logic to control the execution of algorithm contained within the expression.  One way to do this is using the If block (from the Ports & Subsystems library), combined with the If Action Subsystem.  The If Action Subsystem executes based on the conditional expression in the If block.  If you have used Function Call subsystems, this is very similar.

The If Else, Else If, Action construct in Simulink blocks.

The If block provides control over If and ElseIf conditions, and there is even an option to provide an Else signal.

The Simulink If Block parameters.

This model will give you the conditional execution of the two subsystem, however, the subsystems write their outputs to separate signals.  How do you get two subsystem to write to the same signal?

Merge the Signals

The Merge block provides a way for both subsystems to write to the same signal.

The Merge Block provides a way to specify that multiple signal write to the same memory location.

In many ways, the Merge block doesn’t behave like a block with the traditional input/output relationship.  I think of it more like a jumper across multiple wires.  The merge block specifies that all signals connected to it have the same value and actually share the same memory.  This is the programming practice of specifying multiple writers to the same variable.

Generated Code with Merge

The code generated from the above model looks a lot like our original algorithm.

   34     /* If: '<Root>/If' incorporates:
   35      *  ActionPort: '<S1>/Action Port'
   36      *  ActionPort: '<S2>/Action Port'
   37      *  Inport: '<Root>/In3'
   38      *  SubSystem: '<Root>/If Action Subsystem'
   39      *  SubSystem: '<Root>/If Action Subsystem1'
   40      */
   41     if (sel == 0.0) {
   42       /* Gain: '<S1>/Gain' incorporates:
   43        *  Inport: '<Root>/In1'
   44        */
   45       out = 2.0 * u1;
   46     } else {
   47       if (sel == 1.0) {
   48         /* Gain: '<S2>/Gain' incorporates:
   49          *  Inport: '<Root>/In2'
   50          */
   51         out = 3.0 * u2;
   52       }
   53     }

Correct use of Merge

Because Merge blocks are a memory specification rather than an algorithmic construct, there are some guidelines for using merge blocks.  The documentation shows some correct and incorrect usage patterns.  If you use merge block in your model, I suggest you run the Model Advisor Check for proper Merge block usage.

Now it’s your turn

Do you use the Merge block in your models?  Leave a comment here and share your experience.

4 Responses to “A Better If-Else Construct”

  1. Bob replied on :

    A topic that has caused great trouble over the years. As you mention, Simulink doesn’t always apply the conditional execution optimization (code that has states is a common reason here) and so it is generally required that developers use the If/Action or the Switch/Action (a great alternative to an If block with u1==0, u1==1, u1==2,…).

    These always draw complaints about how many lines one needs to connect properly, how easy it is to make a mistake, and how hard it is to visually inspect. Most of the Action subsystems are more complex, with multiple inputs and outputs feeding multiple merge blocks and lines crossing everywhere.

    To deal with this, I’ve seen:
    - Put all the merge blocks in a merge subsystem to prevent lines crossing. Inside the merge subsystem, ports 1 & 3 feed the first merge block, ports 2 & 4 feed the second, or similar.
    - Change the foreground color on the Action subsystem so the lines are colored and easier to trace.
    - Use a virtual bus to bring all the signals together and then break apart without lines crossing.
    - Use local From/Goto blocks to avoid crossing signals.

    Some people also use the From/Goto to avoid having the dashed action lines crossing other lines on their way to that top port.

    And because this is so messy, just the mechanics of implementing If/Then/Else logic gets dedicated to its own subsystem so it can be inspected independently. If the logic is complex, sometimes the If block gets its own subsystem (or Stateflow chart with Boolean outputs) too.

    We encourage people to do something, but don’t have a standard. What do others do to create maintainable models as the Action subsystem I/O grows?

  2. valio replied on :

    Hello Seth!

    Read all your good articles.

    But can you please consider my question for your next article of just give me your kind shortly explanation.

    Cant build simulink model for that ODE:

    L1*x1′ + R1*x1 + M12*x2′ + 1/C1*int(x) = 0
    L2*x2′ + R2*x2 + M21*x1′ = 0
    where int(x1) = Uc

    build model like this:

    http://picspix.com/img87/5728/16333.jpg

    but it was failed..

    It’s classic quotation of LC circuit+mutal inductance bind

    Thanks a lot, and
    sorry for out of topic post.

    Regards,
    Valentino.

  3. Seth replied on :

    @Bob - You got me thinking about this. I see what you mean about the number of wires and the challenge of making sure they get connected correctly every time. I hope I’ll be able to propose some kind of solution in a future post.

    @valio - Start by rewriting the ODEs in terms of first order derivatives. This was discussed in a previous blog post about How to draw ODEs in Simulink.

  4. Bindu replied on :

    please tell me how can i get the sampling time used in simulation

Leave a Reply

Wrap code fragments inside <pre> tags, like this:

<pre class="code">
a = magic(3);
sum(a)
</pre>

If you have a "<" character in your code, either follow it with a space or replace it with "&lt;" (including the semicolon).


Seth Popinchalk is an Application Engineer for The MathWorks. He writes here about Simulink and other MathWorks tools used in Model-Based Design.
  • Mohamamd: Hi Suth, I try to simulate a load tap-changing transformer in simulink but its control part has to be...
  • Han Geerligs: Hello Guy, thanks for the clarificaton and link. However in the documentation I am missing the...
  • Guy: @Han, you probably already know, but I think it is good to share with everyone. To zoom in use the key...
  • Han Geerligs: Hi Seth, Once again I’d like to point out that my biggest accelerator is using mouse and keyboard...
  • XaL: Hi, thanks for the tips. As someone wrote in http://blogs.mathwor ks.com/seth/2009/03/ 13/new-%C2%A0rele...
  • Uba osy: Hi, in the introductory example for fuzzy logic toolbox it was noted that using non fuzzy means, you could...
  • Prashant: How can I have same example but instead AC(1 to 10V 50 or 60Hz) and DC(0.5 to 10 V) then adding AC+DC but...
  • adrian chavarro: Great tool, for educational and sicentific, simulation. I would like to know where can i place a...
  • Ashish Sadanandan: @wei, I was talking about the case where the compiler would perform the ‘model_Xdim...
  • wei: @Ashish, I agree with your observation on compiler optimization but fail to see why Han’s code would be...

These postings are the author's and don't necessarily represent the opinions of The MathWorks.