Guy and Seth on Simulink

Time to Convert to Variant Subsystems 9

Posted by Guy Rouleau,

If you are a user of Configurable Subsystems, it is time to start thinking about making the switch to Variant Systems.

Simulink Variants provide increased functionality over Configurable Subsystems:

  • They exist in two flavors: Model Variants and Subsystem Variants.
  • They can be controlled programmatically via variables in the MATLAB workspace.
  • They are in your model instead of a Simulink Library which simplifies model development.
Once you try the Simulink Variants, I guarantee you will immediately see their advantages and understand why we recommend moving away from Configurable Subsystems.

Here are some tips to help you migrate.

UPDATE - 10/15/2013: New capabilities starting in R2013b.

Upgrade Advisor

In R2012b, the Upgrade Advisor includes a check titled Identify configurable subsystem blocks for converting to variant subsystem blocks.

Upgrade Advisor

If you run the check and a configurable subsystem is found, the result will tell you that "These blocks can be upgraded to variant subsystems as they have better programmatic control and code generation capabilities."

Upgrade Advisor

Context Menu

If you right-click on a configurable subsystem (or any subsystem), you will see a new option to convert the subsystem to a variant.

Upgrade Advisor

A window will allow you to specify some details needed for the conversion.

Converting to Variant

and a new model will pop up with your new block converted to a variant subsystem. Notice the different icon in the lower left corner of the block, it indicates that the variant subsystem is configured to override variant conditions and behaves exactly like the original configurable subsystem.

New Variant Subsystem

Now it's your turn

Are you ready to move to Variant Subsystems? Let us know by leaving a comment here

9 CommentsOldest to Newest

Guy,

In the R2013a release notes, it looks like it is no longer required to create a Simulink.Variant object in the base workspace for each variant subsystem. This requirement is very inconvenient, to the point that I am currently using another method (programmatically changing the ‘ReferenceBlock’ parameter of sets of masked library components, which is only slightly less inconvenient) to implement switching between subsystem variants.

The functionality that I would like to see is to have each variant subsytem block select its active variant based on the value of an expression (which can reference variables in the base workspace, including fields of structs, enumerations, etc.). But no Simulink.Variable objects or other configuration information should be needed in the base workspace – it should be stored in the model itself.

Can you clarify if this behavior is possible in R2013a? (That is, can variant subsystems be used without needing to define anything in the base workspace?)

Thanks,
John

@John: You are not the only user who requested this feature. Variant objects are useful in some cases, but for some cases users feel they are redundant.

I confirm that what you are looking for is available in R2013a. In the Variant dialog, you can now give the name of a variant object, OR a boolean condition expression that will be evaluated in the MATLAB workspace. For example you could type “a ==1″ where “a” is defined in the base workspace.

The following documentation page covers this new behavior:

http://www.mathworks.com/help/simulink/ug/how-variant-controls-work.html

Give this a try ans let us know if this behaves as you expect.

@Guy: Thanks for the info. I updated to 2013a, and it behaves as described, which is a big improvement over having to create Simulink.Variant objects in the base workspace.

Unfortunately, for my projects, it looks like variant subsystems still lack the flexibility we need. Our models contain multiple instances of masked library components. To accommodate different simulation scenarios, many of these library blocks have several different versions (high fidelity (nonlinear), low fidelity (linearized), null/constant (for unused sections of the model), etc.). So for a given simulation, I might want the blocks in Subsystem A to use the high-fidelity variant, Subsystem B to use low-fidelity, and Subsystem C to use the null version. In my opinion, the best way to implement this would be to have the library blocks each contain a variant subsystem, with the condition being determined by the value of a mask parameter. Then, different instances of this library block in the model can have different active variants, controlled by setting the value of the mask parameter (either directly or having the mask parameter point to a workspace variable). In my case, it would end up pointing to a field within a large parameter struct that we use to hold all of our model parameters in the base workspace.

However, I get Simulink errors when I set a variant control to point to a mask parameter – it looks like they can only refer to a base workspace variable. This precludes having different instances of a library block use different active variants at runtime, unless I am not understanding something. The older ‘Configurable Subsystem’ blocks have the ‘BlockChoice’ parameter, which can be set for instances of library blocks. But I haven’t found a way to make this parameter point to a workspace variable, so it can only be changed for a given simulation run via set_param() for each block instance.

Anyway, I appreciate the enhancements in R2013a. If you have any thoughts or questions about my particular use-case, I’d be happy to discuss it further.

-John

@Guy: Thanks for the link – that behavior is very close to what I’m looking for. I think in many cases it could work for us, except for the following twist: Some of our library components (blocks) are made up of several subsystems (also library blocks). I would like to be able to use variant subsystems to implement our various model versions for each of these subsystems. For example, I have a masked library block named ‘ABC’, which contains subsystems ‘X’ and ‘Y’, which are also instances of library blocks. I have three variants of X and two of Y: X_std, X_nlin, X_null, Y_std, Y_nlin. My model then contains multiple instances of ABC : ABC001, ABC002, etc. In general, each instance of ABC has different active variants of its X and Y subsytems for a given run. So ABC001 might have X_nlin and Y_std, while ABC002 has X_null and Y_nlin.

The method described in the link you posted does not work for subsystems inside of a library – I get the following error:

Error evaluating ‘MaskCallback’ callback of (mask) ‘(model name)/ABC001′.
Attempting to override parameters of ‘(model name)/ABC001/X_variant_subsystem’ which is inside a library link.

So it looks like the best I can do is to create a set of library blocks corresponding to each combination of X and Y variants: X_std and Y_std, X_nlin and Y_std, etc., and then use a variant subsystem block containing each of these permutations as the library block that gets instantiated in the model. The drawback here is having to maintain a lot more block diagrams (5 for the subcomponent variants plus 6 for each of the permutations), instead of just 6 (1 for the component plus the 5 subcomponent variants).

P.S. Our models are structured this way because they consist of many instances each of a large set of library blocks (500 to 1000 total blocks). The models and libraries are designed such that the block connectivity does not change for any of the possible variants – the variants only modify the block’s internal behavior during a simulation. Changing the connectivity between components is handled by creating different models, while all of the control of component behavior is handled via block parameters. Hence the interest I have in implementing variant subsystems in a way that is similar to block/mask parameters – basically, keeping connectivity/topology (external) and component behavior (internal) separated.

To handle the large number of parameters needed, I have a single struct in the base workspace, with a field for each component: params.ABC001, params.DEF123, etc. The blocks all have a mask parameter ‘ComponentParameters’, that is set to point to the corresponding field of ‘params’ (so get_param(‘myModel/ABC002′,’ComponentParameters’) returns ‘params.ABC002′.) Ideally, I would have the parameter struct for each component contain fields that define its active variants: params.ABC001.X_variant = ‘X_nlin’, params.ABC002.Y_variant = ‘y_std’, etc., and the desired variants would simply be determined by setting these fields in the base workspace before a model run – no mask callbacks or set_param() calls would be needed.

Thanks again for the info, and for all of your informative blog posts.

-John

A quick followup note for future reference:

The error I described in the previous comment when trying to use subsystem variants with library blocks was caused by my forgetting to enable the ‘Allow library block to modify its contents’ parameter. This can be set in the Mask Editor -> Initialization tab, or via the command line using: set_param(gcb,’MaskSelfModifiable’,'on’).

When this parameter is set correctly, everything works as advertised.

@Guy: thanks again for your help.

-John

John: I’m having the same issue, and it’s really frustrating to have to jump through all these hoops.

Variant subsystem selection needs to have some method of accessing to the mask workspace instead of the base workspace. I’m working on blocks for a library which is being used by some customers of ours. So I have no control over the base workspace contents. It’s up to the end users, and it’s also up to the end user how to configure their variants, on a case-by-case basis (i.e. individual instance of a library block).

@Jason:

You can have the mask initialization callback, which has access to variables in the mask workspace [1], use one of these variables to set the ‘OverrideUsingVariant’ parameter. This could be as simple as:

set_param(gcb,’OverrideUsingVariant’,MyMaskVariable)

where ‘MyMaskVariable’ is a regular mask parameter, or you could add logic to select from available variants based on the values of your mask variables.

I agree that the current implementation is more convoluted than it needs to be. The way I see it, a given variant subsystem must have one and only one active variant at a time. Why not just have an ‘ActiveVariant’ parameter that is a ‘popup’ type, with the choices being a list of block names (or a ‘VariantName’ parameter) of the available variant blocks? This enforces the “one and only one” aspect of variants, and is far simpler than the current implementation. With the ‘popup’ type control, you could use logic to set the parameter value using base workspace values, other parameters, etc., either in the mask initialization, or in a model callback. And as a standard mask parameter, it could be promoted to a parent system, etc. [2].

To me, this would be both simpler and more flexible than having to spread the selection logic among multiple Variant Controls, and having to store and load Simulink.Variant objects separate from the model. For example, what happens if the boolean conditions in the Variant Controls are not mutually exclusive, or there is a case where they all evaluate to |false|? I would much rather put all the selection logic in one place (mask initialization or model callback), where it is far easier to catch logic errors.

Notes:
[1] You can access base workspace variables in the mask initialization by dereferencing them in a mask parameter (e.g. create a parameter BaseWSReference, with its ‘Evaluate’ attribute enabled, and its value set to the name of the base workspace variable you want to access.)

[2] I have unsuccessfully tried to promote the ‘OverrideUsingVariant’ parameter of a variant subsystem to its parent’s mask, but it appears that the variant-related parameters are non-standard parameters that cannot be promoted.

Hi all!

I have tried a similar approach as described in
http://www.mathworks.com/matlabcentral/answers/91562
except the fact, that the user of the masked block is also allowed to enter a variable as mask parameter (not only a value itself). This variable lies in the

base workspace and contains the value which is used to select the appropriate subsystem variant.

Therefore I use the ‘evalin’ function to evaluate the passed variable inside the callback function of the mask parameter.

So far, everything works just fine: The current active variant is changed, as the user of the masked block changes the corresponding mask parameter.

The only problem is, that if the VALUE of the passed varialbe does change in the workspace, the callback function of the mask parameter is not executed and thus

the active variant is not updated.

My first idea to solve this problem was to use the ‘InitFcn’ callback of the masked block instead of the callback function of the mask parameter, which should be

executed BEFORE the simulation starts.
When trying this, i get following error:
‘attempted to change the active variant during simulation. The active variant must be configured before the simulation is started’

Another approach was to use the initialization callback function of the mask, which produces the same error.

Then I tried the LoadFcn callback of the masked block, which does it’s job fine, but this is very inconvenient, since every time the corresponding workspace

variable changes, the model would have to be loaded…

Thank’s in advance, I appreciate any help!

PS: the reason why I don’t select the active variant through a workspace variable directly is, because I do not have control over the base workspace, i.e. the

variable holding the information about the variant to select, can have any name and can lie within an arbitrarily structured object, struct, etc.
That’s why I prompt the user of the masked block to specifiy a workspace variable and then perform the evalin function.

Add A Comment

What is 3 + 5?

Preview: hide

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