Simscape Lang
Simscape Lang
Simscape Lang
Language Guide
R2022b
How to Contact MathWorks
Phone: 508-647-7000
v
Declare Component Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-13
Parameter Units . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-13
Case Sensitivity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-13
vi Contents
Enabled Component . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-58
vii
Attribute Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-104
Attribute Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-104
Model Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-104
Member Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-105
Advanced Techniques
3
Mode Chart Modeling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-2
About Mode Charts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-2
Mode Chart Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-2
Mode Chart Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-3
Enumerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-14
Enumerations in Simscape Language . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-14
Specifying Display Strings for Enumeration Members . . . . . . . . . . . . . . . 3-15
Evaluating Enumeration Members . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-16
Using Enumeration in Event Variables and when Clauses . . . . . . . . . . . . 3-17
Using Enumeration in Predicates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-17
Using Enumeration in Function Arguments . . . . . . . . . . . . . . . . . . . . . . . 3-18
Rules and Restrictions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-19
viii Contents
Case Study — Battery Pack with Fault Using Arrays . . . . . . . . . . . . . . . . 3-33
Overview of the Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-33
Introducing the Fault . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-35
Declaring Arrays of Member Components . . . . . . . . . . . . . . . . . . . . . . . . 3-36
Connecting the Components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-37
Outputting Data as a Numeric Array . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-41
Battery Pack Block . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-42
ix
Customize Block Display . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-41
Language Reference
5
x Contents
Isothermal Liquid Domain . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-11
xi
1
The Simscape language makes modeling physical systems easier and more intuitive. It lets you define
custom components as textual files, complete with parameterization, physical connections, and
equations represented as acausal implicit differential algebraic equations (DAEs). The components
you create can reuse the physical domain definitions provided with Simscape to ensure that your
components are compatible with the standard Simscape components. You can also add your own
physical domains. You can automatically build and manage block libraries of your Simscape
components, enabling you to share these models across your organization.
See Also
Related Examples
• “Model Linear Resistor in Simscape Language” on page 1-3
More About
• “Typical Simscape Language Tasks” on page 1-6
• “Simscape File Types and Structure” on page 1-8
• “Creating Custom Components” on page 1-13
• “When to Define a New Physical Domain” on page 1-11
1-2
Model Linear Resistor in Simscape Language
V =I·R
where
A Simscape file that implements such a linear resistor might look as follows:
component my_resistor
% Linear Resistor
% The voltage-current (V-I) relationship for a linear resistor is V=I*R,
% where R is the constant resistance in ohms.
%
% The positive and negative terminals of the resistor are denoted by the
% + and - signs respectively.
nodes
p = foundation.electrical.electrical; % +:left
n = foundation.electrical.electrical; % -:right
end
variables
i = { 0, 'A' }; % Current
v = { 0, 'V' }; % Voltage
end
parameters
R = { 1, 'Ohm' }; % Resistance
end
branches
i : p.i -> n.i;
end
equations
assert(R>0)
v == p.v - n.v;
v == i*R;
end
end
The first line indicates that this is a component file, and the component name is my_resistor.
Following this line, there are optional comments that customize the block name and provide a short
description in the block dialog box. Comments start with the % character.
The next section of the Simscape file is the declaration section. For the linear resistor, it declares:
1-3
1 Simscape Language Fundamentals
All the public component variables appear on the Variables tab of the dialog box of the block
generated from the component file. To specify how the name of the variable appears in the dialog
box, use the comment immediately following the variable declaration (Current and Voltage).
• Parameter R, with a default value of 1 Ohm, specifying the resistance value. This parameter
appears in the dialog box of the block generated from the component file, and can be modified
when building and simulating a model. The comment immediately following the parameter
declaration, Resistance, specifies how the name of the block parameter appears in the dialog
box.
The branches section establishes the relationship between the component Through variable and the
component nodes (and therefore the domain Through variable). The i : p.i -> n.i statement
indicates that the current through the resistor flows from node p to node n.
• The assert construct performs parameter validation, by checking that the resistance value is
greater than zero. If the block parameter is set incorrectly, the assert triggers a run-time error.
• The first equation, v == p.v - n.v, establishes the relationship between the component Across
variable and the component nodes (and therefore the domain Across variable). It defines the
voltage across the resistor as the difference between the node voltages.
• The second equation, v == i*R, describes the operation of a linear resistor based on Ohm’s law.
It defines the mathematical relationship between the component Through and Across variables,
current i and voltage v, and the parameter R.
The == operand used in these equations specifies continuous mathematical equality between the
left- and right-hand side expressions. This means that the equation does not represent assignment
but rather a symmetric mathematical relationship between the left- and right-hand operands. This
equation is evaluated continuously throughout the simulation.
The following illustration shows the resulting custom block, based on this component file.
1-4
Model Linear Resistor in Simscape Language
To learn more about writing Simscape files and converting your textual components into custom
Simscape blocks, refer to the following table.
For... See...
Declaration semantics, rules, and examples “Declaring Domains and Components” on page 2-
3
Detailed information on writing component “Defining Component Equations” on page 2-26
equations
Annotating the component file to improve the “Customizing the Block Name and Appearance”
generated block cosmetics and usability on page 4-29
Generating Simscape blocks from component files “Generating Custom Blocks from Simscape
Component Files” on page 4-2
See Also
Related Examples
• “Mechanical Component — Spring” on page 2-91
• “Electrical Component — Ideal Capacitor” on page 2-92
• “No-Flow Component — Voltage Sensor” on page 2-93
• “Grounding Component — Electrical Reference” on page 2-94
• “Composite Component — DC Motor” on page 2-96
More About
• “What Is the Simscape Language?” on page 1-2
• “Simscape File Types and Structure” on page 1-8
• “Creating Custom Components” on page 1-13
• “When to Define a New Physical Domain” on page 1-11
1-5
1 Simscape Language Fundamentals
The following table lists typical tasks along with links to background information and examples.
“Parameterizing Composite
Components” on page 2-62
“Specifying Component
Connections” on page 2-66
Generate a custom block from a “Selecting Component File Directly “Deploy a Component File in Block
Simscape component file from Block” on page 4-3 Diagram” on page 4-5
1-6
Typical Simscape Language Tasks
1-7
1 Simscape Language Fundamentals
In this section...
“Simscape File Type” on page 1-8
“File and Model Types” on page 1-8
“Model File Structure” on page 1-9
The Simscape file contains language constructs that do not exist in MATLAB. They are specific to
modeling physical objects. However, the Simscape file incorporates the basic MATLAB programming
syntax at the lowest level.
• directory_on_the_path/+MyPackage/MyComponent.ssc
• directory_on_the_path/+MyPackage/+Subpackage/.../MyComponent.ssc
For more information on packaging your Simscape files, see “Organizing Your Simscape Files” on
page 4-21.
• Domain models describe the physical domains through which component models exchange energy
and data. These physical domains correspond to port types, for example, translational, rotational,
hydraulic, and so on.
• Component models describe the physical components that you want to model, that is, they
correspond to Simscape blocks.
For example, to implement a variable area hydraulic orifice that is different from the one in the
Simscape Foundation library, you can create a component model, MyVarOrifice.ssc, based on the
standard hydraulic domain included in the Foundation library. However, to implement a simple
thermohydraulic orifice, you can create a domain model first, t_hyd.ssc (a custom hydraulic domain
that accounts for fluid temperature), and then create the component model that references it,
MyThhOrifice.ssc, as well as all the other component models based on this custom domain and
needed for modeling thermohydraulic systems. For an example, see “Custom Library with
Propagation of Domain Parameters” on page 2-101.
The third file type, function files, represents Simscape functions. Simscape functions model a class of
pure first-order mathematical functions with explicit input-output relationship. Their purpose is to
reuse expressions in equations and member declarations of multiple components.
1-8
Simscape File Types and Structure
ModelClass Identifier
where
For example:
domain rotational
or
component spring
A Simscape file splits the model description into the following pieces:
• Interface or Declaration — Declarative section similar to the MATLAB class system declarations:
• For domain models, declares variables (Across and Through) and parameters
• For component models, declares nodes, inputs and outputs, parameters, and variables
• Implementation (only for component models) — Describes run-time functionality of the model.
Implementation consists of the following sections:
• Structure — For composite components, describes how the constituent components' ports are
connected to one another and to the external inputs, outputs, and nodes of the top-level
component. Executed once for each instance of the component in the top-level model during
model compilation.
• Equation — For behavioral components, describes underlying equations. Executed throughout
simulation.
• Events — For discrete event modeling, lets you perform discrete changes on continuous
variables. Executed throughout simulation.
Like the MATLAB class system, these constructs and functions act on a specific instance of the class.
Unlike the MATLAB class system, the object is not passed as the first argument to function. This
reduces syntax with no loss of functionality.
See Also
Related Examples
• “Model Linear Resistor in Simscape Language” on page 1-3
More About
• “What Is the Simscape Language?” on page 1-2
1-9
1 Simscape Language Fundamentals
1-10
When to Define a New Physical Domain
You do not need to define a new physical domain to create custom components. Simscape software
comes with several predefined domains, such as mechanical translational, mechanical rotational,
electrical, hydraulic, and so on. These domains are included in the Foundation library, and are the
basis of Simscape Foundation blocks, as well as those in Simscape add-on products (for example,
Simscape Fluids™ or Simscape Electrical™ blocks). If you want to create a custom component to be
connected to the standard Simscape blocks, use the Foundation domain definitions. For a complete
listing of the Foundation domains, see “Foundation Domain Types and Directory Structure” on page
6-2.
You need to define a new domain only if the Foundation domain definitions do not satisfy your
modeling requirements. For example, to enable modeling electrochemical systems, you need to create
a new domain with the appropriate Across and Through variables. If you need to model a simple
thermal hydraulic system, you can create a custom hydraulic domain that accounts for fluid
temperature by supplying a domain-wide parameter (for an example, see “Propagation of Domain
Parameters” on page 2-99).
Once you define a custom physical domain, you can use it for defining nodes in your custom
components. These nodes, however, can be connected only to other nodes of the same domain type.
For example, if you define a custom hydraulic domain as described above and then use it when
creating custom components, you will not be able to connect these nodes with the regular hydraulic
ports of the standard Simscape blocks, which use the Foundation hydraulic domain definition.
See Also
More About
• “Foundation Domain Types and Directory Structure” on page 6-2
• “How to Define a New Physical Domain” on page 1-12
• “Declare a Mechanical Rotational Domain” on page 2-20
1-11
1 Simscape Language Fundamentals
A domain file must begin with the domain keyword, followed by the domain name, and be terminated
by the end keyword.
Domain files contain only the declaration section. Two declaration blocks are required:
• The Across variables declaration block, which begins with the variables keyword and is
terminated by the end keyword. It contains declarations for all the Across variables associated
with the domain. A domain model class definition can contain multiple Across variables, combined
in a single variables block.
• The Through variables declaration block, which begins with the variables(Balancing =
true) keyword and is terminated by the end keyword. It contains declarations for all the Through
variables associated with the domain. A domain model class definition can contain multiple
Through variables, combined in a single variables(Balancing = true) block.
For more information on declaring the Through and Across variables, see “Declare Through and
Across Variables for a Domain” on page 2-6.
The parameters declaration block is optional. If present, it must begin with the parameters keyword
and be terminated by the end keyword. This block contains declarations for domain parameters.
These parameters are associated with the domain and can be propagated through the network to all
components connected to the domain. For more information, see “Working with Domain Parameters”
on page 2-99.
For an example of a domain file, see “Declare a Mechanical Rotational Domain” on page 2-20.
See Also
Related Examples
• “Declare a Mechanical Rotational Domain” on page 2-20
• “Declare Through and Across Variables for a Domain” on page 2-6
More About
• “When to Define a New Physical Domain” on page 1-11
• “Working with Domain Parameters” on page 2-99
1-12
Creating Custom Components
• Behavioral — A model that is implemented based on its physical behavior, described by a system
of mathematical equations. An example of a behavioral block implementation is the Variable
Orifice block.
• Composite — A model that is constructed out of other blocks, connected in a certain way. An
example of a composite, or structural, block implementation is the 4-Way Directional Valve block
(available with Simscape Fluids Isothermal block libraries), which is constructed based on four
Variable Orifice blocks.
Simscape language lets you create new behavioral and composite models when your design
requirements are not satisfied by the libraries of standard blocks provided with Simscape and its add-
on products.
A prerequisite to creating components is having the appropriate domains for the component nodes.
You can use Simscape Foundation domains or create your own, as described in “How to Define a New
Physical Domain” on page 1-12.
A component file must begin with the component keyword, followed by the component name, and be
terminated by the end keyword.
Component files may contain the following sections, appearing in any order:
• Declaration — Contains all the member class declarations for the component, such as parameters,
variables, nodes, inputs, and outputs. Each member class declaration is a separate declaration
block, which begins with the appropriate keyword (corresponding to the member class) and is
terminated by the end keyword. For more information, see the component-related sections and
links in “Declaring Domains and Components” on page 2-3.
• Branches — Establishes the relationship between the component variables and nodes. This
relationship connects the Through and Across variables declared inside the component to the
domain Through and Across variables. For more information, see “Define Relationship Between
Component Variables and Nodes” on page 2-23.
• Structure — Declares the component connections for composite models. For more information, see
“Specifying Component Connections” on page 2-66.
1-13
1 Simscape Language Fundamentals
• Equation — Declares the component equations for behavioral models. These equations may be
conditional, and are applied throughout the simulation. For more information, see “Defining
Component Equations” on page 2-26.
• Events — Manages the event updates. Event modeling lets you perform discrete changes on
continuous variables. For more information, see “Discrete Event Modeling” on page 2-54.
• Annotations — Lets you provide annotations in a component file that control various cosmetic
aspects of a Simscape block generated from this component. See annotations for more
information.
After you have created the textual component files, convert them into a library of blocks using the
procedure described in “Building Custom Block Libraries” on page 4-21. You can control the block
names and appearance by using optional comments in the component file. For more information, see
“Customizing the Block Name and Appearance” on page 4-29.
See Also
Related Examples
• “Mechanical Component — Spring” on page 2-91
• “Electrical Component — Ideal Capacitor” on page 2-92
• “No-Flow Component — Voltage Sensor” on page 2-93
• “Grounding Component — Electrical Reference” on page 2-94
• “Composite Component — DC Motor” on page 2-96
More About
• “What Is the Simscape Language?” on page 1-2
• “Typical Simscape Language Tasks” on page 1-6
• “Declaring Domains and Components” on page 2-3
• “Defining Component Equations” on page 2-26
• “About Composite Components” on page 2-60
• “Building Custom Block Libraries” on page 4-21
1-14
2
2-2
Declaring Domains and Components
• The declaration section of a domain file is where you define the Through and Across variables for
the domain. You can also define the domain-wide parameters, if needed.
• The declaration section of a component file is where you define all the variables, parameters,
nodes, inputs, and outputs that you need to describe the connections and behavior of the
component. These are called member declarations.
In order to use a variable, parameter, and so on, in other sections of a component file (such as
branches, equations, and so on), you have to first define it in the declaration section.
Definitions
The declaration section of a Simscape file may contain one or more member declarations.
Term Definition
Member • A member is a piece of a model’s declaration. The collection of all members
of a model is its declaration.
• It has an associated data type and identifier.
• Each member is associated with a unique member class. Additionally,
members may have some specific attributes.
Member class • A member class is the broader classification of a member.
• The following is the set of member classes: variables (domain or
component variables), parameters, inputs, outputs, nodes,
components. The components member class, not to be confused with the
component model class, is discussed in “Declaring Member Components”
on page 2-61.
• Two members may have the same type, but be of different member classes.
For example, a parameter and an input may have the same data type, but
because they are of different member classes, they behave differently.
Member Declarations
The following rules apply to declaring members:
2-3
2 Creating Custom Components and Domains
• Like the MATLAB class system, declared members appear in a declaration block:
<ModelClass> <Identifier>
<MemberClass>
% members here
end
...
end
• Unlike the MATLAB class system, <MemberClass> may take on any of the available member
classes and dictates the member class of the members defined within the block.
• Like the MATLAB class system, each declared member is associated with a MATLAB identifier,
<Identifier>. Unlike the MATLAB class system, members must be declared with a right-hand
side value.
<ModelClass> <Identifier>
<MemberClass>
<Identifier> = <Expression>;
% more members
end
...
end
• <Expression> on the right-hand side of the equal sign (=) is a MATLAB expression. It could be a
constant expression, or a call to a MATLAB function.
• The MATLAB class of the expression is restricted by the class of the member being declared. Also,
the data type of the expression dictates data type of the declared member.
Member Summary
The following table provides the summary of member classes.
2-4
Declaring Domains and Components
{ value , 'unit' }
where value is a real matrix, including a scalar, and unit is a valid unit string, defined in the unit
registry, or 1 (unitless). Depending on the member type, certain restrictions may apply. See
respective reference pages for details.
For example, this is how you declare a parameter as a value with unit:
To declare a unitless parameter, you can either use the same syntax:
par1 = value;
Internally, however, this parameter will be treated as a two-member value-unit cell array { value ,
'1' }.
See Also
Related Examples
• “Declare a Spring Component” on page 2-21
• “Declare a Mechanical Rotational Domain” on page 2-20
• “Declare Through and Across Variables for a Domain” on page 2-6
• “Declare Component Variables” on page 2-8
• “Declare Component Parameters” on page 2-13
• “Declaring Domain Parameters” on page 2-99
• “Declare Component Nodes” on page 2-16
• “Declare Component Inputs and Outputs” on page 2-18
2-5
2 Creating Custom Components and Domains
variables begins an Across variables declaration block, which is terminated by an end key word.
This block contains declarations for all the Across variables associated with the domain. A domain
model class definition can contain multiple Across variables, combined in a single variables block.
This block is required.
variables
domain_across_var1 = {value,'unit'};
end
value is the initial value. unit is a valid unit string, defined in the unit registry. See “Declare a
Mechanical Rotational Domain” on page 2-20 for more information.
You can specify initialization ranges for domain Across variables, for example, to exclude negative
values for pressure or temperature. The syntax is the same as for component variables:
variables
domain_across_var1 = {value={value,'unit'},imin={value,'unit'},imax={value,'unit'}};
end
Through variables are semantically distinct in that their values have to balance at a node: for each
Through variable, the sum of all its values flowing into a branch point equals the sum of all its values
flowing out. Therefore, a domain file must contain a separate declaration block for its Through
variables, with the Balancing attribute set to true.
variables(Balancing = true)
domain_through_var1 = {value,'unit'};
end
See Also
Related Examples
• “Declare a Mechanical Rotational Domain” on page 2-20
• “Declare Component Variables” on page 2-8
• “Declare Component Nodes” on page 2-16
• “Declaring Domain Parameters” on page 2-99
2-6
Declare Through and Across Variables for a Domain
More About
• “Declaring Domains and Components” on page 2-3
2-7
2 Creating Custom Components and Domains
In this section...
“Through and Across Component Variables” on page 2-8
“Internal Component Variables” on page 2-8
“Variable Priority for Model Initialization” on page 2-9
“Variable Initialization Range” on page 2-10
“Nominal Value and Unit for a Variable” on page 2-10
variables
t = {0,'N*m'};
end
Note After you declare component Through and Across variables, you have to specify their
relationship with component nodes, and therefore with the domain Through and Across variables. For
more information, see “Define Relationship Between Component Variables and Nodes” on page 2-23.
variables
f = {0,'N'}; % Force
v = {0,'m/s'}; % Velocity
x = {0,'m'}; % Spring deformation
end
Force and velocity are the component Through and Across variables, later to be connected to the
domain Through and Across variables using the branches section. Spring deformation is an internal
component variable, to be used for model initialization.
You can declare internal component variables of type integer or real as event variables by setting the
Event=true attribute. For more information, see “Event Variables” on page 2-54.
2-8
Declare Component Variables
The default values for variable priority, target value, and unit come from the variable declaration in
the component file. Specifying an optional comment lets you control the variable name in the block
dialog box. For more information, see “Specify Meaningful Names for the Block Parameters and
Variables” on page 4-32.
Note For variables with temperature units, there is an additional consideration of whether to apply
linear or affine conversion when the block user changes the unit in the Variables tab of the block
dialog box. Use the Conversion attribute in the same way as for the block parameters. For details,
see “Parameter Units” on page 2-13.
In most cases, it is sufficient to declare a variable just as a value with unit on page 2-5, omitting its
priority, which is equivalent to priority = priority.none. The block user can set the variable
priority, as needed, in the Variables tab of the block dialog box prior to simulation.
In some cases, however, setting a variable to a certain priority by default is essential to the correct
operation of the component. To specify a high or low default priority for a component variable,
declare the variable as a field array. For example, the following declaration initializes variable x
(spring deformation) as 0 mm, with high priority:
variables
x = {value = {0,'m'},priority = priority.high}; % Spring deformation
end
In this case, the Spring deformation variable will appear in the Variables tab of the block dialog
box with the default priority High and the default target value and unit 0 mm, but the block user can
change the variable priority and target as usual.
If you want a variable to always have high initialization priority, without letting the block user to
change it, declare the variable as private:
variables(Access=private)
x = {value = {0,'m'},priority = priority.high};
end
In this case, the block user does not have control over the variable priority or initialization target,
because private variables do not appear in the Variables tab of the block dialog box.
If you want the variable to always have a certain initialization priority, such as High, but let the block
user specify the target value, declare the variable as private and tie it to an initialization parameter:
parameters
p = {0,'m'}; % Initial deformation
end
variables(Access=private)
x = {value = p,priority = priority.high};
end
2-9
2 Creating Custom Components and Domains
In this case, the value of the Initial deformation parameter, specified by the block user, is assigned
as the initial target to variable x, with high initialization priority. Depending on the results of the
solve, this target may or may not be satisfied when the solver computes the initial conditions for
simulation. For more information, see “Initial Conditions Computation”.
For composite components, member components are declared as hidden and therefore their variables
do not appear in the Variables tab of the block dialog box. However, you can use a top-level
parameter to let the block user specify the initial target value of a member component variable. For
more information, see “Specifying Initial Target Values for Member Variables” on page 2-64.
When multiple initialization solutions exist, this syntax lets you guide the solver towards the
preferred solution. For more information, see “Block-Level Variable Initialization”. If the specified
range cannot be satisfied during initialization, the solver issues an error.
The solver tries to satisfy the initialization range for a variable regardless of whether its initialization
priority is high, low, or none. It is recommended that you use the priority attribute sparingly. The
default priority value, priority.none (which is equivalent to leaving out the priority attribute
entirely), is suitable in most cases. The block user can modify the variable priority value, as needed,
in the Variables tab of the block dialog box prior to simulation. However, the block user does not
have control over the variable initialization range. Only the block author can specify the acceptable
minimum and maximum values for variable initialization in the component file, both for continuous
and for event variables.
The default initialization range is (-inf,inf). Therefore, you do not have to specify both values to
define the range, it is sufficient to specify only imin or imax. For example, use this syntax to limit the
temperature to positive values:
variables
T = {value={293.15,'K'},imin={0,'K'}};
end
When you specify imin or imax, these values define an open range.
For model initialization using an operating point, the solver tries to satisfy initialization ranges only
for variables that do not have a target in the operating point data tree. For more information, see
“Using Operating Point Data for Model Initialization”.
Each model has an underlying table of nominal value-unit pairs. In general, all variables in a model
are scaled based on the nominal value corresponding to their physical unit. You can override this
2-10
Declare Component Variables
scaling for an individual variable in a component file by providing a nominal value and unit as a
variable declaration attribute.
variables
x = {value = {value,'unit'},nominal = {value,'unit'}};
end
When you generate a custom Simscape block from a component file, nominal value and unit form the
nominal declaration attribute translate into default values for block parameters x_nominal and
x_nominal_unit (where x is the variable name).
variables
i = {value = {0,'A'},nominal = {1,'mA'}}; % Current
end
Note It is recommended that you use the nominal attribute sparingly. The default nominal values,
which come from the model value-unit table, are suitable in most cases. The block user can also
modify the nominal values and units for individual blocks by using either the block dialog box or
set_param and get_param functions, if needed. For more information, see “Modify Nominal Values
for a Block Variable”.
2-11
2 Creating Custom Components and Domains
See Also
Related Examples
• “Declare a Spring Component” on page 2-21
• “Declare Through and Across Variables for a Domain” on page 2-6
• “Declare Component Parameters” on page 2-13
• “Declaring Domain Parameters” on page 2-99
• “Declare Component Nodes” on page 2-16
• “Declare Component Inputs and Outputs” on page 2-18
More About
• “Declaring Domains and Components” on page 2-3
2-12
Declare Component Parameters
Component parameters let you specify adjustable parameters for the Simscape block generated from
the component file. Parameters will appear in the block dialog box and can be modified when building
and simulating a model.
You declare each parameter as a value with unit on page 2-5. Specifying an optional comment lets
you control the parameter name in the block dialog box. For more information, see “Specify
Meaningful Names for the Block Parameters and Variables” on page 4-32.
The following example declares parameter k, with a default value of 10 N*m/rad, specifying the
spring rate of a rotational spring. In the block dialog box, this parameter will be named Spring rate.
parameters
k = { 10, 'N*m/rad' }; % Spring rate
end
Parameter Units
When you declare a component parameter, use the units that make sense in the context of the block
application. For example, if you model a solenoid, it is more convenient for the block user to input
stroke in millimeters rather than in meters. When a parameter is used in equations and other sections
of a component file, Simscape unit manager handles the conversions.
With temperature units, however, there is an additional issue of whether to apply linear or affine
conversion (see “Thermal Unit Conversions”). Therefore, when you declare a parameter with
temperature units, you can specify only nonaffine units (kelvin or rankine). When the block user
enters the parameter value in affine units (Celsius or Fahrenheit), this value is automatically
converted to the units specified in the parameter declaration. By default, affine conversion is applied.
If a parameter specifies relative, rather than absolute, temperature (in other words, a change in
temperature), set its Conversion attribute to relative (for details, see “Member Attributes” on
page 2-105).
Note Member attributes apply to a whole declaration block. If some of your parameters are relative
and others are absolute, declare them in separate blocks. You can have more than one declaration
block of the same member type within a Simscape file.
Case Sensitivity
Simscape language is case-sensitive. This means that member names may differ only by case.
However, Simulink® software is not case-sensitive. Simulink parameter names (that is, parameter
names in a block dialog box) must be unique irrespective of case. Therefore, if you declare two
parameters whose names differ only by case, such as
component MyComponent
parameters
2-13
2 Creating Custom Components and Domains
A = 0;
a = 0;
end
end
However, if one of the parameters is private or hidden, that is, does not appear in the block dialog
box,
component MyComponent
parameters(Access=private)
A = 0;
end
parameters
a = 0;
end
end
then there is no conflict in the Simulink namespace and no problem generating the block from the
component source.
Public component variables also appear in the block dialog box, on the Variables tab, because they
are used for model initialization. These variables therefore compete with each other and with the
block parameter names in the Simulink namespace. If a component has a public variable and a
parameter whose names differ only by case, such as
component MyComponent
variables
A = 0;
end
parameters
a = 0;
end
end
you will not be able to generate a block from this component. As a possible workaround, you can
declare the variable as private or hidden. In this case, the variable does not appear on the Variables
tab of the resulting block dialog, and therefore there is no namespace conflict. However, if you want
to be able to use the variable in the model initialization process, keep it public and change its name,
or the name of the parameter.
The case-sensitivity restriction applies only to component parameters and public component
variables, because other member types do not have an associated Simulink entity, and are therefore
completely case-sensitive.
See Also
Related Examples
• “Declare a Spring Component” on page 2-21
• “Declare Component Variables” on page 2-8
• “Declare Component Nodes” on page 2-16
• “Declare Component Inputs and Outputs” on page 2-18
2-14
Declare Component Parameters
More About
• “Declaring Domains and Components” on page 2-3
• “Enumerations” on page 3-14
2-15
2 Creating Custom Components and Domains
When declaring nodes in a component, you have to associate them with an existing domain. Once a
node is associated with a domain, it:
For more information, see “Define Relationship Between Component Variables and Nodes” on page 2-
23.
You need to refer to the domain name using the full path starting with the top package directory. For
more information on packaging your Simscape files, see “Building Custom Block Libraries” on page 4-
21.
The following example uses the syntax for the Simscape Foundation mechanical rotational domain:
nodes
r = foundation.mechanical.rotational.rotational;
end
If you want to use your own customized rotational domain called rotational.ssc and located at
the top level of your custom package directory +MechanicalElements, the syntax would be:
nodes
r = MechanicalElements.rotational;
end
Note Components using your own customized rotational domain cannot be connected with the
components using the Simscape Foundation mechanical rotational domain. Use your own customized
domain definitions to build complete libraries of components to be connected to each other.
Specifying an optional comment lets you control the port label and location in the block icon. For
more information, see “Customize the Names and Locations of the Block Ports” on page 4-34. In the
following example, the electrical conserving port will be labelled + and will be located on the top side
of the block icon.
nodes
p = foundation.electrical.electrical; % +:top
end
2-16
Declare Component Nodes
See Also
Related Examples
• “Declare a Spring Component” on page 2-21
• “Declare a Mechanical Rotational Domain” on page 2-20
• “Declare Through and Across Variables for a Domain” on page 2-6
• “Declare Component Variables” on page 2-8
• “Declare Component Parameters” on page 2-13
• “Declare Component Inputs and Outputs” on page 2-18
More About
• “Declaring Domains and Components” on page 2-3
2-17
2 Creating Custom Components and Domains
• A value with unit on page 2-5, where value can be a scalar, vector, or matrix. For a vector or a
matrix, all signals have the same unit.
• An untyped identifier, to facilitate unit propagation.
Specifying an optional comment lets you control the port label and location in the block icon. For
more information, see “Customize the Names and Locations of the Block Ports” on page 4-34.
This example declares an input port s, with a default value of 1 Pa, specifying the control port of a
hydraulic pressure source. In the block diagram, this port will be named Pressure and will be located
on the top side of the block icon.
inputs
s = { 1, 'Pa' }; % Pressure:top
end
The next example declares an output port v as a 3-by-3 matrix of linear velocities.
outputs
v = {zeros(3), 'm/s'};
end
You can also reference component parameters in input and output declarations. For example, you can
control the signal size by using a block parameter:
component MyTransformer
parameters
N = 3; % Number of windings
end
inputs
I = {zeros(N, 1), 'A'};
end
....
end
The following example declares an input port I and output port O as untyped identifiers. In the block
diagram, the output port will be located on the right side of the block icon. The block propagates the
unit and size of the physical signal. For more information, see “Physical Signal Unit Propagation”.
inputs
I;
end
outputs
O; % :right
end
2-18
Declare Component Inputs and Outputs
See Also
Related Examples
• “Declare a Spring Component” on page 2-21
• “Declare Component Variables” on page 2-8
• “Declare Component Parameters” on page 2-13
• “Declare Component Nodes” on page 2-16
More About
• “Declaring Domains and Components” on page 2-3
• “Physical Signal Unit Propagation”
2-19
2 Creating Custom Components and Domains
domain rotational
% Define the mechanical rotational domain
% in terms of across and through variables
variables
w = { 1 , 'rad/s' }; % angular velocity
end
variables(Balancing = true)
t = { 1 , 'N*m' }; % torque
end
end
Note This domain declaration corresponds to the Simscape Foundation mechanical rotational
domain. For a complete listing of the Foundation domains, see “Foundation Domain Types and
Directory Structure” on page 6-2.
For more information, see “Define Relationship Between Component Variables and Nodes” on page 2-
23.
See Also
Related Examples
• “Declare Through and Across Variables for a Domain” on page 2-6
• “Declaring Domain Parameters” on page 2-99
More About
• “Declaring Domains and Components” on page 2-3
2-20
Declare a Spring Component
The domain is declared in a file named rotational.ssc (see “Declare a Mechanical Rotational
Domain” on page 2-20). The following file, named spring.ssc, declares a component called spring.
The component contains:
Note This example shows only the declaration section of the spring component. For a complete file
listing of a spring component, see “Mechanical Component — Spring” on page 2-91.
2-21
2 Creating Custom Components and Domains
See Also
Related Examples
• “Declare Component Variables” on page 2-8
• “Declare Component Parameters” on page 2-13
• “Declare Component Nodes” on page 2-16
• “Declare Component Inputs and Outputs” on page 2-18
More About
• “Declaring Domains and Components” on page 2-3
2-22
Define Relationship Between Component Variables and Nodes
• To establish the relationship between the Through variables, use the branches section of the
component file. If the component has multiple nodes, indicate branches by writing multiple
statements in the branches section. For syntax and examples, see the branches on page 5-
5 reference page.
• To establish the relationship between the Across variables, use the equations section of the
component file. Add an equation that connects the component Across variable with the respective
variables at the component nodes. If there is more than one Across variable, add multiple
equations, connecting each variable with its respective nodes. The equations section can also
contain other equations that define the component action. For more information, see “Defining
Component Equations” on page 2-26.
1 Declare the Across and Through variables in a domain file (or use an existing domain; for a
complete listing of the Foundation domains, see “Foundation Domain Types and Directory
Structure” on page 6-2).
For example, the following domain file, named rotational.ssc, declares angular velocity, w, as
an Across variable and torque, t, as a Through variable.
domain rotational
% Define the mechanical rotational domain
% in terms of across and through variables
variables
w = { 1 , 'rad/s' }; % angular velocity
end
variables(Balancing = true)
t = { 1 , 'N*m' }; % torque
end
end
2-23
2 Creating Custom Components and Domains
2 Declare the nodes in a component file and associate them with the domain, for example:
nodes
node1 = MyPackage.rotational;
node2 = MyPackage.rotational;
end
• Carries each of the domain Across variables as a measurable quantity. In this example, each of
the nodes carries one Across variable, w.
• Writes a conserving equation for each of the domain Through variables. In this example, there
is one Through variable, t, and therefore each node writes one conserving equation. A
conserving equation is a sum of terms that is set to zero (node.t == 0). The branches on
page 5-5 section in the component file establishes the terms that are summed to zero at
the node.
3 Declare the corresponding variables in the component file, for example:
variables
w = { 1 , 'rad/s' }; % angular velocity
t = { 1 , 'N*m' }; % torque
end
The names of the component variables do not have to match those of the domain Across and
Through variables, but the units must be commensurate. At this point, there is no connection
between the component variables and the domain variables.
4 Establish the relationship between the Through variables by using the branches section of the
component file. For example:
branches
t : node1.t -> node2.t; % t - Through variable from node1 to node2
end
This branch statement declares that t flows from node1 to node2. Therefore, t is subtracted
from the conserving equation identified by node1.t, and t is added to the conserving equation
identified by node2.t. For more information and examples, see the branches on page 5-5
reference page.
5 Establish relationship between the Across variables in the equations section of the component
file, for example, by adding the following equation:
equations
w == node1.w - node2.w; % w - Across variable between node1 and node2
[...] % more equations describing the component behavior, as necessary
end
2-24
Define Relationship Between Component Variables and Nodes
variables
[...]
t = { 0, 'N*m' }; % torque through
w = { 0, 'rad/s' }; % velocity across
end
branches
t : r.t -> c.t; % t - Through variable from r to c
end
equations
w == r.w - c.w; % w - Across variable between r and c
[...] % more equations here
end
end
component two_windings
nodes
p1 = foundation.electrical.electrical;
n1 = foundation.electrical.electrical;
p2 = foundation.electrical.electrical;
n2 = foundation.electrical.electrical;
end
[...]
variables
i1 = { 0, 'A' };
v1 = { 0, 'V' };
i2 = { 0, 'A' };
v2 = { 0, 'V' };
end
[...]
branches
i1 : p1.i -> n1.i; % Current through first winding
i2 : p2.i -> n2.i; % Current through second winding
end
equations
v1 == p1.v - n1.v; % Voltage across first winding
v2 == p2.v - n2.v; % Voltage across second winding
[...] % more equations here
end
end
2-25
2 Creating Custom Components and Domains
Note You can also specify equations that are executed during model initialization only, by using the
(Initial=true) attribute. For more information, see “Initial Equations” on page 2-33.
A Simscape language equation consists of two expressions connected with the == operator. Unlike
the regular assignment operator (=), the == operator specifies continuous mathematical equality
between the two expressions (for more information, see “Specifying Mathematical Equality” on page
2-26). The equation expressions may be constructed from any of the identifiers defined in the model
declaration. You can also access global simulation time from the equation section using the time
function.
For a list of MATLAB functions that you can use in the equation section, see Supported Functions.
equations
Expression1 == Expression2;
end
Here we have declared an equality between Expression1 and Expression2. The left- and right-
hand side expressions are any valid MATLAB expressions (see the next section on page 2-27 for
restrictions on using the relational operators: ==, <, >, <=, >=, ~=, &&, ||). The equation expressions
may be constructed from any of the identifiers defined in the model declaration.
The equation is defined with the == operator. This means that the equation does not represent
assignment but rather a symmetric mathematical relationship between the left- and right-hand
operands. Because == is symmetric, the left-hand operand is not restricted to just a variable. For
example:
2-26
Defining Component Equations
component MyComponent
[...]
variables
a = 1;
b = 1;
c = 1;
end
equations
a + b == c;
end
end
Note Equation expressions must be terminated with a semicolon or a newline. Unlike MATLAB, the
absence of a semicolon makes no difference. In any case, Simscape language does not display the
result as it evaluates the equation.
where a, b, and c represent scalar double values, is a legal MATLAB expression. This would mean,
take the logical value generated by testing a’s equivalence to b, coerce this value to a double and
multiply by c. If a is the same as b, then this expression will return c. Otherwise, it will return 0.
This expression is ambiguous, but MATLAB makes == and other relational operators left associative,
so this expression is treated as:
(a == b) == c;
2-27
2 Creating Custom Components and Domains
equations
a == b == c;
end
end
is illegal in the Simscape language. You must explicitly associate top-level occurrences of relational
operators. Either
component MyComponent
[...]
equations
(a == b) == c;
end
end
or
component MyComponent
[...]
equations
a == (b == c);
end
end
are legal. In either case, the quantity in the parentheses is equated to the quantity on the other side
of the equation.
With the exception of the top-level use of the == operator, == and other relational operators are left
associative. For example:
component MyComponent
[...]
parameters
a = 1;
b = 1;
c = false;
end
variables
d = 1;
end
equations
(a == b == c) == d;
end
end
component MyComponent
[...]
parameters
a = 1;
b = 1;
c = false;
end
variables
d = 1;
end
equations
2-28
Defining Component Equations
((a == b) == c) == d;
end
end
Equation Dimensionality
The expressions on either side of the == operator need not be scalar expressions. They must be either
the same size or one must be scalar. For example:
equations
[...]
<3x3 Expression> == <3x3 Expression>;
[...]
end
equations
[...]
<1x1 Expression> == <3x3 Expression>;
[...]
end
is also legal. Here, the left-hand side of the equation is expanded, via scalar expansion, into the same
expression replicated into a 3x3 matrix. This equation expression also introduces 9 scalar equations.
equations
[...]
<2x3 Expression> == <3x2 Expression>;
[...]
end
is illegal because the sizes of the expressions on the left- and right-hand side are different.
Equation Continuity
The equation section is evaluated in continuous time. Some of the values that are accessible in the
equation section are themselves piecewise continuous, that is, they change continuously in time.
These values are:
• variables
• inputs
• outputs
• time
Piecewise continuous indicates that values are continuous over compact time intervals but may
change value at certain instances. The following values are continuous, but not time-varying:
• parameters
• constants
Time-varying countable values, for example, integer or logical, are never continuous.
2-29
2 Creating Custom Components and Domains
Continuity is propagated like a data type. It is propagated through continuous functions (see
Supported Functions).
However, empirical formulae often employ noninteger exponents where the base is either unitless or
in known units. When working with these types of formulae, convert the base to a unitless value using
the value function and then reapply units if needed.
For example, the following formula gives the pressure drop, in Pa, in terms of flow rate, in m^3/s:
p == k * q^1.023
where p is pressure, q is flow rate and k is some unitless constant. To write this formula in Simscape
language, use:
This approach works regardless of the actual units of p or q, as long as they are commensurate with
pressure and volumetric flow rate, respectively. For example, the actual flow rate can be in gallons
per minute, the equation will still work and handle the unit conversion automatically.
See Also
Related Examples
• “Simple Algebraic System” on page 2-31
• “Use Simulation Time in Equations” on page 2-32
More About
• “Using Conditional Expressions in Equations” on page 2-35
• “Using Intermediate Terms in Equations” on page 2-37
• “Using Lookup Tables in Equations” on page 2-48
• “Programming Run-Time Errors and Warnings” on page 2-50
2-30
Simple Algebraic System
y = x2
x = 2y - 1
component MyAlgebraicSystem
outputs
x = 0;
y = 0;
end
equations
y == x^2; % y = x^2
x == 2 * y - 1; % x = 2 * y - 1
end
end
See Also
Related Examples
• “Use Simulation Time in Equations” on page 2-32
More About
• “Defining Component Equations” on page 2-26
• “Using Conditional Expressions in Equations” on page 2-35
• “Using Intermediate Terms in Equations” on page 2-37
• “Using Lookup Tables in Equations” on page 2-48
• “Programming Run-Time Errors and Warnings” on page 2-50
2-31
2 Creating Custom Components and Domains
component
parameters
w = { 1, '1/s' } % omega
end
outputs
y = 0;
end
equations
y == sin( w * time );
end
end
See Also
Related Examples
• “Simple Algebraic System” on page 2-31
More About
• “Defining Component Equations” on page 2-26
• “Using Conditional Expressions in Equations” on page 2-35
• “Using Intermediate Terms in Equations” on page 2-37
• “Using Lookup Tables in Equations” on page 2-48
• “Programming Run-Time Errors and Warnings” on page 2-50
2-32
Initial Equations
Initial Equations
Regular equations are executed throughout the simulation. The (Initial=true) attribute lets you
specify additional equations that are executed during model initialization only.
Regular component equations alone are not sufficient to initialize a DAE system. Consider a system
with n continuous differential variables and m continuous algebraic variables. For simulation, this
system has n+m degrees of freedom and must provide n+m equations. The initialization problem has
up to n additional unknowns that correspond to the derivative variables. These additional unknowns
can be satisfied when you specify initial targets for block variables. Initial equations provide another
way to initialize a system.
In general, the maximum number of high-priority targets you can specify is equal to the number of
additional unknowns in the initialization problem. Besides the unknowns from differential variables,
the initialization problem also has one more unknown for each event variable. These additional
unknowns determine the maximum combined number of initial equations and high-priority variable
targets. If there are too many high-priority targets, these cannot all be met. For more information,
see “Block-Level Variable Initialization”.
Because the default value of the Initial attribute for equations is false, you can omit this
attribute when declaring regular equations:
The syntax of initial equations is the same as that of regular equations, except:
• der(x) in initial equations is treated as an unknown value and is solved for during initialization.
• delay and integ operators are disallowed.
When you include assert constructs in initial equations, their predicate conditions are checked only
once, after solving for initial conditions (before the start of simulation, see “Initial Conditions
Computation”). Use these assertions to safeguard against the model initializing with nonphysical
values. For more information, see “Programming Run-Time Errors and Warnings” on page 2-50.
A common use case for specifying initial equations is to initialize a system in steady state, for
example:
component C
parameters
a = {-5, '1/s'};
b = {-2, '1/s'};
end
outputs
2-33
2 Creating Custom Components and Domains
x = 5;
y = 10;
end
equations
der(x) == a*x + b*y;
der(y) == b*y;
end
equations(Initial=true)
der(x) == 0;
der(y) == 0;
end
end
der(x) == 0;
der(y) == 0;
der(x) == a*x + b*y;
der(y) == b*y;
Note When you initialize a model from an operating point, especially one that was generated from
logged simulation data, the operating point is likely to contain all the necessary high-priority targets
and applying initial equations would result in an over-specified model. Therefore, if you initialize a
model from an operating point, the solver ignores all the initial equations that contain variables
present in the operating point data. Initial equations for other variables are not affected: for example,
if you add a block to the model after extracting the operating point data, initial equations for this
block will be executed at initialization time. For more information, see “Using Operating Point Data
for Model Initialization”.
See Also
More About
• “Defining Component Equations” on page 2-26
• “Using Conditional Expressions in Equations” on page 2-35
• “Using Intermediate Terms in Equations” on page 2-37
• “Using Lookup Tables in Equations” on page 2-48
• “Programming Run-Time Errors and Warnings” on page 2-50
2-34
Using Conditional Expressions in Equations
Statement Syntax
You can specify conditional equations by using if statements.
equations
[...]
if Expression
[...]
elseif Expression
[...]
else
[...]
end
[...]
end
Restrictions
• Every if requires an else.
• The total number of equation expressions, their dimensionality, and their order must be the same
for every branch of the if-elseif-else statement. However, this rule does not apply to the
assert expressions, because they are not included in the expression count for the branch.
Example
For a component where x and y are declared as 1x1 variables, specify the following piecewise
equation:
2-35
2 Creating Custom Components and Domains
equations
if x >= -1 && x <= 1
y == x;
else
y == x^2;
end
end
equations
y == if x>=-1 && x<=1, x else x^2 end
end
See Also
More About
• “Defining Component Equations” on page 2-26
• “Using Intermediate Terms in Equations” on page 2-37
• “Using Lookup Tables in Equations” on page 2-48
• “Programming Run-Time Errors and Warnings” on page 2-50
2-36
Using Intermediate Terms in Equations
f · L · ρ · V2
P=
2D
where P is pressure, f is the Darcy friction factor, L is length, ρ is density, V is flow velocity, and D is
hydraulic area.
0.316
f =
Re1/4
D·V
Re =
ν
4A
D=
π
q
V=
A
where Re is the Reynolds number, A is the area, q is volumetric flow rate, and ν is the kinematic
viscosity.
In Simscape language, there are two ways that you can define intermediate terms for use in
equations:
Another advantage of using named intermediate terms instead of let expressions is that you can
include named intermediate terms in simulation data logs.
2-37
2 Creating Custom Components and Domains
The following example shows the same Darcy-Weisbach equation with intermediate terms written out
in Simscape language:
component MyComponent
[...]
parameters
L = { 1, 'm' }; % Length
rho = { 1e3, 'kg/m^3' }; % Density
nu = { 1e-6, 'm^2/s' }; % Kinematic viscosity
end
variables
p = { 0, 'Pa' }; % Pressure
q = { 0, 'm^3/s' }; % Volumetric flow rate
A = { 0, 'm^2' }; % Area
end
intermediates
f = 0.316 / Re_d^0.25; % Darcy friction factor
Re_d = D_h * V / nu; % Reynolds number
D_h = sqrt( 4.0 * A / pi ); % Hydraulic diameter
V = q / A; % Flow velocity
end
equations
p == f * L * rho * V^2 / (2 * D_h); % final equation
end
end
end
When you use this component in a model and log simulation data, the logs will include data for the
four intermediate terms, with their descriptive names (such as Darcy friction factor) shown in
the Simscape Results Explorer.
You can also include an intermediates section in a domain file and reuse these intermediate terms
in any component that has nodes of that domain type.
You declare an intermediate term by assigning a unique identifier on the left-hand side of the equal
sign (=) to an expression on the right-hand side of the equal sign.
• Can refer to other intermediate terms. For example, in the Darcy-Weisbach equation, the identifier
Re_d (Reynolds number) is used in the expression declaring the identifier f (Darcy friction factor).
The only requirement is that these references are acyclic.
2-38
Using Intermediate Terms in Equations
• Can refer to parameters, variables, inputs, outputs, member components and their parameters,
variables, inputs, and outputs, as well as Across variables of domains used by the component
nodes.
• Cannot refer to Through variables of domains used by the component nodes.
You can use intermediate terms in equations, as described in “Use in Equations” on page 2-39.
However, you cannot access intermediate terms in the setup function.
Intermediate terms can appear in simulation data logs and Simscape Results Explorer, as described in
“Data Logging” on page 2-40. However, intermediate terms do not appear in:
• Variable Viewer
• Statistics Viewer
• Operating Point data
• Block dialog boxes and Property Inspector
Use in Equations
After declaring an intermediate term, you can refer to it by its identifier anywhere in the equations
section of the same component. For example:
component A
[...]
parameters
p1 = { 1, 'm' };
end
variables
v1 = { 0, 'm' };
v2 = { 0, 'm^2' };
end
intermediates
int_expr = v1^2 * pi / p1;
end
equations
v2 == v1^2 + int_expr;
end
end
You can refer to a public intermediate term declared in a member component in the equations of an
enclosing composite component. For example:
component B
[...]
components
comp1 = MyPackage.A;
end
variables
v1 = { 0, 'm^2' };
end
[...]
equations
v1 == comp1.int_expr;
end
end
2-39
2 Creating Custom Components and Domains
Similarly, you can refer to an intermediate term declared in a domain in the equations section of any
component that has nodes of this domain type. For example:
domain D
[...]
intermediates
int_expr = v1 / sqrt(2);
end
[...]
end
component C
[...]
nodes
n = D;
end
variables
v1 = { 0, 'V' };
end
[...]
equations
v1 == n.int_expr;
end
end
Accessibility of intermediate terms outside of the file where they are declared is governed by their
Access attribute value. For mode information, see “Attribute Lists” on page 2-104.
Data Logging
Intermediate terms with ExternalAccess attribute values of modify or observe are included in
simulation data logs. For mode information, see “Attribute Lists” on page 2-104.
If you specify a descriptive name for an intermediate term, this name appears in the status panel of
the Simscape Results Explorer.
For example, you declare the intermediate term D_h (hydraulic diameter) as a function of the orifice
area:
component E
[...]
intermediates
D_h = sqrt( 4.0 * A / pi ); % Hydraulic diameter
end
[...]
end
When you use a block based on this component in a model and log simulation data, selecting D_h in
the Simscape Results Explorer tree on the left displays a plot of the values of the hydraulic diameter
over time in the right pane and the name Hydraulic diameter in the status panel at the bottom.
For more information, see “About the Simscape Results Explorer”.
2-40
Using Intermediate Terms in Equations
equations. This way, the declarations and equations are close together, which improves file
readability.
The following example shows the same Darcy-Weisbach equation as in the beginning of this topic but
with intermediate terms written out using the let expression:
component MyComponent
[...]
parameters
L = { 1, 'm' }; % Length
rho = { 1e3, 'kg/m^3' }; % Density
nu = { 1e-6, 'm^2/s' }; % Kinematic viscosity
end
variables
p = { 0, 'Pa' }; % Pressure
q = { 0, 'm^3/s' }; % Volumetric flow rate
A = { 0, 'm^2' }; % Area
end
equations
let
f = 0.316 / Re_d^0.25; % Darcy friction factor
Re_d = D_h * V / nu; % Reynolds number
D_h = sqrt( 4.0 * A / pi ); % Hydraulic diameter
V = q / A; % Flow velocity
in
p == f * L * rho * V^2 / (2 * D_h); % final equation
end
end
end
However, in this case the four intermediate terms do not appear in logged simulation data.
A let expression consists of two clauses, the declaration clause and the expression clause.
equations
[...]
let
declaration clause
in
expression clause
end
[...]
end
The declaration clause assigns an identifier, or set of identifiers, on the left-hand side of the equal
sign (=) to an equation expression on the right-hand side of the equal sign:
LetValue = EquationExpression
The expression clause defines the scope of the substitution. It starts with the keyword in, and may
contain one or more equation expressions. All the expressions assigned to the identifiers in the
declaration clause are substituted into the equations in the expression clause during parsing.
2-41
2 Creating Custom Components and Domains
component MyComponent
[...]
variables
x = 0;
y = 0;
end
equations
let
z = y + 1;
in
x == z;
end
end
end
In this example, the declaration clause of the let expression sets the value of the identifier z to be
the expression y + 1. Thus, substituting y + 1 for z in the expression clause in the let statement, the
code above is equivalent to:
component MyComponent
[...]
variables
x = 0;
y = 0;
end
equations
x == y + 1;
end
end
end
There may be multiple declarations in the declaration clause. These declarations are order
independent. The identifiers declared in one declaration may be referred to by the expressions for
identifiers in other declarations in the same declaration clause. Thus, in the example with the Darcy-
Weisbach equation, the identifier Re_d (Reynolds number) is used in the expression declaring the
identifier f (Darcy friction factor). The only requirement is that the expression references are acyclic.
The expression clause of a let expression defines the scope of the substitution for the declaration
clause. Other equations, that do not require these substitutions, may appear in the equation section
outside of the expression clause. In the following example, the equation section contains the equation
expression c == b + 2 outside the scope of the let expression before it.
component MyComponent
[...]
variables
a = 0;
b = 0;
c = 0;
end
equations
let
x = a + 1;
2-42
Using Intermediate Terms in Equations
in
b == x;
end
c == b + 2;
end
end
These expressions are treated as peers. They are order independent, so this example is equivalent to
component MyComponent
[...]
variables
a = 0;
b = 0;
c = 0;
end
equations
c == b + 2;
let
x = a + 1;
in
b == x;
end
end
end
component MyComponent
[...]
variables
a = 0;
b = 0;
c = 0;
end
equations
b == a + 1;
c == b + 2;
end
end
component MyComponent
[...]
variables
a = 0;
b = 0;
c = 0;
end
equations
let
w = a + 1;
in
let
z = w + 1;
2-43
2 Creating Custom Components and Domains
in
b == z;
c == w;
end
end
end
end
In case of nesting, substitutions are performed based on both of the declaration clauses. After the
substitutions, the code above becomes:
component MyComponent
[...]
variables
a = 0;
b = 0;
c = 0;
end
equations
b == a + 1 + 1;
c == a + 1;
end
end
The innermost declarations take precedence. The following example illustrates a nested let
expression where the inner declaration clause overrides the value declared in the outer one:
component MyComponent
[...]
variables
a = 0;
b = 0;
end
equations
let
w = a + 1;
in
let
w = a + 2;
in
b == w;
end
end
end
end
component MyComponent
[...]
variables
a = 0;
b = 0;
end
equations
b == a + 2;
end
end
2-44
Using Intermediate Terms in Equations
You can use if statements within both declarative and expression clause of let expressions, for
example:
component MyComponent
[...]
variables
a = 0;
b = 0;
c = 0;
end
equations
let
x = if a < 0, a else b end;
in
c == x;
end
end
end
Here x is declared as the conditional expression based on a < 0. Performing substitution on this
example yields:
component MyComponent
[...]
variables
a = 0;
b = 0;
c = 0;
end
equations
c == if a < 0, a else b end;
end
end
The next example illustrates how you can use let expressions within conditional expressions. The
two let expressions on either side of the conditional expression are independent:
component MyComponent
[...]
variables
a = 0;
b = 0;
c = 0;
end
equations
if a < 0
let
z = b + 1;
in
c == z;
end
else
let
z = b + 2;
in
c == z;
2-45
2 Creating Custom Components and Domains
end
end
end
end
This example shows using an identifier list, rather than a single identifier, in the declarative clause of
a let expression:
component MyComponent
[...]
variables
a = 0;
b = 0;
c = 0;
d = 0;
end
equations
let
[x, y] = if a < 0, a; -a else -b; b end;
in
c == x;
d == y;
end
end
end
Here x and y are declared as the conditional expression based on a < 0. Notice that each side of the
if statement defines a list of two expressions. A first semantic translation of this example separates
the if statement into
if a < 0, a; -a else -b; b end =>
{ if a < 0, a else -b end; if a < 0, -a else b end }
2-46
Using Intermediate Terms in Equations
component MyComponent
[...]
variables
a = 0;
b = 0;
c = 0;
d = 0;
end
equations
c == if a < 0, a else -b end;
d == if a < 0, -a else b end;
end
end
See Also
intermediates
More About
• “Defining Component Equations” on page 2-26
• “Using Conditional Expressions in Equations” on page 2-35
• “Using Lookup Tables in Equations” on page 2-48
• “Programming Run-Time Errors and Warnings” on page 2-50
2-47
2 Creating Custom Components and Domains
The following example implements mapping temperature to pressure using a one-dimensional lookup
table.
component TtoP
inputs
u = {0,'K'}; % temperature
end
outputs
y = {0,'Pa'}; % pressure
end
parameters (Size=variable)
xd = {[100 200 300 400] 'K'};
yd = {[1e5 2e5 3e5 4e5] 'Pa'};
end
equations
y == tablelookup(xd,yd,u,interpolation=linear,extrapolation=nearest);
end
end
xd and yd are declared as variable-size parameters with units. This enables the block users to
provide their own data sets when the component is converted to a custom block, and also to select
commensurate units from the drop-downs in the custom block dialog box. The next illustration shows
the dialog box of the custom block generated from this component.
Note Currently, you cannot use variable-size parameters in the equations section outside of the
tablelookup function.
To avoid repeating the same variable-size parameter declarations in each component that needs to
use them in its tablelookup function, you can declare variable-size domain parameters and
propagate them to components for interpolation purposes. For more information, see “Propagation of
Domain Parameters” on page 2-99.
2-48
Using Lookup Tables in Equations
The TtoP component uses linear interpolation for values within the table range, but outputs the
nearest value of yd for out-of-range input values. The following illustration shows a block diagram,
where the custom TtoP block is used with a linear input signal changing from 0 to 1000, and the
resulting output.
See the tablelookup reference page for syntax specifics and more examples.
See Also
More About
• “Defining Component Equations” on page 2-26
• “Using Conditional Expressions in Equations” on page 2-35
• “Using Intermediate Terms in Equations” on page 2-37
• “Programming Run-Time Errors and Warnings” on page 2-50
2-49
2 Creating Custom Components and Domains
The following component file implements a variable resistor, where input physical signal R supplies
the resistance value. The assert construct checks that this input signal is greater than or equal to
zero:
component MyVariableResistor
% Variable Resistor
% Models a linear variable resistor. The relationship between voltage V
% and current I is V=I*R where R is the numerical value presented at the
% physical signal port R. If this signal becomes negative, simulation
% errors out.
%
inputs
R = { 0.0, 'Ohm' };
end
nodes
p = foundation.electrical.electrical; % +:left
n = foundation.electrical.electrical; % -:right
end
variables
i = { 0, 'A' };
v = { 0, 'V' };
end
branches
i : p.i -> n.i;
end
equations
assert( R >= 0, 'Negative resistance is not modeled' );
v == p.v - n.v;
v == i*R;
end
end
If a model contains this Variable Resistor block, and signal R becomes negative during simulation,
then simulation stops and the Simulation Diagnostics window opens with a message similar to the
following:
At time 3.200000, an assertion is triggered. Negative resistance is not modeled.
The assertion comes from:
Block path: dc_motor1/Variable Resistor
Assert location: between line: 29, column: 14 and line: 29, column: 18 in file:
C:/Work/libraries/+MySimscapeLibrary/+ElectricalElements/MyVariableResistor.ssc
2-50
Programming Run-Time Errors and Warnings
See the assert reference page for syntax specifics and more examples.
See Also
More About
• “Defining Component Equations” on page 2-26
• “Using Conditional Expressions in Equations” on page 2-35
• “Using Intermediate Terms in Equations” on page 2-37
• “Using Lookup Tables in Equations” on page 2-48
2-51
2 Creating Custom Components and Domains
Suppose, you want to generate a Simscape equation from the solution of the following ordinary
differential equation. As a first step, use the dsolve function to solve the equation:
syms a y(t)
Dy = diff(y);
s = dsolve(diff(y, 2) == -a^2*y, y(0) == 1, Dy(pi/a) == 0);
s = simplify(s)
s =
cos(a*t)
Then, use the simscapeEquation function to rewrite the solution in the Simscape language
equation format:
simscapeEquation(s)
ans =
s == cos(a*time);
Copy and paste the generated code into the equation section of a component file:
component MyComponent
equations
s == cos(a*time);
end
end
Make sure the declaration section of the component file contains all the symbolic variables used in
these equations. You can declare these symbolic variables as Simscape language variables,
parameters, inputs, or outputs, depending on their physical function and your intended block design.
component MyComponent
inputs
a = {1,'m/s'};
end
2-52
Import Symbolic Math Toolbox Equations
outputs
s = {0,'m'};
end
equations
s == cos(a*time);
end
end
See Also
Related Examples
• “Use Simulation Time in Equations” on page 2-32
More About
• “Get Started with Symbolic Math Toolbox” (Symbolic Math Toolbox)
• “Generate Simscape Equations from Symbolic Expressions” (Symbolic Math Toolbox)
2-53
2 Creating Custom Components and Domains
Physical modeling, in general, involves continuous variables and equations. In some cases, however,
you can simplify the mathematical model of the system and improve simulation performance by
treating certain changes in system behavior as discrete. Such an idealization assumes that system
variables may only change values instantaneously and discontinuously at specific points in time.
An event is a conceptual notation that denotes a change of state in a system. Event modeling lets you
perform discrete changes on continuous variables. The two most common applications of event
modeling are:
• Trigger-and-hold mechanism, such as a triggered delay. For example, a component has two inputs:
u and x (triggered signal), and one output y. When and only when the triggered signal x changes
value from false to true, output y is reset to the value of u at current time. y remains unchanged
all other times.
• Enabled component, acting on a principle similar to Simulink enabled subsystem. That is, the
component has a control signal as input. If the control signal has a positive value, then the
component holds certain states to the most recent value, or resets them. When the control signal
is negative, the states change according to component equations.
The following constructs in Simscape language let you perform event modeling: event variables,
events section, when clause, and edge operator.
Event Variables
Event variables are piecewise constant, that is, they change values only at event instants, and keep
their values constant between events. You can declare internal component variables of type integer or
real as event variables by setting the Event=true attribute.
For example, the following code declares two event variables: x (type real) and d (type integer).
variables (Event=true)
x = 0;
d = int32(0);
end
You can initialize event variables by using the initialevent operator. You can also initialize event
variables the same way as continuous variables, by setting their target values and priorities in the
member declaration block. For more information, see initialevent.
You update the values of the event variables in the events section of the component file, by using the
when clause.
2-54
Discrete Event Modeling
event type. Event data type is a special category of Boolean type, which returns true only
instantaneously, and returns false otherwise.
The following graphic illustrates the difference between Boolean and event data types.
The data derivation rules between Boolean and event data types are:
• edge(boolean) is event
• ~event is boolean
• (event && event) is event
• (event && boolean) is event
• (event || event) is event
• (event || boolean) is boolean
You use the edge operator to define event predicates in when clauses.
The when clause serves to update the values of the event variables. The syntax is
when EventPredicate
var1 = expr1;
var2 = expr2;
...
end
The variables in the body of the when clause must be declared as event variables. When the event
predicate returns true, all the variables in the body of the when clause simultaneously get updated to
the new values.
2-55
2 Creating Custom Components and Domains
The order of the variable assignments in the body of the when clause does not matter, because all
updates happen simultaneously. For example, if d1 and d2 are event variables initialized to 0,
when edge(time>1.0)
d1 = d2 + 1;
d2 = d1 + 1;
end
is equivalent to:
when edge(time>1.0)
d2 = d1 + 1;
d1 = d2 + 1;
end
After the event, both d1 and d2 have a new value of 1, because they were both simultaneously
updated by adding 1 to the old value of 0.
A when clause cannot update an event variable more than once within the same assignments list.
However, two independent when clauses also may not update the same event variable. You must use
an elsewhen branch to do this.
when EventPredicate
var1 = expr1;
var2 = expr2;
...
elsewhen EventPredicate
var1 = expr3;
...
end
A common usage of elsewhen branches is to prioritize events. If multiple predicates become true at
the same point in time, only the branch with the highest precedence is activated. The precedence of
the branches in a when clause is determined by their declaration order. That is, the when branch has
the highest priority, the last elsewhen branch has the lowest priority.
See Also
Related Examples
• “Triggered Delay Component” on page 2-57
• “Enabled Component” on page 2-58
2-56
Triggered Delay Component
component Triggered
inputs
u = 0; % input signal
triggered = 0; % control signal
end
variables(Event=true)
x = 0;
end
outputs
y = 0;
end
events
when edge(triggered>0)
x = u;
end
end
equations
y == x;
end
end
When the control signal becomes positive, the event variable x gets updated to the current value of
the input signal u. Output y outputs the value of x. Therefore, the output signal y gets updated to the
current value of the input signal u on the rising edge of the control signal, and then holds that value
between the events.
See Also
Related Examples
• “Enabled Component” on page 2-58
More About
• “Discrete Event Modeling” on page 2-54
2-57
2 Creating Custom Components and Domains
Enabled Component
The following example implements a component similar to a Simulink enabled subsystem:
component EnabledComponent
inputs
enabled = 0; % control signal
u = 0; % input signal
end
variables (Event=true)
x = 0; % state to hold output if necessary
end
outputs
y = 0; % output
end
parameters
held = true; % set true for held or false for reset
y_init = 0;
end
events
when edge(held && ~(enabled>0))
x = u; % if necessary, hold input on falling edge
end
end
equations
if enabled > 0
y == u;
elseif held==true
y == x;
else % not enabled and not held
y == y_init;
end
end
end
The component has two inputs: control signal enabled and data signal u.
The block operation depends on the value of the held parameter: if it is true, then the event
variable x assumes the value of the input data signal u on the falling edge of the control signal.
As long as the control signal has a positive value, the output y matches the input data signal u. When
the control signal is negative:
• If held is true, the output port y outputs the most recent held value of the event variable.
• If held is false, the output resets to the initial value, specified by the y_init parameter.
See Also
Related Examples
• “Triggered Delay Component” on page 2-57
2-58
Enabled Component
More About
• “Discrete Event Modeling” on page 2-54
2-59
2 Creating Custom Components and Domains
In certain ways, this functionality is similar to creating a subsystem in a Simulink block diagram,
however there are important differences. Simscape language is a textual environment, and therefore
you cannot “look under mask” and see a graphical representation of the underlying component
connections. At the same time, the textual environment is a very powerful tool for modeling complex
modular systems that consist of multiple interconnected member components.
See Also
Related Examples
• “Composite Component — DC Motor” on page 2-96
• “Composite Component Using import Statements” on page 2-112
• “Component Variants — Series RLC Branch” on page 2-85
• “Segmented Pipeline Using Component Array” on page 3-31
• “Case Study — Battery Pack with Fault Using Arrays” on page 3-33
More About
• “Declaring Member Components” on page 2-61
• “Parameterizing Composite Components” on page 2-62
• “Specifying Initial Target Values for Member Variables” on page 2-64
• “Specifying Component Connections” on page 2-66
• “Importing Domain and Component Classes” on page 2-110
• “Defining Component Variants” on page 2-77
• “Component Arrays” on page 3-28
• “Converting Subsystems into Composite Components” on page 2-72
2-60
Declaring Member Components
When declaring a member component, you have to associate it with an existing component file, either
in the Simscape Foundation libraries or in your custom package. You need to refer to the component
name using the full path starting with the top package directory. For more information on packaging
your Simscape files, see “Building Custom Block Libraries” on page 4-21.
The following example includes a Rotational Spring block from the Simscape Foundation library in
your custom component:
components(ExternalAccess=observe)
rot_spring = foundation.mechanical.rotational.spring;
end
If you want to use your own customized rotational spring called spring.ssc and located at the top
level of your custom package directory +MechanicalElements, the syntax would be:
components(ExternalAccess=observe)
rot_spring = MechanicalElements.spring;
end
Once you declare a member component, use its identifier (in the preceding examples, rot_spring)
to refer to its parameters, variables, nodes, inputs, and outputs. For example,
rot_spring.spr_rate refers to the Spring rate parameter of the Rotational Spring block.
See Also
Related Examples
• “Composite Component — DC Motor” on page 2-96
More About
• “Parameterizing Composite Components” on page 2-62
• “Specifying Initial Target Values for Member Variables” on page 2-64
• “Specifying Component Connections” on page 2-66
• “Importing Domain and Component Classes” on page 2-110
2-61
2 Creating Custom Components and Domains
Specify the composite component parameters by declaring a corresponding parameter in the top-
level parameters declaration block, and then assigning it to the desired parameter of a member
component. The declaration syntax is the same as described in “Declare Component Parameters” on
page 2-13.
For example, the following code includes a Foundation library Resistor block in your custom
component file, with the ability to control the resistance at the top level and a default resistance of 10
Ohm:
component MyCompositeModel
[...]
parameters
p1 = {10, 'Ohm'};
[...]
end
components(ExternalAccess=observe)
r1 = foundation.electrical.elements.resistor(R = p1);
[...]
end
[...]
end
You do not have to assign all the parameters of member blocks to top-level parameters. If a member
block parameter does not have a corresponding top-level parameter, the composite model uses the
default value of this parameter, specified in the member component.
component MyCompositeModel
[...]
parameters
p1 = {10, 'Ohm'};
[...]
end
components(ExternalAccess=observe)
r1 = foundation.electrical.elements.resistor;
...
end
[...]
function setup
r1.R = p1;
end
[...]
end
2-62
Parameterizing Composite Components
Note In case of conflict, assignments in the setup section override those made in the declaration
section.
Components are instantiated using default parameter values in the declaration section before setup
is run. Therefore, if you make adjustments to the parameters in the setup section, use a subsequent
setup section assignment to establish proper connection between the top-level parameter with a
member component parameter, as shown in the following example:
component RC
nodes
p = foundation.electrical.electrical; % :right
n = foundation.electrical.electrical; % :left
end
parameters
R = {1 , 'Ohm'}; % Resistance
tc = {1 , 's'}; % RC time constant
end
parameters(ExternalAccess=observe)
C = {1 , 'F'};
end
components(ExternalAccess=observe)
c1 = foundation.electrical.elements.capacitor(c=C);
r1 = foundation.electrical.elements.resistor(R=R);
end
function setup
C = tc/R;
c1.c = C; % This assignment ensures correct operation
end
connections
connect(c1.p, p);
connect(c1.n, r1.p);
connect(r1.n, n);
end
end
See Also
Related Examples
• “Composite Component — DC Motor” on page 2-96
More About
• “Declaring Member Components” on page 2-61
• “Specifying Initial Target Values for Member Variables” on page 2-64
• “Specifying Component Connections” on page 2-66
2-63
2 Creating Custom Components and Domains
Note The block user cannot change the initialization priority of the member component variable. You
specify the variable initialization priority when you declare the member component. The syntax is the
same as described in “Variable Priority for Model Initialization” on page 2-9.
For example, you have a composite DC Motor block (similar to the one described in “Composite
Component — DC Motor” on page 2-96) and want the block user to specify the initial target value
for the inductor current, with low priority. The following code includes a Foundation library Inductor
block in your custom component file, with the ability to control its inductance at the top level (by
using the Rotor Inductance block parameter) and also to specify a low-priority initial target for the
inductor current variable:
component DCMotor2
[...]
parameters
rotor_inductance = { 12e-6, 'H' }; % Rotor Inductance
i0 = { 0, 'A' }; % Initial current target for Rotor Inductor
[...]
end
components(ExternalAccess=observe)
rotorInductor = foundation.electrical.elements.inductor(l = rotor_inductance,
i_L = {value = i0, priority = priority.low});
[...]
end
[...]
end
In this case, the block user can specify a value for the Initial current target for Rotor Inductor
parameter, which appears in the block dialog box of the composite component. This value gets
assigned as the initial target to variable i_L (Initial current variable of the member Inductor block),
with low initialization priority. Depending on the results of the solve, the target may or may not be
satisfied when the solver computes the initial conditions for simulation. For more information, see
“Block-Level Variable Initialization”.
You can use an alternative syntax that lets you assign the variable value and priority data fields
separately, using the dot notation. For example, the following statement:
rotorInductor = foundation.electrical.elements.inductor(l = rotor_inductance,
i_L.value = i0, i_L.priority = priority.low);
2-64
Specifying Initial Target Values for Member Variables
See Also
Related Examples
• “Composite Component — DC Motor” on page 2-96
More About
• “Declaring Member Components” on page 2-61
• “Parameterizing Composite Components” on page 2-62
• “Specifying Component Connections” on page 2-66
2-65
2 Creating Custom Components and Domains
The structure section begins with a connections keyword and is terminated by an end keyword.
This connections block contains a set of connect constructs, which describe both the conserving
connections (between nodes) and the physical signal connections (between the inputs and
outputs).
In the following example, the custom component file includes the Foundation library Voltage Sensor
and Electrical Reference blocks and specifies the following connections:
• Positive port of the voltage sensor to the external electrical conserving port + of the composite
component
• Negative port of the voltage sensor to ground
• Physical signal output port of the voltage sensor to the external output of the composite
component, located on the right side of the resulting block icon
component VoltSG
nodes
p = foundation.electrical.electrical; % +
end
outputs
Out = { 0.0, 'V' }; % V:right
end
components(ExternalAccess=observe)
VoltSensor = foundation.electrical.sensors.voltage;
Grnd = foundation.electrical.elements.reference;
2-66
Specifying Component Connections
end
connections
connect(p, VoltSensor.p);
connect(Grnd.V, VoltSensor.n);
connect(VoltSensor.V, Out);
end
end
In this example, the first two connect constructs specify conserving connections between electrical
nodes. The third connect construct is a physical signal connection. Although these constructs look
similar, their syntax rules are different.
Conserving Connections
For conserving connections, the connect construct can have two or more arguments. For example,
the connections in the following example
connections
connect(R1.p, R2.n);
connect(R1.p, R3.p);
end
connections
connect(R1.p, R2.n, R3.p);
end
The order of arguments does not matter. The only requirement is that the nodes being connected are
all of the same type (that is, are all associated with the same domain).
In the following example, the composite component consists of three identical resistors connected in
parallel:
component ParResistors
nodes
p = foundation.electrical.electrical;
n = foundation.electrical.electrical;
end
parameters
p1 = {3 , 'Ohm'};
end
components(ExternalAccess=observe)
r1 = foundation.electrical.elements.resistor(R=p1);
r2 = foundation.electrical.elements.resistor(R=p1);
r3 = foundation.electrical.elements.resistor(R=p1);
end
connections
connect(r1.p, r2.p, r3.p, p);
connect(r1.n, r2.n, r3.n, n);
end
end
2-67
2 Creating Custom Components and Domains
connections
connect(A, *);
end
The implicit reference node acts as a virtual grounding component. A node connected to an implicit
reference has all its Across variables equal to 0.
The * symbol is not domain-specific, and the same structure section can contain connections to
implicit reference in different domains:
component abc
nodes
M = foundation.hydraulic.hydraulic;
N = foundation.electrical.electrical;
end
connections
connect(M,*);
connect(N,*);
end
end
However, multiple ports connected to an implicit reference within the same connect statement must
all belong to the same domain:
connections
connect(a, b, *);
end
The order of ports does not matter. This behavior is consistent with general connection rules for
multiple conserving ports.
connect(s, d);
There can be more than one destination port connected to the same source port:
The source and destination ports belong to the inputs or outputs member classes. The following
table lists valid source and destination combinations.
Source Destination
External input port of composite component Input port of member component
2-68
Specifying Component Connections
Source Destination
Output port of member component Input port of member component
Output port of member component External output port of composite component
Construct Explanation
connect(In, subt.I1); Connects port In to the input port + of the PS
Subtract block. Illustrates connecting an input
port of the composite component to an input port
of a member component.
connect(subt.O, gain.I); Connects the output port of the PS Subtract block
to the input port of the PS Gain block. Illustrates
connecting an output port of a member
component to an input port of another member
component at the same level.
connect(fl_rate.Q, subt.I2, Out); Connects the output port Q of the Hydraulic Flow
Rate Sensor block to the input port - of the PS
Subtract block and to the output port Out of the
composite component. Illustrates connecting a
single source to multiple destinations, and also
connecting an output port of a member
component to an output port of the enclosing
composite component.
Also notice that the output port of the PS Gain block is connected to the input port of the Valve
Subsystem composite block (another member component at the same level). Valve Subsystem is a
standalone composite component, and therefore if you connect the output port of the PS Gain block
to an input port of one of the member components inside the Valve Subsystem, that would violate the
causality of the physical signal connections (a destination port cannot be connected to multiple
sources).
2-69
2 Creating Custom Components and Domains
• Aggregating measurements at different spatial points, such as temperatures along a coil or a 2-D
grid of elements
• Using 3-D body positions or velocities
• Using rotation matrices or quaternions in 3-D
• Using tensors
inputs
I = {zeros(3), 'm/s'}; % :left
end
When you connect input and output ports carrying nonscalar physical signals, you can use signal
indexing and concatenation at the source, but not at the destination. Scalar expansion is not allowed.
The following table shows valid syntax examples, assuming subcomponent A with output signal port
A.o is being connected to subcomponent B with input signal port B.i, and all sizes and units are
compatible.
Construct Explanation
connect(A.o(1,2), B.i); Source indexing, to connect to a scalar
destination: take entry (1,2) of the output A.o and
connect it to the input B.i.
connect(A.o(1:2:5,2:3), B.i); Index by rows and columns to specify a
submatrix.
connect(A.o(1:2:end,:), B.i); Use colon notation to specify array boundaries
(pass every other column of the output A.o to
input B.i.
connect([A1.o, A2.o], B.i); Concatenate outputs A1.o and A2.o column-wise
and pass the result to the input B.i.
You can use block parameter values for indexing inside a connect statement, for example:
When you connect two physical signals, their units must be directly convertible. If one of the signals
is declared as unitless (that is, with units of '1') , then you can connect a signal with any base units
to it. However, unit conversion is not supported in this case. For example, if a.i is a 2x1 unitless
input port, then this statement is valid:
2-70
Specifying Component Connections
If you connect signals with different scales of the same unit with a unitless input port, the compiler
alerts you to the fact that unit conversion is ignored. For example, the following statement produces a
warning at compile time:
See Also
Related Examples
• “Composite Component — DC Motor” on page 2-96
More About
• “Declaring Member Components” on page 2-61
• “Parameterizing Composite Components” on page 2-62
• “Specifying Initial Target Values for Member Variables” on page 2-64
2-71
2 Creating Custom Components and Domains
The subsystem2ssc function lets you convert a subsystem consisting entirely of Simscape blocks
into a textual Simscape file. The function generates a composite component file based on the
subsystem configuration. If the subsystem being converted contains nested subsystems, then the
function generates several Simscape files, one for each subsystem.
• Facilitate the authoring of composite components. When writing textual files, it can be difficult to
visualize the connections inside a composite component. This functionality lets you create a model
out of Simscape blocks, enclose it into a subsystem, and then convert this subsystem into a textual
composite component.
• Improve the usability of a complex subsystem, by reducing clutter and exposing only a few
relevant parameters at the top level.
• Share your models with customers without revealing the underlying intellectual property.
Suggested Workflows
To create a reusable composite component:
1 Model a physical component (such as a motor, valve, amplifier, and so on) using blocks from the
Simscape Foundation library, add-on product libraries, or custom blocks. Fine-tune the
parameters and troubleshoot the model, as necessary.
2 Select the blocks and connection lines that represent your physical component, and create a
subsystem from selection. For more information, see “Create Subsystems”.
The subsystem does not need to be masked. However, to expose underlying block parameters or
variables at the top level, you have to mask the subsystem and promote these parameters or
variables to the subsystem mask. For more information, see “Parameter Promotion” on page 2-
73.
3 Use the subsystem2ssc function to convert your subsystem into a textual composite
component. If the subsystem being converted contains nested subsystems, then the function
generates several Simscape files, one for each subsystem.
1 When converting the subsystem, use the subsystem2ssc function with a targetFolder
argument to place the file or files generated by the function into a target folder.
For example,
subsystem2ssc('ssc_dcmotor/DC Motor','./MotorsLibrary')
creates a file named DC_Motor.ssc and places it into the folder named MotorsLibrary.
2-72
Converting Subsystems into Composite Components
2 Create and place other motor models into the same target folder.
3 Protect the source files in the target folder by using the ssc_protect function.
4 Share the contents of the folder with other users or customers without revealing the underlying
source.
You can place generated files into a package folder and build a library by using the ssc_build or
ssc_mirror functions. However, if your subsystem contains nested subsystems, you have to edit the
subcomponent paths in the generated files manually to match your intended package structure.
Alternatively, you can use the Simscape Component blocks, which work with the flat hierarchy of the
target folder without modification.
Parameter Promotion
You can mark member block and subsystem parameters for promotion to the top level using the
subsystem mask. The subsystem2ssc function automatically generates the corresponding Simscape
code, similar to composite components. For more information, see “Parameterizing Composite
Components” on page 2-62.
When you deploy the generated composite file as a custom block, the block dialog box contains these
promoted parameters only.
This example shows how you can make the motor inertia modifiable at the DC Motor subsystem level,
and the effect on generated Simscape code and the resulting custom block mask:
1 Open the Permanent Magnet DC Motor example model by typing ssc_dcmotor in the MATLAB
Command Window.
2 Right-click the DC Motor subsystem and, from the context menu, select Mask > Edit Mask.
3 Click the Parameters & Dialog tab. Use the Promote One-to-One control option to promote
the Inertia parameter of the Inertia block to the subsystem mask.
2-73
2 Creating Custom Components and Domains
The function creates a file named DC_Motor.ssc in the current folder. Open the file in the
editor.
component DC_Motor
parameters
inertia = {.01, 'cm^2*g'}; %Inertia
end
nodes
C = foundation.mechanical.rotational.rotational;
R = foundation.mechanical.rotational.rotational;
V1 = foundation.electrical.electrical;
V0 = foundation.electrical.electrical;
end
components(ExternalAccess = observe)
Rotor_Resistance = foundation.electrical.elements.resistor(R = {3.9, 'Ohm'});
Rotor_Inductance = foundation.electrical.elements.inductor(l = {1.2e-05, 'H'}, r = {0, 'Ohm'}, g = {1e-09, '1/Ohm'}, i_L = {val
Rotational_Electromechanical_Converter = foundation.electrical.elements.rotational_converter(K = {.0006875493541569879, 's*V/ra
Inertia = foundation.mechanical.rotational.inertia(inertia = inertia);
2-74
Converting Subsystems into Composite Components
Limitations
The subsystem being converted must consist entirely of blocks authored in Simscape language, such
as blocks from the Simscape Foundation library, add-on product libraries, or custom blocks. Blocks
from the Simscape “Utilities” library are not authored in Simscape language, therefore:
• If the subsystem contains a Simscape Component block, then during the conversion this block is
replaced by its source component.
• Connection Port blocks are represented by the connect statements.
• Other blocks from the Utilities library (Solver Configuration, Simscape Bus, and so on) are not
allowed because they have no equivalent textual representation.
If the subsystem being converted contains nested subsystems, you might have to manually edit the
references to the generated files for nested subsystems when running ssc_build on the package.
If you use blocks from Simscape libraries, keep the original subsystem used to generate the
composite component. Simscape language does not support forwarding tables or versioning. As a
result, if the underlying library blocks undergo changes in a future release, a textual composite
component generated from these blocks might stop working. If that happens, open the original
subsystem in the new release and rerun the conversion.
See Also
subsystem2ssc | components | connections | ssc_build | ssc_mirror | ssc_protect
2-75
2 Creating Custom Components and Domains
More About
• “Declaring Member Components” on page 2-61
• “Parameterizing Composite Components” on page 2-62
• “Specifying Component Connections” on page 2-66
• “Building Custom Block Libraries” on page 4-21
2-76
Defining Component Variants
Physical modeling often requires incremental modeling approach. It is a good practice to start with a
simple model, run and troubleshoot it, then add the desired special effects, like fluid compressibility
or fluid inertia. Another example is modeling a diode with different levels of complexity: linear, zener
diode, or exponential. Composite components often require conditional inclusion of a certain member
component and a flexible connection scheme.
Including different modeling variants within a single component requires applying control logic to
determine the model configuration. You achieve this goal by using conditional sections in a
component file.
Conditional Sections
A conditional section is a top-level section guarded by an if clause. Conditional sections are parallel
to other top-level sections of a component file, such as declaration or equations sections.
A conditional section starts with an if keyword and ends with an end keyword. It can have optional
elseif and else branches. The body of each branch of a conditional section can contain declaration
blocks, equations, structure sections, and so on, but cannot contain the setup function.
The if and elseif branches start with a predicate expression. If a predicate is true, the branch gets
activated. When all predicates are false, the else branch (if present) gets activated. The compiled
model includes elements (such as declarations, equations, and so on) from active branches only.
component MyComp
[...]
if Predicate1
[...] % body of branch1
elseif Predicate2
[...] % body of branch2
else
[...] % body of branch3
end
[...]
end
Unlike the if statements in the equations section, different branches of a conditional section can
have different variables, different number of equations, and so on. For example, you can have two
variants of a pipe, one that accounts for resistive properties only and the second that also models
fluid compressibility:
component MyPipe
parameters
fl_c = 0; % Model compressibility? (0 - no, 1 - yes)
end
[...] % other parameters, variables, branches
if fl_c == 0
equations
% first set of equations, resistive properties only
2-77
2 Creating Custom Components and Domains
end
else
variables
% additional variable declarations, needed to account for fluid compressibility
end
equations
% second set of equations, including fluid compressibility
end
end
end
In this example, if the block parameter Model compressibility? (0 - no, 1 - yes) is set to 0, the first
set of equations gets activated and the block models only the resistive properties of the pipe. If the
block user changes the value of the parameter, then the else branch gets activated, and the
compiled model includes the additional variables and equations that account for fluid compressibility.
Note Enumerations are very useful in defining component variants, because they let you specify a
discrete set of acceptable parameter values. For an example of how this component can use
enumeration, see “Using Enumeration in Predicates” on page 3-17.
Predicates must be parametric expressions, because the structure of a model must be fixed at
compile time and cannot change once the model is compiled. Using a variable in a predicate results in
a compile-time error:
component A
[...]
variables
v = 0;
end
if v > 0 % error: v>0 is not a parametric expression because v is a variable
[...]
else
[...]
end
end
Predicates may depend on parameters of the parent (enclosing) component. They may not depend,
directly or indirectly, on parameters of member (embedded) components or on domain parameters:
2-78
Defining Component Variants
component A
parameters
p = 1;
end
parameters(Access=private)
pp = c.p;
end
components
c = MyComp;
end
nodes
n = MyDomain;
end
if p > 0 % ok
[...]
elseif c.p > 0 % error: may not depend on parameters of embedded component
[...]
elseif n.p > 0 % error: may not depend on domain parameters
[...]
elseif pp > 0 % error: pp depends on c.p
[...]
end
end
Accessibility of class members declared inside conditional sections is equivalent to private class
members (Access=private). They are not accessible from outside the component class, even if
their branch is active.
The scope of the class members declared inside a conditional section is the entire component class.
For example:
component A
nodes
p = foundation.electrical.electrical;
n = foundation.electrical.electrical;
end
parameters
p1 = 1;
end
if p1 > 0
components
r1 = MyComponentVariant1;
end
else
components
r1 = MyComponentVariant2;
end
end
connections
connect(p, r1.p);
connect(n, r1.n);
end
end
However, using a conditional member outside the conditional section when the branch is not active
results in a compilation error:
component A
nodes
p = foundation.electrical.electrical;
n = foundation.electrical.electrical;
end
2-79
2 Creating Custom Components and Domains
parameters
p1 = 0;
end
if p1 > 0
components
r1 = MyComponentVariant1;
end
end
connections
connect(p, r1.p); % error if p1=0 and the predicate is false
end
end
Parameters that are referenced by predicates of conditional sections, directly and indirectly, must be
compile-time parameters. The setup function may not write to these parameters, for example:
component A
parameters
p1 = 1;
end
if p1 > 0 % p1 is a compile-time parameter
[...]
else
[...]
end
function setup
tmp = p1; % ok to read from p1
p1 = 10; % error: may not write to p1 here
end
end
Example
This simple example shows a component containing two resistors. The resistors can be connected
either in series or in parallel, depending on the value of the control parameter:
component TwoResistors
nodes
p = foundation.electrical.electrical; % +:left
n = foundation.electrical.electrical; % -:right
end
parameters
p1 = {1, 'Ohm'}; % Resistor 1
p2 = {1, 'Ohm'}; % Resistor 2
ct = 0; % Connection type (0 - series, 1 - parallel)
end
components(ExternalAccess=observe)
r1 = foundation.electrical.elements.resistor(R=p1);
r2 = foundation.electrical.elements.resistor(R=p2);
end
if ct == 0 % linear connection
connections
connect(p, r1.p);
connect(r1.n, r2.p);
connect(r2.n, n);
end
else % parallel connection
2-80
Defining Component Variants
connections
connect(r1.p, r2.p, p);
connect(r1.n, r2.n, n);
end
end
end
To test the correct behavior of the conditional section, point a Simscape Component block to this
component file. Place the block in a circuit with a 10V DC voltage source and a current sensor. With
the default parameter values, the resistors are connected in series, and the current is 5A.
If you change the value of the Connection type (0 - series, 1 - parallel) parameter to 1, the
resistors are connected in parallel, and the current is 20A.
2-81
2 Creating Custom Components and Domains
See Also
More About
• “Defining Conditional Visibility of Component Members” on page 2-83
• “Component Variants — Series RLC Branch” on page 2-85
• “Component Variants — Thermal Resistor” on page 2-87
2-82
Defining Conditional Visibility of Component Members
When you define component variants using conditional declarations, certain parameters, variables, or
ports can be used in one block variant but not in others. For example, you have a component that
models hydraulic pipelines with circular and noncircular cross sections. For a circular pipe, you need
to specify its internal diameter. For a noncircular pipe, you need to specify its hydraulic diameter and
pipe cross-sectional area. You can now use the annotations section to control the visibility of these
parameters in the block dialog box:
component MyPipe
parameters
circular = true; % Circular pipe?
d_in = { 0.01, 'm' }; % Pipe internal diameter
area = { 1e-4, 'm^2' }; % Noncircular pipe cross-sectional area
D_h = { 1.12e-2, 'm' }; % Noncircular pipe hydraulic diameter
end
if circular
% Hide inapplicable parameters
annotations
[area, D_h] : ExternalAccess=none;
end
equations
% first set of equations, for circular pipe
end
else
% Hide inapplicable parameter
annotations
d_in : ExternalAccess=none;
end
equations
% second set of equations, for noncircular pipe
end
end
[...] % other parameters, variables, branches, equations
end
The annotations section lets you control visibility of the following component members:
• Parameters
• Variables
• Nodes
• Inputs
• Outputs
The annotations section also lets you specify conditional custom icons. This is especially useful if
the number of ports changes for different variants. For example:
component MyPipe
parameters
2-83
2 Creating Custom Components and Domains
For more information on using custom block icons, see “Customize the Block Icon” on page 4-38.
Member attributes must be uniquely defined, which means that the same member cannot be declared
more than once, with different values of the same attribute. The only exception to this rule is the use
of ExternalAccess attribute in the annotations section. You can declare a component member
with a certain value of ExternalAccess, and then specify a different ExternalAccess attribute
value in the annotations section, for example:
component MyPipe
parameters
circular = true; % Circular pipe?
end
parameters(ExternalAccess=none)
d_in = { 0.01, 'm' }; % Pipe internal diameter
[...]
end
if circular
% Expose pipe diameter
annotations
d_in : ExternalAccess=modify;
end
[...]
In case of conflict, the ExternalAccess attribute value specified in the annotations section
overrides the value specified for that member in the declaration section. For a complete component
example using this approach, see “Component Variants — Thermal Resistor” on page 2-87.
See Also
More About
• “Defining Component Variants” on page 2-77
• “Component Variants — Thermal Resistor” on page 2-87
• “Component Variants — Series RLC Branch” on page 2-85
2-84
Component Variants — Series RLC Branch
2-85
2 Creating Custom Components and Domains
connections
connect(lc, n); % short circuit lc--n
end
end
end
The R, L, and C parameters are initialized to 0, 0, and inf, respectively. If the block user specifies a
nonzero resistance, nonzero impedance, or finite capacitance, the appropriate branch gets activated.
The active branch declares the appropriate member component and connects it in series. Each of the
else clauses short-circuits the appropriate nodes.
Internal nodes rl and lc, which serve to connect the member components, should not be accessible
from outside the component. Set their Access attribute to protected or private. Their
ExternalAccess attribute is none, so that these nodes are not visible on the block icon.
See Also
More About
• “Defining Component Variants” on page 2-77
• “Parameterizing Composite Components” on page 2-62
• “Specifying Component Connections” on page 2-66
2-86
Component Variants — Thermal Resistor
nodes
p = foundation.electrical.electrical; % +:left
n = foundation.electrical.electrical; % -:right
H = foundation.thermal.thermal; % H:left
end
parameters
thermal_effects = simscape.enum.onoff.off; % Model thermal effects
end
parameters(ExternalAccess=none)
R = { 1, 'Ohm' }; % Nominal resistance
T0 = {300,'K'}; % Reference temperature
alpha = {50e-6,'1/K'}; % Temperature coefficient
tc = {10,'s'}; % Thermal time constant
K_d = {1e-3,'W/K'}; % Dissipation factor
end
variables(ExternalAccess=none)
i = { 0, 'A' }; % Current
v = { 0, 'V' }; % Voltage
T1 = {value = {300,'K'}, priority = priority.high}; % Temperature
end
branches
i : p.i -> n.i;
end
equations
v == p.v - n.v;
end
if thermal_effects == simscape.enum.onoff.off
annotations
% Show non-thermal settings
Icon = 'custom_resistor.png';
[R, i, v] : ExternalAccess=modify;
% Hide thermal node
2-87
2 Creating Custom Components and Domains
H : ExternalAccess=none;
end
connections
connect(H, *); % Connect hidden thermal node to reference
end
equations
R*i == v;
T1 == T0; % Temperature is constant
end
else
annotations
% Show thermal settings
Icon = 'custom_resistor_thermal.png';
[T1, T0, alpha, tc, K_d, H] : ExternalAccess=modify;
end
end
end
The component initially declares all the optional parameters and variables with the ExternalAccess
attribute set to none, and then exposes them selectively by using the conditional annotations
sections. The opposite method, of hiding inapplicable members, is also valid, but this approach is
more easily scalable when you have multiple component configurations.
If the control parameter, Model thermal effects, is set to Off, the block represents a linear resistor.
The only exposed block parameter is Nominal resistance, the Initial Targets section lets you set
targets for Current and Voltage, and the block icon has two ports, + and -.
2-88
Component Variants — Thermal Resistor
If the Model thermal effects parameter is set to On, the block represents a resistor with a thermal
port, with temperature-dependent resistance. The block parameters, variable initialization targets,
ports, and the custom block icon change accordingly.
2-89
2 Creating Custom Components and Domains
See Also
More About
• “Defining Component Variants” on page 2-77
• “Defining Conditional Visibility of Component Members” on page 2-83
2-90
Mechanical Component — Spring
The branches section establishes the relationship between the component Through variable and the
component nodes (and therefore the domain Through variable). The t : r.t -> c.t statement
indicates that the torque through the spring acts from node r to node c.
The equation section starts with an assert construct, which checks that the spring rate is greater
than zero. If the block parameter is set incorrectly, the assert triggers a run-time error.
The first equation, w == r.w - c.w, establishes the relationship between the component Across
variable and the component nodes (and therefore the domain Across variable). It defines the angular
velocity across the spring as the difference between the node angular velocities.
• t = k * theta, that is, torque equals spring deformation times spring rate
• w = theta.der, that is, angular velocity equals time derivative of spring deformation
component spring
nodes
r = foundation.mechanical.rotational.rotational;
c = foundation.mechanical.rotational.rotational;
end
parameters
k = { 10, 'N*m/rad' };
end
variables
theta = { 0, 'rad' };
t = { 0, 'N*m' }; % torque through
w = { 0, 'rad/s' }; % velocity across
end
branches
t : r.t -> c.t; % torque through from node r to node c
end
equations
assert(k>0) % spring rate must be greater than zero
w == r.w - c.w; % velocity across between node r and node c
t == k * theta;
w == theta.der;
end
end
2-91
2 Creating Custom Components and Domains
Variable v is declared with high initialization priority, to ensure the initial voltage of 0 V.
The branches section establishes the relationship between the component Through variable and the
component nodes (and therefore the domain Through variable). The i : p.i -> n.i statement
indicates that the current through the capacitor flows from node p to node n.
The equation section starts with an assert construct, which checks that the capacitance value is
greater than zero. If the block parameter is set incorrectly, the assert triggers a run-time error.
The first equation, v == p.v - n.v, establishes the relationship between the component Across
variable and the component nodes (and therefore the domain Across variable). It defines the voltage
across the capacitor as the difference between the node voltages.
The second equation defines the capacitor action: I = C*dV/dt, that is, output current equals
capacitance multiplied by the time derivative of the input voltage.
component ideal_capacitor
% Ideal Capacitor
% Models an ideal (lossless) capacitor. The output current I is related
% to the input voltage V by I = C*dV/dt where C is the capacitance.
nodes
p = foundation.electrical.electrical; % +:top
n = foundation.electrical.electrical; % -:bottom
end
parameters
C = { 1, 'F' }; % Capacitance
end
variables
i = { 0, 'A' }; % Current
v = {value = { 0, 'V' }, priority = priority.high}; % Voltage
end
branches
i : p.i -> n.i; % Current through from node p to node n
end
equations
assert(C > 0)
v == p.v - n.v; % Voltage across between node p and node n
i == C*v.der; % Equation defining the capacitor action
end
end
2-92
No-Flow Component — Voltage Sensor
Note that a Through variable (current ) is not declared, and there is no branches section.
In the equation section, the first equation, v == p.v - n.v, establishes the relationship between
the component Across variable, voltage v1, and the component nodes (and therefore the domain
Across variable at these nodes). It defines the voltage across the sensor as the difference between the
node voltages.
• V == v1, that is, output voltage equals the voltage across the sensor nodes
component voltage_sensor
% Voltage Sensor
% The block represents an ideal voltage sensor. There is no current
% flowing through the component, therefore it is unnecessary to
% declare a Through variable (i1), use a branches section, or
% create an equation statement for current (such as i1 == 0).
%
% Connection V is a physical signal port that outputs voltage value.
outputs
V = { 0.0, 'V' }; % V:bottom
end
nodes
p = foundation.electrical.electrical; % +:top
n = foundation.electrical.electrical; % -:bottom
end
variables
v1 = { 0, 'V' };
end
equations
v1 == p.v - n.v;
V == v1;
end
end
2-93
2 Creating Custom Components and Domains
component reference
% Electrical Reference :0.5
% Electrical reference port. A model must contain at least one
% electrical reference port (electrical ground).
nodes
V = foundation.electrical.electrical; % :top
end
connections
connect(V, *);
end
end
For more information on component connections and the implicit reference node syntax, see
“Connections to Implicit Reference Node” on page 2-68.
The branches section establishes the relationship between the component Through variable, current
i, and the component nodes (and therefore the domain Through variable). The i : V.i -> *
statement indicates that the current flows from node V to the reference node, indicated as *.
The equation section of the component contains the equation that defines the grounding action:
nodes
V = foundation.electrical.electrical; % :top
end
variables
i = { 0, 'A' };
2-94
Grounding Component — Electrical Reference
end
branches
i : V.i -> *;
end
equations
V.v == 0;
end
end
See Also
More About
• “Specifying Component Connections” on page 2-66
2-95
2 Creating Custom Components and Domains
The following code implements the same model by means of a composite component, called DC
Motor. The composite component uses the components from the Simscape Foundation library as
building blocks, and connects them as shown in the preceding block diagram.
component DC_Motor
% DC Motor
% This block models a DC motor with an equivalent circuit comprising a
% series connection of a resistor, inductor, and electromechanical converter.
% Default values are as for the DC Motor Simscape example, ssc_dcmotor.
nodes
p = foundation.electrical.electrical; % +:left
n = foundation.electrical.electrical; % -:left
R = foundation.mechanical.rotational.rotational; % R:right
C = foundation.mechanical.rotational.rotational; % C:right
end
parameters
rotor_resistance = { 3.9, 'Ohm' }; % Rotor Resistance
rotor_inductance = { 12e-6, 'H' }; % Rotor Inductance
motor_inertia = { 0.01, 'g*cm^2' }; % Inertia
breakaway_torque = { 0.02e-3, 'N*m' }; % Breakaway friction torque
coulomb_torque = { 0.02e-3, 'N*m' }; % Coulomb friction torque
breakaway_velocity = { 0.1, 'rad/s' }; % Breakaway friction velocity
back_emf_constant = { 0.072e-3, 'V/rpm' }; % Back EMF constant
end
components(ExternalAccess=observe)
rotorResistor = foundation.electrical.elements.resistor(R = rotor_resistance);
rotorInductor = foundation.electrical.elements.inductor(l = rotor_inductance);
rotationalElectroMechConverter = foundation.electrical.elements.rotational_converter(K = ...
back_emf_constant);
friction = foundation.mechanical.rotational.friction(brkwy_trq = ...
breakaway_torque, Col_trq = coulomb_torque, ...
brkwy_vel = breakaway_velocity);
motorInertia = foundation.mechanical.rotational.inertia(inertia = motor_inertia);
end
connections
connect(p, rotorResistor.p);
connect(rotorResistor.n, rotorInductor.p);
connect(rotorInductor.n, rotationalElectroMechConverter.p);
connect(rotationalElectroMechConverter.n, n);
connect(rotationalElectroMechConverter.R, friction.R, motorInertia.I, R);
connect(rotationalElectroMechConverter.C, friction.C, C);
end
end
The declaration section of the composite component starts with the nodes section, which defines the
top-level connection ports of the resulting composite block:
• Two electrical conserving ports, + and -, on the left side of the block
2-96
Composite Component — DC Motor
• Two mechanical rotational conserving ports, R and C, on the right side of the block
The parameters declaration block lists all the parameters that will be available in the composite
block dialog box.
The components block declares all the member (constituent) components, specifying their complete
names starting from the top-level package directory. This example uses the components from the
Simscape Foundation library:
• Resistor
• Inductor
• Rotational Electromechanical Converter
• Rotational Friction
• Inertia
The components block also links the top-level parameters, declared in the parameters declaration
block, to the parameters of underlying member components. For example, the Rotor Resistance
parameter of the composite block (rotor_resistance) corresponds to the Resistance parameter
(R) of the Resistor block in the Foundation library.
You do not have to link all the parameters of member blocks to top-level parameters. For example, the
Rotational Friction block in the Foundation library has the Viscous friction coefficient parameter,
which is not mapped to any parameter at the top level. Therefore, the composite model always uses
the default value of this parameter specified in the Rotational Friction component, 0.001 N*m/(rad/s).
The connections block defines the connections between the nodes (ports) of the member
components, and their connections to the top-level ports of the resulting composite block, declared in
the nodes declaration block of the composite component:
• Positive electrical port p of the composite component is connected to the positive electrical port p
of the Resistor
2-97
2 Creating Custom Components and Domains
• Negative electrical port n of the Resistor is connected to the positive electrical port p of the
Inductor
• Negative electrical port n of the Inductor is connected to the positive electrical port p of the
Rotational Electromechanical Converter
• Negative electrical port n of the Rotational Electromechanical Converter is connected to the
negative electrical port n of the composite component
• Mechanical rotational port R of the composite component is connected to the following mechanical
rotational ports: R of the Rotational Electromechanical Converter, R of the Rotational Friction, and
I of the Inertia
• Mechanical rotational port C of the composite component is connected to the following mechanical
rotational ports: C of the Rotational Electromechanical Converter and C of the Rotational Friction
These connections are the textual equivalent of the graphical connections in the preceding block
diagram.
See Also
More About
• “About Composite Components” on page 2-60
• “Declaring Member Components” on page 2-61
• “Parameterizing Composite Components” on page 2-62
• “Specifying Initial Target Values for Member Variables” on page 2-64
• “Specifying Component Connections” on page 2-66
2-98
Working with Domain Parameters
All components with nodes connected to this domain will have access to the fluid temperature
parameter t. The component examples in the following sections assume that this domain file,
t_hyd.ssc, is located in a package named +THyd.
When dealing with domain parameters, there are three different types of components. There are
some components that provide the domain parameter values used in the larger model, there are some
that simply propagate the parameters, and there are some that do not propagate parameters.
For a complete example of building a custom block library based on this domain definition and using
propagation of domain parameters in a simple circuit, see “Custom Library with Propagation of
Domain Parameters” on page 2-101.
Source Components
Source components provide a way to modify the domain parameter values. You declare a component
parameter, and then use direct assignment to a domain parameter in the component node
declaration. This assignment establishes the connection, which lets the parameter of the source
component control the domain parameter value.
2-99
2 Creating Custom Components and Domains
The following is an example of a source component, connected to the hydraulic domain t_hyd,
defined in “Propagation of Domain Parameters” on page 2-99. This component provides the value of
the temperature parameter to the rest of the model.
component hyd_temp
% Hydraulic Temperature
% Provide hydraulic temperature to the rest of the model
parameters
t = {333,'K'}; % Fluid temperature
end
nodes
a = THyd.t_hyd(t=t); % t_hyd node with direct parameter assignment
end
end
When you generate a Simscape block from this component file, the block dialog box will have a
parameter labelled Fluid temperature. You can then use it to enter the temperature value for the
hydraulic fluid used in the model. You cannot have more than one block controlling the same domain
parameter connected to a circuit, unless different segments of the circuit are separated by a blocking
component.
Propagating Components
The default setting for the Propagation component attribute is propagates. Most components use
this setting. If a component is configured to propagate its domain parameters, then all public nodes
connected to this domain have the same set of domain parameters. These parameters are accessible
in equations and other sections of the component file.
Blocking Components
Blocking components are those components that do not propagate domain parameters. These
components have their Propagation attribute set to blocks. If your model requires different values
of a domain parameter in different segments of the same circuit, use blocking components to
separate these segments and connect each segment to its own source component. For more
information, see “Attribute Lists” on page 2-104.
2-100
Working with Domain Parameters
• Create the necessary domain and component files and organize them in a package. For more
information, see “Organizing Your Simscape Files” on page 4-21.
• Build a custom block library based on these Simscape files. For more information, see “Converting
Your Simscape Files” on page 4-22.
• Use these custom blocks to build a model and test propagation of domain parameters.
1 In a directory located on the MATLAB path, create a directory called +THyd. This is your package
directory, where you store all Simscape files created in the following steps.
2 Create the domain file t_hyd.ssc, as described in “Propagation of Domain Parameters” on page
2-99.
domain t_hyd
variables
p = {1e6,'Pa'}; % pressure
end
variables(Balancing = true)
q = {1e-3,'m^3/s'}; % flow rate
end
parameters
t = {303,'K'}; % fluid temperature
end
end
3 Create the component file hyd_temp.ssc, as described in “Source Components” on page 2-99.
This component provides the value of the temperature parameter to the rest of the model.
component hyd_temp
% Hydraulic Temperature
% Provide hydraulic temperature to the rest of the model
parameters
t = {333,'K'}; % Fluid temperature
end
nodes
a = THyd.t_hyd(t=t); % t_hyd node with direct parameter assignment
end
end
2-101
2 Creating Custom Components and Domains
5 In order to create a working circuit, you will need a reference block corresponding to the domain
type, as described in “Grounding Rules”. Create a reference component for your t_hyd domain,
as follows (name the component h_temp_ref.ssc):
component h_temp_ref
% Hydraulic Temperature Reference
% Provide reference for thermohydraulic circuits
nodes
a = THyd.t_hyd; % t_hyd node
end
connections
connect(a,*);
end
end
6 You can optionally define other components referencing the t_hyd domain, but this basic set of
components is enough to create a working circuit. Now you need to build a custom block library
based on these Simscape files. To do this, at the MATLAB command prompt, type:
ssc_build THyd;
7 This command generates a file called THyd_lib in the directory that contains your +THyd
package. Before using this library, restart MATLAB to register the new domain. Then open the
custom library by typing:
THyd_lib
ssc_new
This command creates a new model, prepopulated with the following blocks:
9 Delete the Simulink-PS Converter block, because our model is not going to have any Simulink
input signals.
10 Drag the Hydraulic Temperature, Hydraulic Temperature Sensor, and Hydraulic Temperature
Reference blocks from THyd_lib and connect them as follows:
2-102
Working with Domain Parameters
11 Simulate the model and notice that the scope displays the value of the domain temperature
parameter, as it is defined in the hyd_temp.ssc file, 333 K.
12 Double-click the Hydraulic Temperature block. Change the value of the Fluid temperature
parameter to 363 K.
13 Simulate the model again and notice that the scope now displays the new value of the domain
temperature parameter.
2-103
2 Creating Custom Components and Domains
Attribute Lists
In this section...
“Attribute Types” on page 2-104
“Model Attributes” on page 2-104
“Member Attributes” on page 2-105
Attribute Types
The attributes appear in an AttributeList, which is a comma separated list of pairs, as defined in the
MATLAB class system grammar. Simscape language distinguishes between two types of attributes:
model attributes and member attributes.
Model Attributes
Model attributes are applicable only to model type component.
2-104
Attribute Lists
Member Attributes
Member attributes apply to a whole declaration block.
2-105
2 Creating Custom Components and Domains
The attribute list for the declaration block appears after MemberClass keyword. For example:
Here, all parameters in the declaration block are externally writable in language, but they will not
appear in the block dialog box.
The two attributes defining member accessibility act in conjunction. The default value of the
ExternalAccess attribute for a member depends on the value of the Access attribute for that
member.
You can modify the values of the two attributes independently from each other. However, certain
combinations are prohibited. The compiler enforces the following rules:
• Members in the base class with Access=private are forced to have ExternalAccess=none, to
avoid potential collision of names between the base class and the derived class.
• When Access is explicitly set to private or protected, it does not make sense to explicitly set
ExternalAccess=modify . In this situation, the compiler issues a warning and remaps
ExternalAccess to observe.
2-106
Subclassing and Inheritance
By subclassing, the subclass inherits all of the members (such as parameters, variables, nodes) from
the base class and can add members of its own. When using the subclass as an external client, all
public members of the base class are available. All public and protected members of the base
class are available to the events, equation, structure, and other sections of the subclass. The subclass
may not declare a member with the same identifier as a public or protected member of the base
class.
The setup function of the base class is executed before the setup function of the subclass.
Note
• Starting in R2019a, using setup is not recommended. Other constructs available in Simscape
language let you achieve the same results without compromising run-time capabilities. For more
information, see “setup is not recommended” on page 5-40.
The equations of both the subclass and the base class are included in the overall system of equations.
For example, you can create the base class ElectricalBranch.ssc, which defines an electrical
branch with positive and negative external nodes, initial current and voltage, and relationship
between the component variables and nodes (and therefore, connects the component variables with
the Through and Across domain variables). Such a component is not very useful as a library block, so
if you do not want the base class to appear as a block in a custom library, set the Hidden=true
attribute value:
2-107
2 Creating Custom Components and Domains
If, for example, your base class resides in a package named +MyElectrical, then you can define the
subclass component Capacitor.ssc as follows:
The subclass component inherits the p and n nodes, the i and v variables with initial values, and the
relationship between the component and domain variables from the base class. This way, the
Capacitor.ssc file contains only parameters and equations specific to the capacitor.
You cannot override the Access attribute of base class members. For example, if a base class
member is declared as protected, it stays protected in all derived classes.
You cannot override values or attributes of base class members declared as private.
Annotation override can be conditional, except for annotation types that do not accept conditional
definition, such as Side. If the active branch does not explicitly define an annotation override, or if
none of the branches are active and an else branch is not explicitly defined, the annotation inherits
the attribute from the closest base class in the hierarchy.
2-108
Subclassing and Inheritance
intermediates
bm1 = 2*bv1+bp1;
end
annotations
Icon = 'file1.jpg';
bp1 : ExternalAccess = modify;
bp2 : ExternalAccess = observe;
end
end
Limitations for overriding default values of parameters and variables from the base class:
• You cannot reference other parameters from the base class. For example, when overriding the
value of bp1, you cannot reference bp2.
• You cannot reference conditional parameters.
• If the subclass is a composite component, you cannot reference parameters from its member
components.
• Parameters used in overriding parameters and variables from the base class cannot be run-time
configurable.
These limitations do not apply to intermediates. In the example, parameter p1 can be run-time
configurable because it is used in overriding the intermediate bm1. However, if it was overriding the
base class parameter bp1 (bp1 = p1), then p1 would be restricted to compile-time only.
See Also
annotations
More About
• “Defining Conditional Visibility of Component Members” on page 2-83
2-109
2 Creating Custom Components and Domains
In composite components, class member declarations include user-defined types, that is, component
classes. If you do not use import statements, accessing component class names from a different
scope always requires a fully qualified reference. For example, the Foundation library Resistor block
is:
foundation.electrical.elements.resistor
An import mechanism provides a convenient means to accessing classes defined in different scopes,
with the following benefits:
• Allows access to model class names defined in other scopes without a fully qualified reference
• Provides a simple and explicit view of dependencies on other packages
There are two types of syntax for the import statement. One is a qualified import, which imports a
specific package or class:
import package_or_class;
The other one is an unqualified import, which imports all subpackages and classes under the
specified package:
import package.*;
The package or class name must be a full path name starting from the library root (the top-level
package directory name) and containing subpackage names as necessary.
You must place import statements at the beginning of a Simscape file. The scope of imported names
is the entire Simscape file, except the setup section. For example, if you use the following import
statement:
import foundation.electrical.elements.*;
at the beginning of your component file, you can refer to the Foundation library Resistor block
elsewhere in this component file directly by name:
See the import on page 5-26 reference page for syntax specifics. For an example of using
import statements in a custom component, see the “Transmission Line” example. To view the
Simscape file, open the example, then double-click Open the transmission line component
library. In the TransmissionLine_lib window, double-click the T-Section Transmission Line block and
then, in the block dialog box, click Source code.
2-110
Importing Domain and Component Classes
See Also
Related Examples
• “Composite Component Using import Statements” on page 2-112
2-111
2 Creating Custom Components and Domains
nodes
p = electrical; % +:left
n = electrical; % -:left
R = rotational; % R:right
C = rotational; % C:right
end
parameters
rotor_resistance = { 3.9, 'Ohm' }; % Rotor Resistance
rotor_inductance = { 12e-6, 'H' }; % Rotor Inductance
motor_inertia = { 0.01, 'g*cm^2' }; % Inertia
breakaway_torque = { 0.02e-3, 'N*m' }; % Breakaway friction torque
coulomb_torque = { 0.02e-3, 'N*m' }; % Coulomb friction torque
breakaway_velocity = { 0.1, 'rad/s' }; % Breakaway friction velocity
back_emf_constant = { 0.072e-3, 'V/rpm' }; % Back EMF constant
end
components(ExternalAccess=observe)
rotorResistor = resistor(R = rotor_resistance);
rotorInductor = inductor(l = rotor_inductance);
rotationalElectroMechConverter = rotational_converter(K = back_emf_constant);
friction = friction(brkwy_trq = breakaway_torque, Col_trq = coulomb_torque, ...
brkwy_vel = breakaway_velocity);
motorInertia = inertia(inertia = motor_inertia);
end
connections
connect(p, rotorResistor.p);
connect(rotorResistor.n, rotorInductor.p);
connect(rotorInductor.n, rotationalElectroMechConverter.p);
connect(rotationalElectroMechConverter.n, n);
connect(rotationalElectroMechConverter.R, friction.R, motorInertia.I, R);
connect(rotationalElectroMechConverter.C, friction.C, C);
end
end
Consider the three import statements at the beginning of the file. The first one:
import foundation.electrical.electrical;
is a qualified import of the Foundation electrical domain class. Therefore, in the nodes section, you
can define the p and n nodes simply as electrical.
is an unqualified import, which imports all subpackages and classes under the
foundation.electrical.elements subpackage and therefore gives you direct access to all the
Foundation electrical components in the Elements sublibrary, such as inductor, resistor, and
rotational_converter.
2-112
Composite Component Using import Statements
import foundation.mechanical.rotational.*;
is an unqualified import, which imports all subpackages and classes under the
foundation.mechanical.rotational subpackage and therefore gives you direct access to the
Foundation mechanical rotational domain definition (rotational) and components (such as
friction and inertia).
The nodes block declares two electrical nodes, p and n, and two mechanical rotational nodes, R and
C.
The components block declares all the member (constituent) components, using the following
components from the Simscape Foundation library:
• Resistor
• Inductor
• Rotational Electromechanical Converter
• Rotational Friction
• Inertia
Because of the import statements at the top of the file, these classes already exist in the scope of the
file, and you do not have to specify their complete names starting from the top-level package
directory.
See Also
Related Examples
• “Composite Component — DC Motor” on page 2-96
More About
• “Importing Domain and Component Classes” on page 2-110
2-113
3
Advanced Techniques
These constructs in Simscape language let you perform mode chart modeling:
• modecharts — A top-level section in a component file. It can contain one or more modechart
constructs.
• modechart — A named construct that contains a textual representation of the mode chart:
modes, transitions, and an optional initial mode specification.
• modes — A section in a mode chart that describes all the operating modes. It can contain one or
more mode constructs.
• mode — A named construct that corresponds to a distinct operating mode of the component,
defined by a set of equations.
• transitions — A section in a mode chart that describes transitions between the operating
modes, based on predicate conditions.
• initial — An optional section in a mode chart that specifies the initial operating mode, based on
a predicate condition. If the predicate is not true, or if the initial section is missing, then the
first mode listed in the modes section is active at the start of simulation. If one of the other
predicate conditions is true at initialization time, then the simulation can start in a different mode,
as described in “Transition Precedence and Execution Rules” on page 5-0 .
• entry — An optional section inside a mode construct in a mode chart that lets you specify the
actions to be performed upon entering the mode.
3-2
Mode Chart Modeling
end
mode m2
equations
...
end
end
end
transitions
m1->m2 : p1;
end
initial
m2 : p2;
end
end
end
It contains one mode chart, mc1, with two modes, m1 and m2.
The system transitions from mode m1 to mode m2 when the predicate condition p1 is true.
If the predicate condition p2 is true, the simulation starts in mode m2, otherwise in mode m1.
In this example, the transitions section does not define a transition from mode m2 to mode m1.
Therefore, according to this mode chart, once the system reaches mode m2, it never goes back to
mode m1.
inputs
u1 = 0;
end
outputs
y = 0;
end
parameters
p = 1;
end
modecharts(ExternalAccess = observe)
mc1 = modechart
modes
mode m1
equations
y==1;
end
end
mode m2
equations
y==2;
end
3-3
3 Advanced Techniques
end
mode m3
equations
y==3;
end
end
end
transitions
m1->m2 : u1<0;
m2->m3 : u1>0;
end
initial
m2 : p<0;
end
end
end
end
The component transitions from the first to the second mode when the input signal is negative, and
from the second to the third mode when the input signal is positive.
The initial mode depends on the block parameter value: if parameter p is negative, simulation starts
with the block in the second mode, otherwise — in the first mode.
See Also
modecharts | modes | transitions | initial | entry
More About
• “Switch with Hysteresis” on page 3-5
• “State Reset Modeling” on page 3-11
3-4
Switch with Hysteresis
This example implements a switch with hysteresis applied to the switching threshold level. The
hysteresis acts to prevent rapid spurious switching when the control signal is noisy.
The switch has two distinct operating modes, shown in the diagram. If the external physical signal at
the control port is greater than the upper threshold, then the switch is closed. If the signal is lower
than the lower threshold, the switch is open.
The following component implements the logic in the diagram by using a mode chart.
component delayed_switch
% Switch with Hysteresis
inputs
u = { 0.0, '1' };
end
nodes
p = foundation.electrical.electrical; % +
n = foundation.electrical.electrical; % -:right
end
parameters
R_closed = { 0.01, 'Ohm' }; % Closed resistance R_closed
G_open = { 1e-8, '1/Ohm' }; % Open conductance G_open
T_closed = { 0.5, '1' }; % Upper threshold
T_open = { 0, '1' }; % Lower threshold
InitMode = switching.open; % Initial Mode
end
variables
i = { 0, 'A' }; % Current
v = { 0, 'V' }; % Voltage
end
branches
i : p.i -> n.i;
end
3-5
3 Advanced Techniques
modecharts(ExternalAccess = observe)
m1 = modechart
modes
mode CLOSED
equations
v == p.v - n.v;
v == i*R_closed;
end
end
mode OPEN
equations
v == p.v - n.v;
v == i/G_open;
end
end
end
transitions
CLOSED -> OPEN : u < T_open;
OPEN -> CLOSED : u > T_closed;
end
initial
OPEN : InitMode <= 0;
end
end
end
end
The mode chart m1 defines two modes, CLOSED and OPEN. Each mode has an equations section that
lists all the applicable equations. The transitions section defines the transitions between the
operating modes, based on predicate conditions:
• The switch transitions from CLOSED to OPEN when the control signal falls below the lower
threshold, T_open.
• The switch transitions from OPEN to CLOSED when the control signal rises above the upper
threshold, T_closed.
The initial section specifies the initial operating mode, based on a predicate condition:
• If the predicate is true (that is, the Initial Mode parameter value is less than or equal to 0), then
the OPEN mode is active at the start of simulation.
• If the predicate is not true, then the CLOSED mode (the first mode listed in the modes section) is
active at the start of simulation.
For the component to work as described, this enumeration needs to be in a separate switching.m
file. The file can be located either on the MATLAB path or in a package imported into the component.
3-6
Switch with Hysteresis
In general, enumerations are very useful in mode charts, because they let you specify a discrete set of
acceptable parameter values. For more information, see “Enumerations” on page 3-14.
To verify the correct component behavior, deploy it in a Simscape Component block. Create a simple
test model, as shown, with all the blocks using the default parameter values.
3-7
3 Advanced Techniques
3-8
Switch with Hysteresis
The Initial Mode parameter value is Switch is open. This enumerated value evaluates to 0, which
makes the predicate in the initial section true. Therefore, at the start of simulation the switch is
open and no current flows through the resistor R1. When the control signal value reaches 0.5 (the
Upper threshold parameter value), the switch closes and the current through the branch, based on
the other parameter values, is 1A. When the control signal falls below 0 (the Lower threshold
parameter value), the switch opens.
Now change the Initial Mode parameter value to Switch is closed and simulate the model. The
enumerated value evaluates to 1, the predicate condition in the initial section is no longer true,
and therefore the first mode listed in the modes section is active. At the start of simulation, the
switch is closed, and it stays closed until the control signal falls below 0.
3-9
3 Advanced Techniques
See Also
modecharts | modes | transitions | initial
More About
• “Mode Chart Modeling” on page 3-2
• “Enumerations” on page 3-14
3-10
State Reset Modeling
To implement a state reset, use instantaneous modes and compound transitions in a mode chart. An
instantaneous mode is a mode that is active only for one event iteration. You specify that a mode is
instantaneous by using a compound transition:
A -> B -> C : t
The middle mode, B, is instantaneous. When predicate t becomes true, the system transitions from
mode A to mode B, performs one event iteration, and then immediately transitions to mode C.
You declare instantaneous modes the same way as regular modes, by using the mode section of a
mode chart. To specify that a mode is instantaneous, list it as the middle mode in a compound
transition. Only one instantaneous mode is allowed per transition, therefore, a compound transition
cannot contain more than three modes.
In the majority of state reset use cases, the reset value is a function of the previous value of the
variable. For example, when modeling a bouncing ball, the new velocity depends on the velocity
before impact. The entry section, which you declare within a mode section in a mode chart, lets you
specify the actions to be performed upon entering the mode. These actions are event variable updates
based on the value of a continuous expression immediately before entering the mode. When modeling
a state reset, you can use entry actions to update the value of an event variable based on the value of
the respective continuous variable immediately before entering the mode.
When you connect multiple ideal components that use state resets, the solver automatically detects
and propagates impulses in continuous states during variable reinitialization. Impulse propagation
can only trigger events whose predicates are linear expressions of continuous states. Also, impulse
detection can add computational cost during transient initialization. Two options in the Solver
Configuration block, Compute impulses and Impulse iterations, let you control the computational
cost of impulse detection during transient initialization. If you use fixed-cost simulation for a model
that contains components with state resets, select the Compute impulses check box to get the
correct impulse propagation results.
The Translational Hard Stop block in the Simscape Foundation library models a hard stop as a spring
and damper that come into contact with the slider at the bounds. In contrast, this example
implements an ideal translational hard stop, where the slider velocity resets instantaneously upon
hitting the upper or lower bound.
3-11
3 Advanced Techniques
component ideal_hard_stop
nodes
R = foundation.mechanical.translational.translational % R:left
C = foundation.mechanical.translational.translational % C:right
end
parameters
upper_bnd = { 0.1, 'm'} % Upper bound
lower_bnd = {-0.1, 'm'} % Lower bound
e = 0.8 % Coefficient of restitution
end
variables
v = {0, 'm/s'} % Velocity
f = {0, 'N'} % Force
x = {value = {0, 'm'}, priority = priority.high} % Position
end
branches
f : R.f -> C.f
end
equations
v == R.v - C.v
x.der == v
modecharts(ExternalAccess = observe)
m = modechart
modes
mode FREE
equations
f == 0
end
end
mode IMPACT
entry
v_old = v
end
equations
v == -e*v_old
end
end
end
transitions
FREE -> IMPACT -> FREE : x <= lower_bnd && v < 0
FREE -> IMPACT -> FREE : x >= upper_bnd && v > 0
end
3-12
State Reset Modeling
end
end
end
Each mode has an equations section that lists the equations applicable to that mode. The
equations section outside the mode chart lists the asserts and equations that apply to both modes.
The transitions section defines two compound transitions, one for the slider hitting the lower
bound and one for the upper bound. In each transition, when the predicate becomes true, the
component switches from the FREE mode to IMPACT, and then back to FREE. IMPACT is an
instantaneous mode.
When the component enters the IMPACT mode, the event variable v_old gets updated with the value
of velocity before impact. This update action is defined in the entry section for that mode. Then, in
the equations section for this mode, the velocity, v, is reset to a value that is a function of this
previous velocity value and the coefficient of restitution, e.
The component implements separate transitions for the upper and lower bounds to improve code
readability. The predicate for each of these compound transitions includes both the slider position and
the velocity sign, to avoid entering a self-loop. Compound transitions follow the same rules as regular
transitions. If a predicate is true, the system immediately enters the transition. Therefore, if you
defined a compound transition based only on the slider position:
transitions
FREE -> IMPACT -> FREE : x <= lower_bnd || x >= upper_bnd
end
the predicate could still be true after completing the transition, the system would enter an infinite
loop and eventually generate an error. To avoid this situation, it is a good practice to try to model
compound transitions in such a way that the instantaneous mode invalidates the predicate:
transitions
FREE -> IMPACT -> FREE : x <= lower_bnd && v < 0
FREE -> IMPACT -> FREE : x >= upper_bnd && v > 0
end
In this case, while in instantaneous mode, the velocity flips sign and the predicate is no longer valid.
For a more detailed example, see “Mass on Cart Using an Ideal Hard Stop”, which uses a custom
Ideal Hard Stop block with additional options that cover a wider variety of use cases. That block has a
more complex mode chart, but the modeling principles and the block behavior are similar.
See Also
modecharts | modes | transitions | initial | entry
More About
• “Mode Chart Modeling” on page 3-2
3-13
3 Advanced Techniques
Enumerations
In this section...
“Enumerations in Simscape Language” on page 3-14
“Specifying Display Strings for Enumeration Members” on page 3-15
“Evaluating Enumeration Members” on page 3-16
“Using Enumeration in Event Variables and when Clauses” on page 3-17
“Using Enumeration in Predicates” on page 3-17
“Using Enumeration in Function Arguments” on page 3-18
“Rules and Restrictions” on page 3-19
• Component parameters
• Event variables and when clauses
• Equation predicates
• Conditional declaration predicates
• Function arguments (such as an interpolation method in tablelookup)
• Mode charts
You define enumerations using a MATLAB enumeration class. For more information, see
“Enumerations”.
The enumeration class must derive from the int32 type, for example:
Save the enumeration class definition in a .m file with the same name as the class. For more
information, see “Rules and Restrictions” on page 3-19.
parameters
fl_c = offon.off; % Fluid compressibility
end
In the resulting block dialog, the Fluid compressibility parameter will have a drop-down list of
values, off and on, with off as the default.
3-14
Enumerations
You can then use this enumeration in a component parameter, for example:
parameters
r_damp = damping.direct; % Rotor damping parameterization
end
In the resulting block dialog, the Rotor damping parameterization parameter has a drop-down list
of values:
• By damping value
• By no-load current
3-15
3 Advanced Techniques
For a detailed example of using enumeration with display strings in a component parameter, see “Use
Advanced Techniques to Customize Block Display” on page 4-43.
3-16
Enumerations
Then, the initial section of the mode chart uses the Initial Mode parameter value in the predicate
expression:
initial
OPEN : InitMode <= 0;
end
When the Initial Mode parameter value is Switch is open, the corresponding enumeration
member, open (0), evaluates to 0, and the predicate is true. Therefore, at the start of simulation the
switch is open.
Conversely, when the parameter value is Switch is closed, the corresponding enumeration
member, closed (1), evaluates to 1, and the predicate is false. For more information, see “Switch
with Hysteresis” on page 3-5.
Event variables are piecewise constant, that is, they change values only at event instants (by using
the when clause), and keep their values constant between events.
For example:
variables (Event = true)
x = myEnum.a;
end
events
when edge(time > {1.0, 's'})
x = myEnum.b;
end
end
3-17
3 Advanced Techniques
equations
% first set of equations, resistive properties only
end
else
variables
% additional variable declarations, needed to account for fluid compressibility
end
equations
% second set of equations, including fluid compressibility
end
end
end
In this example, the block parameter Fluid compressibility is using the offon enumeration:
In the resulting block dialog, the Fluid compressibility parameter has a drop-down list of values,
off and on, with off as the default. If the parameter is set to off, the first set of equations gets
activated and the block models only the resistive properties of the pipe. If the block user changes the
value of the parameter, then the else branch gets activated, and the compiled model includes the
additional variables and equations that account for fluid compressibility. For more information on
defining block variants, see “Defining Component Variants” on page 2-77.
Likewise, you can use enumerated parameters and event variables in equation predicates:
parameters
p = myEnum.a;
end
variables
x = 0;
y = 0;
end
equations
if p == myEnum.a
y == x * 100;
elseif p == myEnum.b
y == x * 0.01;
else % (p == myEnum.c)
y == x;
end
end
3-18
Enumerations
smooth (2)
end
methods(Static)
function map = displayText()
map = containers.Map;
map('linear') = 'Linear';
map('smooth') = 'Smooth';
end
end
end
You can use these enumerations to declare component parameters, and then use these parameters as
function arguments:
parameters
interp = simscape.enum.interpolation.linear; % Interpolation method
extrap = simscape.enum.extrapolation.linear; % Extrapolation method
end
equations
o == tablelookup(xd, yd, x, interpolation = interp_method, extrapolation = extrap_method);
end
Instead of providing fully qualified names, you can use the import statement to reduce the amount of
typing:
import simscape.enum.*
...
parameters
interp = interpolation.linear; % Interpolation method
extrap = extrapolation.linear; % Extrapolation method
end
equations
o == tablelookup(xd, yd, x, interpolation = interp, extrapolation = extrap);
end
The file containing the enumeration class definition must reside on the MATLAB path or in a package
directory. For more information about package directories, see “Organizing Your Simscape Files” on
page 4-21.
3-19
3 Advanced Techniques
Parameters that have enumerated values are marked as Compile-time only in the block dialogs.
Similar to MATLAB enumerations, you can define more than one identifier for the same integer value,
for example:
The first identifier in the enumeration block with a given integer value is the actual identifier, and
subsequent identifiers are aliases.
Note Although multiple identifiers with the same integer value are allowed, it is recommended that
you use unique integer values within a Simscape language enumeration set, for better clarity.
See Also
Related Examples
• “Switch with Hysteresis” on page 3-5
3-20
Declaration Functions
Declaration Functions
In this section...
“Multiple Return Values” on page 3-21
“Restriction on Values with Units” on page 3-22
“Run-Time Compatibility” on page 3-22
You can use declaration functions to compute derived parameter values or initialize variables, instead
of doing this inside the setup function.
Note Starting in R2019a, using setup is not recommended. Other constructs available in Simscape
language let you achieve the same results without compromising run-time capabilities. For more
information, see “setup is not recommended” on page 5-40.
Declaration function is a MATLAB function used inside a member declaration section in a Simscape
file. A declaration function can be any MATLAB function (even if it is not supported in the Simscape
language equations section), including user-defined functions on the MATLAB path. For example:
component A
parameters
p1 = 1;
p2 = 0;
end
parameters(Access = private)
pDerived = gamma(p1) + p2;
end
variables(Access = private)
vDerived = {value = {my_fcn(p1,p2) + 1, 'm'}, priority = priority.high };
end
equations
...
end
end
Use the Access=private attribute for member declaration unless all the arguments of the
declaration function are constants.
Exercise caution when using persistent variables inside a declaration function, because this may lead
to inconsistent results for multiple simulation runs.
[id1] = my_fcn(); % rules of single assignment apply, nonrequested return values ignored
• You can use multiple value assignments on the left-hand side only for parameters and variables
with the Access=private attribute.
• When omitting return values using the placeholder attribute (~), at least one value must be
assigned. Empty declarations produce an error in Simscape language.
3-21
3 Advanced Techniques
For example, parameter p has the units of 'm'. To use it as an input for the myfcn function, use the
value function to get the unitless value of the parameter.
parameters
p = {1,'m'}
end
parameters(Access = private)
pd = my_fcn(value(p,'m')); % extract unitless value from p
end
In the previous example, pd is a unitless parameter. To declare it as a value with unit, use the
{value,'unit'} syntax, for example:
pd = {my_fcn(value(p,'m')),'m/s'};
For multiple input and return values with units, use this syntax:
[y_value,z_value] = my_fcn(value(a,'V'),value(b,'V'));
y = {y_value,'V'};
z = {z_value,'V'};
For more information, see “Declaring a Member as a Value with Unit” on page 2-5.
Run-Time Compatibility
Member declarations for parameters and variables can include calls to MATLAB functions that
generate code.
By default, the declaration function will be evaluated at run time if a run-time parameter appears in
its input parameters. Otherwise, it will be evaluated at compile time.
component A
parameters
p1 = 1;
p2 = 0;
end
parameters(Access = private)
pDerived = my_fcn(p1,p2);
end
equations
...
end
end
If p1 or p2 is designated as Run-time in the block dialog, then my_fcn is evaluated at run time, and
you can tune these parameter values without regenerating code.
If my_fcn does not support code generation, you can set the member
attributeMATLABEvaluation=compiletime, to prevent the block user from accidentally
designating any of the function input parameters as Run-time in the block dialog:
3-22
Declaration Functions
component A
parameters
p1 = 1;
p2 = 0;
end
parameters(Access = private,MATLABEvaluation = compiletime)
pDerived = my_fcn(p1,p2);
end
equations
...
end
end
If you set this attribute, the declaration function will be evaluated only at compile time, and the block
parameters p1 and p2 will be marked as Compile-time only.
• Use coder.allowpcode('plain')
• Turn on lint: %#codegen
3-23
3 Advanced Techniques
Simscape Functions
In this section...
“Main Simscape Functions” on page 3-24
“Using Main Simscape Functions” on page 3-25
“Recommended Ways of Code Reuse” on page 3-26
“Local Simscape Functions” on page 3-26
Simscape functions model a class of pure first-order mathematical functions with explicit input-output
relationship. These functions explicitly map the inputs of numerical values into outputs of numerical
values by using declarative expressions. When a component calls a Simscape function, numerical
input values are passed to the function, which then evaluates these declarative expressions to
compute the output values.
The Simscape function file must start with the keyword function, followed by the function header,
which includes the function name, inputs, and outputs. For example:
The body of the function must be enclosed inside the definitions section, for example:
Syntax Rules
3-24
Simscape Functions
o == SumSquared(5,2);
Packaging Rules
• Simscape function files can reside directly on MATLAB path or in package directories. For more
information, see “Organizing Your Simscape Files” on page 4-21.
• You can use source protection, as described in “Using Source Protection for Simscape Files” on
page 4-22.
• Importing a package imports all the Simscape functions in this package. For more information, see
“Importing Domain and Component Classes” on page 2-110.
• If a MATLAB function and a Simscape function have the same name, the MATLAB function has
higher precedence.
For example, exponential diode equations often use an expression that is a modification of exp(i), to
provide protection for large magnitudes of i. For details, see Diode and NPN Bipolar Transistor block
reference pages. The “Simscape Functions” example shows how you can write a Simscape function to
reuse this expression, instead of repeating it in every block:
3-25
3 Advanced Techniques
Then, the Diode block can call this function with y and z values of 80 and 79, respectively:
equations
o == SimscapeFunction.Use.Functions.userFunction(i,80,79);
end
and the NPN Bipolar Transistor block can call the same function with values of 40 and 39:
equations
o == SimscapeFunction.Use.Functions.userFunction(i,40,39);
end
• Use main Simscape functions to reuse expressions in equations and member declarations.
• Use declaration functions in member declarations to reuse expressions that are out of Simscape
expression capability. For more information, see “Declaration Functions” on page 3-21.
• Use subclassing to model the "is-a" relationship between the base component and the derived
component. The equations in the base component are reused in the derived component. For more
information, see “Subclassing and Inheritance” on page 2-107.
• Use composite components to model the "has-a" relationship between the container component
and the subcomponents. The equations in the member components are reused in the composite
component. For more information, see “About Composite Components” on page 2-60.
3-26
Simscape Functions
Include the local Simscape function in a component, domain, or function file, after the final end
keyword that concludes the description of the component, domain, or main function. For example,
this rotational spring component uses a local function to modify its torque equation:
component spring_with_local_function
nodes
r = foundation.mechanical.rotational.rotational;
c = foundation.mechanical.rotational.rotational;
end
parameters
k = { 10, 'N*m/rad' };
end
variables
theta = { 0, 'rad' };
t = { 0, 'N*m' }; % torque through
w = { 0, 'rad/s' }; % velocity across
end
branches
t : r.t -> c.t; % torque through from node r to node c
end
equations
assert(k>0) % spring rate must be greater than zero
w == r.w - c.w; % velocity across between node r and node c
t == localTorque(k,theta);
w == theta.der;
end
end
The syntax rules for local functions are the same as for main functions. See “Syntax Rules” on page 3-
24.
You can have multiple local functions declared in the same component, domain, or function file.
Local functions can contain calls to other local functions, in the same file, or to main functions in
other files. In case of a name conflict, local functions have higher call precedence than main
functions.
See Also
function
Related Examples
• “Simscape Functions”
More About
• “Declaration Functions” on page 3-21
3-27
3 Advanced Techniques
Component Arrays
In this section...
“How to Use Arrays of Components” on page 3-28
“Syntax Rules and Restrictions” on page 3-29
Component arrays provide an intuitive way to model composite components with an arbitrary number
of homogeneous members, such as segmented pipelines, battery packs, or transmission lines.
The array size can be declared as an adjustable parameter of the composite component, so that the
block users can modify this value.
parameters
array_size = 10; % Number of member components
end
Declare the parameter specifying the array size as a unitless integer because a for-loop iterator
must be a unitless integer.
Similar to regular composite components, if you want certain parameters of the underlying member
component to be adjustable through the composite component interface, include them in the member
declaration. This example establishes the relationship between parameter parX of the member
component compX and the top-level parameter top_level_parX of the composite component:
parameters
array_size = 10; % Number of member components
top_level_parX = { 1, 'm' }; % Modifiable parameter of the member components
end
for i=1:array_size
components (ExternalAccess=none)
member_comp(i) = compX(parX = top_level_parX);
end
end
Use for-loops to specify connections between the member components. The iterator range for these
for-loops depends on the array size and the type of connection. For example, when you connect N
members in parallel, the iterator range is equal to the array size:
for i=1:N
connections
connect(compX(i).A, A);
connect(compX(i).B, B);
end
end
However, if you connect N members in series, the iterator range is from 1 to (N-1), because you are
connecting port B of each member except the last one to port A of the next member:
for i=1:(N-1)
connections
3-28
Component Arrays
connect(compX(i).B, compX(i+1).A);
end
end
In this case, do not forget to connect the ends of the chain to the external ports of the composite
component:
connections
connect(compX(1).A, A);
connect(compX(N).B, B);
end
You can also use compX(end) to indicate the last member of a component array. For example, this
syntax is equivalent to the previous one, for connecting the ends of the chain to the external ports of
the composite component:
connections
connect(compX(1).A, A);
connect(compX(end).B, B);
end
• Arrays apply only to the components and nodes member classes. For information on arrays of
nodes, see “Arrays of Nodes” on page 3-43.
• Component arrays must be homogeneous, that is, their members must all belong to the same
class. However, members can have different parameter values.
• For an example of a component array with identical members, see “Segmented Pipeline Using
Component Array” on page 3-31.
• For an example of how you can specify different parameter values for certain members of a
component array, see “Case Study — Battery Pack with Fault Using Arrays” on page 3-33.
• The array size can be a parameter, or a parametric expression. Parameters that control the array
size can have their ExternalAccess attribute set to modify, which enables the block users to
change the size of the array.
• Array members must have the ExternalAccess attribute set to none or observe.
• Empty arrays are not supported.
You can use for-loops to declare component arrays and to connect members of the array to each
other. for-loops have the same syntax as for in MATLAB. The following rules and restrictions apply
to for-loops in Simscape language:
for i=1:N
for j=1:i
3-29
3 Advanced Techniques
...
end
end
• Component declaration using a for-loop must contain the for-loop iterator on the left side as a
bare identifier, for example, pipe(i). You cannot use expressions or numbers in place of an
iterator. Components declared inside a nested for-loop must list all the iterators, for example:
for i=1:N
for j=1:M
components (ExternalAccess=none)
resistor(i,j) = foundation.electrical.elements.resistor(R = R);
end
end
end
• You cannot include conditional sections (that you use to define component variants) inside for-
loops. However, you can include for-loops inside the conditional sections.
See Also
More About
• “Segmented Pipeline Using Component Array” on page 3-31
• “Case Study — Battery Pack with Fault Using Arrays” on page 3-33
3-30
Segmented Pipeline Using Component Array
In this example, for the sake of simplicity, the SegmentedPipeline component has only two
modifiable parameters: N (Number of segments) and segm_length (Length of each segment).
However, you can make other parameters of the underlying Pipe (IL) block accessible from the top-
level composite component block dialog, as described in “Parameterizing Composite Components” on
page 2-62. Parameter N, which defines the array size and is going to be used as the upper limit for the
for-loop iterator, is declared as a unitless integer.
In this example, all the pipe segments have the same length. For an example of array component
members having different parameter values, see “Case Study — Battery Pack with Fault Using
Arrays” on page 3-33.
3-31
3 Advanced Techniques
Use another for-loop to connect all segments in series, by connecting node B of each pipe segment
(except the last one) to node A of the next segment:
for i=1:(N-1)
connections
connect(pipe(i).B, pipe(i+1).A);
end
end
Finally, connect the internal chain of segments to the two ends of pipeline, by connecting node A of
the composite component to node A of the first segment and connecting node B of the composite
component to node B of the last segment:
connections
connect(A, pipe(1).A);
connect(B, pipe(N).B);
end
end
The resulting block has two isothermal liquid ports, A and B, and two modifiable parameters:
Number of segments and Length of each segment.
See Also
More About
• “Component Arrays” on page 3-28
• “Case Study — Battery Pack with Fault Using Arrays” on page 3-33
3-32
Case Study — Battery Pack with Fault Using Arrays
The case study is based on the “Lithium-Ion Battery Pack with Fault Using Arrays” example. To open
the example model, type ssc_lithium_battery_arrays in the MATLAB Command Window.
The Battery Pack block is a composite component modeling an array of battery cells. The source files
for this example are in the following package folder:
matlabroot/toolbox/physmod/simscape/simscapedemos/+BatteryPack
where matlabroot is the MATLAB root directory on your machine, as returned by entering
matlabroot
• battery_cell.ssc — Component file representing the individual battery cell. The source for
this component is generated using subsystem2ssc from the Lithium Cell 1RC subsystem in the
“Lithium Battery Cell - One RC-Branch Equivalent Circuit” example.
• battery_pack.ssc — Composite component that models the battery pack as an array of
battery_cell components.
component battery_pack
% Battery Pack
% This block models a scalable battery pack with faults using arrays.
parameters
Ncells = 20; % Number of series-connected cells
cell_mass = {1, 'kg'}; % Cell mass
cell_area = {0.1019, 'm^2'}; % Cell area
h_conv = {5, 'W/(m^2 * K)'}; % Heat transfer coefficient
cell_Cp_heat = {810.5328, 'J/(kg*K)'}; %Cell specific heat
Qe_init = {15.6845, 'hr*A'}; %Initial cell charge deficit
T_init = {293.15, 'K'}; % Initial cell temperature
SOC_LUT = [0; .1; .25; .5; .75; .9; 1]; %SOC table breakpoints (Mx1 array)
Temperature_LUT = {[278.15, 293.15, 313.15], 'K'}; %Temperature table breakpoints (1xN array)
Capacity_LUT = {[28.0081, 27.625, 27.6392], 'hr*A'}; %Capacity (1xN table)
Em_LUT = {[3.4966, 3.5057, 3.5148; 3.5519, 3.566, 3.5653; 3.6183, 3.6337, 3.6402; 3.7066, 3.7127, 3.7213; 3.9131, 3.9259, 3.9376; 4.
R0_LUT = {[.0117, .0085, .009; .011, .0085, .009; .0114, .0087, .0092; .0107, .0082, .0088; .0107, .0083, .0091; .0113, .0085, .0089
3-33
3 Advanced Techniques
R1_LUT = {[.0109, .0029, .0013; .0069, .0024, .0012; .0047, .0026, .0013; .0034, .0016, .001; .0033, .0023, .0014; .0033, .0018, .00
C1_LUT = {[1913.6, 12447, 30609; 4625.7, 18872, 32995; 23306, 40764, 47535; 10736, 18721, 26325; 18036, 33630, 48274; 12251, 18360,
% Fault cell
fault_cell_position = 10; %Fault cell position
fault_cell_Capacity_LUT = {[28.0081, 27.625, 27.6392]*0.95, 'hr*A'}; %Fault cell capacity (1xN table)
fault_cell_Em_LUT = {[3.4966, 3.5057, 3.5148; 3.5519, 3.566, 3.5653; 3.6183, 3.6337, 3.6402; 3.7066, 3.7127, 3.7213; 3.9131, 3.9259,
fault_cell_R0_LUT = {[.0117, .0085, .009; .011, .0085, .009; .0114, .0087, .0092; .0107, .0082, .0088; .0107, .0083, .0091; .0113, .
fault_cell_R1_LUT = {[.0109, .0029, .0013; .0069, .0024, .0012; .0047, .0026, .0013; .0034, .0016, .001; .0033, .0023, .0014; .0033,
fault_cell_C1_LUT = {[1913.6, 12447, 30609; 4625.7, 18872, 32995; 23306, 40764, 47535; 10736, 18721, 26325; 18036, 33630, 48274; 122
end
nodes
p = foundation.electrical.electrical; % +:top
n = foundation.electrical.electrical; % -:bottom
H = foundation.thermal.thermal; % H:bottom
end
variables(Access=protected)
T = {ones(1,Ncells),'K'};
SOC = ones(1,Ncells);
end
outputs
m = {ones(1,Ncells),'K'}; % m:top
end
for i =1:Ncells
components(ExternalAccess=none)
battery_cell(i) = BatteryPack.battery_cell(cell_mass=cell_mass,cell_Cp_heat=cell_Cp_heat,...
C1_LUT=(if i==fault_cell_position,fault_cell_C1_LUT;else C1_LUT; end),...
SOC_LUT=SOC_LUT,Temperature_LUT=Temperature_LUT,...
Capacity_LUT=(if i==fault_cell_position,fault_cell_Capacity_LUT;else Capacity_LUT; end),...
Em_LUT=(if i==fault_cell_position,fault_cell_Em_LUT;else Em_LUT; end),Qe_init=Qe_init,...
R0_LUT=(if i==fault_cell_position,fault_cell_R0_LUT;else R0_LUT; end),...
R1_LUT=(if i==fault_cell_position,fault_cell_R1_LUT;else R1_LUT; end),T_init.value=T_init);
convection(i) = foundation.thermal.elements.convection(area=cell_area,heat_tr_coeff=h_conv);
end
connections
connect(battery_cell(i).H,convection(i).B);
connect(H,convection(i).A);
end
end
connections
connect(battery_cell(1).p,p);
connect(battery_cell(Ncells).n,n);
end
equations
assert(mod(Ncells, 1) == 0 && Ncells > 0, 'Number of series-connected cells must be a positive integer');
assert(mod(fault_cell_position, 1) == 0 && fault_cell_position > 0 && fault_cell_position <= Ncells , 'Fault cell position must be a
T == [battery_cell.T_init];
SOC == [battery_cell.SOC];
m == T;
end
for i=1:Ncells-1
components(ExternalAccess=none)
conduction(i) = foundation.thermal.elements.conduction(area={1e-3,'m^2'},...
th_cond={200,'W/(m*K)'});
end
connections
connect(battery_cell(i+1).p,battery_cell(i).n);
connect(battery_cell(i).H,conduction(i).A);
connect(battery_cell(i+1).H,conduction(i).B);
end
end
end
This schematic represents the equivalent circuit for the composite component.
3-34
Case Study — Battery Pack with Fault Using Arrays
The composite component has two electrical nodes, p and n, and one thermal node, H:
nodes
p = foundation.electrical.electrical; % +:top
n = foundation.electrical.electrical; % -:bottom
H = foundation.thermal.thermal; % H:bottom
end
To account for the fault, top-level composite component parameters are divided in two groups:
generic parameters and those specific to the faulted cell. For example, cell mass is the same for all
cells. However, the capacitance of the faulted cell is different from all the other cells, therefore it
needs a separate fault_cell_Capacity_LUT parameter, instead of the generic Capacity_LUT.
parameters
Ncells = 20; % Number of series-connected cells
cell_mass = {1, 'kg'}; % Cell mass
3-35
3 Advanced Techniques
Both the number of cells, Ncells, and the position of the faulted cell, fault_cell_position, are
top-level parameters of the composite component, which means that they will be modifiable by the
block user.
For each member, associate its parameters with the top-level parameters of the composite
component. For the iterator value that corresponds to the faulted cell position, specify the faulted cell
parameters instead of the respective generic ones, as needed. For example, all cells have the same
cell mass:
cell_mass=cell_mass
However, the capacitance of the faulted cell is different from all the other cells, therefore, for the
iterator value that corresponds to the faulted cell position, assign the Capacity_LUT parameter of
the cell to the fault_cell_Capacity_LUT parameter of the composite component, and for all other
cells assign it to Capacity_LUT:
Capacity_LUT=(if i==fault_cell_position,fault_cell_Capacity_LUT;else Capacity_LUT; end)
An array of N cells requires N identical convections and N-1 identical conductions. These are thermal
components from the Foundation library.
for i =1:Ncells
components(ExternalAccess=none)
convection(i) = foundation.thermal.elements.convection(area=cell_area,heat_tr_coeff=h_conv);
end
end
for i=1:Ncells-1
components(ExternalAccess=none)
conduction(i) = foundation.thermal.elements.conduction(area={1e-3,'m^2'},...
th_cond={200,'W/(m*K)'});
end
end
3-36
Case Study — Battery Pack with Fault Using Arrays
3-37
3 Advanced Techniques
Then connect this internal chain to the two electrical nodes of the composite component:
connections
connect(battery_cell(1).p,p);
connect(battery_cell(Ncells).n,n);
end
3-38
Case Study — Battery Pack with Fault Using Arrays
Use another for-loop to connect thermal node H of each of the cells to node B of its respective
convection component, and also to connect nodes A of all the convection components to thermal node
H of the composite component:
for i=1:Ncells
connections
connect(battery_cell(i).H,convection(i).B);
connect(H,convection(i).A);
end
end
3-39
3 Advanced Techniques
Finally, incorporate the thermal conduction elements by connecting node A to node H of the previous
cell and node B to node H of the next cell:
for i=1:Ncells-1
connections
connect(battery_cell(i).H,conduction(i).A);
connect(battery_cell(i+1).H,conduction(i).B);
end
end
3-40
Case Study — Battery Pack with Fault Using Arrays
outputs
m = {ones(1,Ncells),'K'}; % m:top
end
To get the temperature data from the array of components, use the equations section. Declare the
variable T as protected, because public variables cannot reference parameters, and then use this
variable to extract the temperature values from the member cells.
variables(Access=protected)
T = {ones(1,Ncells),'K'};
end
equations
T == [battery_cell.T_init];
m == T;
end
3-41
3 Advanced Techniques
See Also
More About
• “Component Arrays” on page 3-28
• “Segmented Pipeline Using Component Array” on page 3-31
3-42
Arrays of Nodes
Arrays of Nodes
In this section...
“Declaring Arrays of Nodes” on page 3-43
“Textual Connections” on page 3-44
“Graphical Connections” on page 3-45
“Application Example” on page 3-46
Arrays of nodes provide an easy way to specify element-wise connections between two or more
parametric-sized arrays of components. These arrays must be of the same size but can belong to
different components. For example, in battery modeling, using arrays of nodes lets you model the
battery pack and the cooling plate as separate components. For more information, see “Application
Example” on page 3-46.
An array of nodes (AON) is represented as a single port on the block icon. If you have two or more
AON ports of the same domain type and identical size, you can establish element-wise connections
between these arrays by drawing connection lines between the ports. For more information, see
“Graphical Connections” on page 3-45.
You can declare the array size as an adjustable parameter of the composite component, so that the
block users can modify this value.
parameters
N = 20; % Number of nodes
end
Declare the parameter that specifies the array size as a unitless integer because a for-loop iterator
must be a unitless integer. For detailed information on using arrays and for-loops, see “Syntax Rules
and Restrictions” on page 3-29.
To customize the port name and location on the block icon, use the same syntax as for regular nodes,
for example:
for i=1:N
nodes
P(i) = foundation.electrical.electrical; % +
end
end
annotations
P : Side = top;
end
For more information, see “Customize the Names and Locations of the Block Ports” on page 4-34.
3-43
3 Advanced Techniques
Textual Connections
Use for-loops to specify textual element-wise connections between arrays of components and arrays
of nodes.
for i=1:N
connections
connect(compX(i).H,H(i));
end
end
You can also index into an AON to specify textual connections between elements of the array. For
example, this is how you establish a delta or polygon connection for multiphase electrical
components:
component Polygon
% Delta or polygon connection
parameters
N = 3; % Number of phases
end
for i=1:N
nodes
p(i)=foundation.electrical.electrical;
n(i)=foundation.electrical.electrical;
end
end
connections
connect(p(1:end-1),n(2:end));
connect(p(end),n(1));
end
...
end
Scalar expansion is not supported. Use a for-loop to connect a scalar node to an AON:
component ScalarExp
parameters
N = 3;
end
components
c = foundation.electrical.elements.resistor;
end
for i=1:N
nodes
p(i) = foundation.electrical.electrical;
n(i) = foundation.electrical.electrical;
end
connections
connect(c.p,p(i));
% connects positive port of resistor to AON p
end
end
...
end
Similarly, use a for-loop to connect an AON to an implicit reference node, *, because the implicit
reference node is scalar:
component ImpRef
parameters
N = 3;
end
3-44
Arrays of Nodes
for i=1:N
nodes
p(i) = foundation.electrical.electrical;
end
connections
connect(p(i),*);
end
end
...
end
Graphical Connections
An AON is represented as a single port on the block icon. If you have two or more AON ports of the
same domain type and identical size, you can establish element-wise connections between these
arrays by drawing connection lines between the ports.
If A1 and A2 are instances of component A, the graphical connection between the two AON ports, n
and p, is equivalent to:
connect(A1.n(1), A2.p(1))
connect(A1.n(2), A2.p(2))
...
connect(A1.n(end), A2.p(end))
• Like with scalar ports, error checking for the domain type is performed at edit time. You cannot
connect ports of different domain types.
• Error checking for the array size is performed at compile time. This means that, although you can
graphically connect AON ports of different sizes, this connection generates an error when you
compile the model or update the block diagram.
• Implicit scalar expansion is not supported. Connecting a scalar port to an AON port also generates
a compile-time error.
3-45
3 Advanced Techniques
You can connect AON ports using Simscape Bus or Connection Port blocks with rigid interface
specifications, as long as the domain types match. Similar to other graphical connections, error
checking for the array size is performed at compile time. If the array sizes do not match, the
connection generates a compile-time error.
Application Example
This conceptual example shows how you can model a battery pack and a cooling plate separately, and
then connect them using AON thermal ports.
The example is similar to the “Case Study — Battery Pack with Fault Using Arrays” on page 3-33
example, which shows how to model a lithium-ion battery pack as a single composite component that
includes component arrays of battery cells and cooling elements. The custom block based on this
composite component has a scalar thermal port H.
However, in applications such as electric vehicle modeling, it is common to have a separate battery
module, comprising an array of battery cells, and a separate cooling plate. For these applications, you
need to model heat transfer between an array of battery cells with thermal ports and an array of
convection elements by establishing element-wise connections between two arrays of thermal nodes,
located in two different custom blocks.
1 Create a battery pack component. This is a composite component that contains an array of
battery_cell components, with the array size determined by the Ncells parameter.
component batteryPack
% Battery Pack
parameters
Ncells = 20; % Number of battery cells
end
% declare array of battery cell components
for i =1:Ncells
components(ExternalAccess=none)
battery_cell(i) = battery_cell(cell_mass=cell_mass,... % other modifiable parameters
T_init.value=T_init);
end
end
% declare electrical nodes
nodes
p = foundation.electrical.electrical; % +
n = foundation.electrical.electrical; % -
end
% declare array of thermal nodes
for i=1:Ncells
nodes
H(i) = foundation.thermal.thermal; % H array
end
end
annotations
H : Side = right;
end
for i=1:Ncells
connections
connect(battery_cell(i).H, H(i));
end
end
parameters
cell_mass = {1, 'kg'}; % Cell mass
T_init = {293.15, 'K'}; % Initial cell temperature
end
% other parameters, nodes, connections, variables, equations
end
The custom block generated from this component has two scalar electrical ports, + and -, on the
left side and an AON thermal port, H array, on the right side of the block icon.
3-46
Arrays of Nodes
2 Create a cooling plate component. This is a composite component that contains an array of
Foundation library convection components, with the array size also determined by the Ncells
parameter.
component coolingPlate
% Cooling Plate
parameters
Ncells = 20; % Number of battery cells
end
% declare array of convection components
for i =1:Ncells
components(ExternalAccess=none)
convection(i) = foundation.thermal.elements.convection(area=cell_area,heat_tr_coeff=h_conv);
end
end
% declare array of thermal nodes
for i=1:Ncells
nodes
H(i) = foundation.thermal.thermal; % H array
end
end
for i=1:Ncells
connections
connect(convection(i).H, H(i));
end
end
parameters
cell_area = {0.1019, 'm^2'}; % Cell area
h_conv = {5, 'W/(m^2 * K)'}; % Heat transfer coefficient
end
% other parameters, nodes, connections, variables, equations
end
The custom block generated from this component has an AON thermal port H array on the left
side of the block icon.
3 Place the two custom blocks into a model and connect their AON ports.
This connection line represents element-wise connections between the two arrays of thermal
nodes. In other words, it connects each of the battery cells in the battery pack to the
corresponding convection element in the cooling plate.
4 To synchronize the AON sizes in the battery pack and the cooling plate, declare a workspace
variable:
3-47
3 Advanced Techniques
number_cells = 20;
Specify the Number of battery cells parameter value in both blocks as number_cells. This
way, you can modify the number of cells by assigning a new value to the number_cells variable,
with the change being reflected in the battery pack and the cooling plate simultaneously.
See Also
nodes
More About
• “Component Arrays” on page 3-28
• “Case Study — Battery Pack with Fault Using Arrays” on page 3-33
3-48
4
• “Selecting Component File Directly from Block” on page 4-3 — Use the Simscape Component
block, which you can find in the Utilities library, and point it to a Simscape component file. The
block instantly acquires the properties based on the source component file: name, description,
parameters, variables, appropriate ports and the custom icon image (if available). If you modify
the underlying source file, the block reflects these changes. If you point the block to a different
component file, the block properties change accordingly, to reflect the new source.
Use this method to quickly deploy a single component file, to try out different variants of a
component in your model, or to iterate on a component definition and get instant feedback.
• “Building Custom Block Libraries” on page 4-21 — Generate a custom block library from a
package of Simscape component files. The package hierarchy determines the resulting library
structure. You can customize the library name and appearance and provide annotation.
See Also
Related Examples
• “Deploy a Component File in Block Diagram” on page 4-5
• “Switch Between Different Source Components” on page 4-8
• “Prototype a Component and Get Instant Feedback” on page 4-15
• “Create a Custom Block Library” on page 4-27
• “Customize Block Display” on page 4-41
More About
• “Customizing the Block Name and Appearance” on page 4-29
• “Customizing the Library Name and Appearance” on page 4-25
4-2
Selecting Component File Directly from Block
Suggested Workflows
The Simscape Component block lets you select a Simscape component file, and then instantly
acquires the properties based on that source component file: name, description, parameters,
variables, the block icon and appropriate ports. For more information on how the component file
elements translate into the properties of the block, see “Customizing the Block Name and
Appearance” on page 4-29.
• Quickly deploy a single Simscape component file as a block in your model, without the extra steps
of packaging the file and building a custom library. For example, you wrote a component prototype
yourself, got it from a colleague, or found it on MATLAB Central. Save the file in your current
working directory, or anywhere on the MATLAB path, and use it as a source file for a Simscape
Component block in your model. For more information on valid locations of a source component
file, see “Component File Locations” on page 4-3. For an example of this workflow, see “Deploy
a Component File in Block Diagram” on page 4-5.
• Try out different component implementations, to decide which implementation is most appropriate
for your model. You can also use this workflow to test the differences between the old and new
implementations of the same component. Instead of adding, deleting, and reconnecting different
blocks in your model, you can use a single Simscape Component block and switch between the
source component files. When you point a Simscape Component block to a different component
file, the block properties change accordingly, to reflect the new source. For an example of this
workflow, see “Switch Between Different Source Components” on page 4-8.
• Quickly try out different ideas for a physical component and get instant feedback on the resulting
block implementation. This workflow lets you interactively modify the component source and
immediately see the changes by refreshing the resulting block. For an example of this workflow,
see “Prototype a Component and Get Instant Feedback” on page 4-15.
If you browse to a component file that is not on the path, then, when you try to select it, a File Not On
Path dialog opens. Click Add to add the appropriate directory to the MATLAB path.
The Add button is similar to the addpath command, that is, it adds the folder to the path only for the
duration of the current MATLAB session. If you do not save the path and then open the model in a
subsequent session, the Simscape Component block becomes unresolved.
If the source component is located in the current working directory, then there is no requirement for
it to be on the path. However, if you later try to open the model from another directory, the Simscape
Component block also becomes unresolved.
4-3
4 Simscape File Deployment
It is good practice to keep the source component files that you want to reuse in a directory included
in your permanent search path. For more information, see “What Is the MATLAB Search Path?”.
See Also
Related Examples
• “Deploy a Component File in Block Diagram” on page 4-5
• “Switch Between Different Source Components” on page 4-8
• “Prototype a Component and Get Instant Feedback” on page 4-15
More About
• “Customizing the Block Name and Appearance” on page 4-29
4-4
Deploy a Component File in Block Diagram
Suppose you have the following Simscape file, named my_resistor, in your working directory:
component my_resistor
% Linear Resistor
% The voltage-current (V-I) relationship for a linear resistor is V=I*R,
% where R is the constant resistance in ohms.
%
% The positive and negative terminals of the resistor are denoted by the
% + and - signs respectively.
nodes
p = foundation.electrical.electrical; % +:left
n = foundation.electrical.electrical; % -:right
end
variables
i = { 0, 'A' }; % Current
v = { 0, 'V' }; % Voltage
end
parameters
R = { 1, 'Ohm' }; % Resistance
end
branches
i : p.i -> n.i;
end
equations
assert(R>0)
v == p.v - n.v;
v == i*R;
end
end
Tip This component implements a linear resistor. It is described in more detail in “Model Linear
Resistor in Simscape Language” on page 1-3. You can copy the source from this page and save it as
my_resistor.ssc in your working directory.
3 Double-click the block to open the source file selector dialog box.
4-5
4 Simscape File Deployment
4
Click to open the browser. The browser opens in the current working directory and lists only
the files with the .ssc or .sscp extension. Select the my_resistor.ssc file and click Open.
The name of the source file appears in the text field of the source file selector dialog box, and the
block name, description, and the link to source code appear in the Description pane.
The source component selection is applied immediately, regardless of whether you have the Auto
Apply check box selected or not. The block icon and dialog box get updated, based on the
selected source component.
4-6
Deploy a Component File in Block Diagram
Tip Instead of browsing, you can type my_resistor directly into the text field. In this case,
however, the Description pane does not automatically get updated. If you want to view the block
name, description, or source code, click . To view the block parameters, click the Settings
tab.
See Also
Related Examples
• “Model Linear Resistor in Simscape Language” on page 1-3
• “Customize Block Display” on page 4-41
• “Switch Between Different Source Components” on page 4-8
• “Prototype a Component and Get Instant Feedback” on page 4-15
More About
• “Selecting Component File Directly from Block” on page 4-3
• “Customizing the Block Name and Appearance” on page 4-29
4-7
4 Simscape File Deployment
The component files used in this example are capacitor models with different levels of fidelity, to
allow exploration of the effect of losses and nonlinearity. The source files are part of your product
installation, located in the following package directory:
matlabroot/toolbox/physmod/simscape/simscapedemos/+Capacitors
where matlabroot is the MATLAB root directory on your machine, as returned by entering
matlabroot
in the MATLAB Command Window. For more information about these capacitor models, see “Case
Study — Basic Custom Block Library” on page 4-50.
1 To create a new model with optimal settings for physical modeling, in the MATLAB Command
Window, type:
ssc_new
2 Open the Simscape > Utilities library and add the Simscape Component block to your model. At
first, the block does not point to any component file, therefore it does not have any ports and the
block icon says Unspecified.
3 Double-click the block to open the source file selector dialog box.
4
Click and navigate to the directory containing the capacitor component files.
4-8
Switch Between Different Source Components
5 Select the IdealCapacitor.ssc file and click Open. The name of the source file appears in the
text field of the source file selector dialog box, and the block name, description, and the link to
source code appear in the Description pane.
Note Because the component file resides in a package, the file name in the selector dialog box
field is the full name, starting from the package root.
6 Close the block dialog box. The block icon gets updated, based on the selected source
component.
4-9
4 Simscape File Deployment
Note The +Capacitors package directory contains image files, with the names corresponding
to the Simscape component files, that define customized block icons. Therefore, when you point
the Simscape Component block to the IdealCapacitor.ssc source file, it uses the
IdealCapacitor.jpg in the same directory as the block icon. For details, see “Customize the
Block Icon” on page 4-38.
7 Build the test model and connect the blocks as shown in the following diagram.
4-10
Switch Between Different Source Components
The Simscape Component block points to an ideal capacitor component. Simulation results show
that, when the switch is flipped at t=5 seconds, the capacitor delivers 2.5 A to the load.
9 To switch to another capacitor model, open the Simscape Component block dialog box and click
Description. It displays the currently selected component.
10
Click . The browser opens in the +Capacitors directory, because it contains the currently
selected component.
4-11
4 Simscape File Deployment
11 Select the IdealUltraCapacitor.ssc file and click Open. The name of the source file appears
in the text field of the source file selector dialog box, and the block name, description, and the
link to source code appear in the Description pane.
12 Close the block dialog box. The block icon in the model diagram updates to reflect the new
source component.
4-12
Switch Between Different Source Components
Simulation results show that, when the switch is flipped at t=5 seconds, the current delivered to
the load is less than 2.5 A.
14 To make the effect more pronounced, open the block dialog box and increase the Rate of
change of C with voltage V parameter value to 0.8 F/V.
4-13
4 Simscape File Deployment
See Also
Related Examples
• “Deploy a Component File in Block Diagram” on page 4-5
• “Prototype a Component and Get Instant Feedback” on page 4-15
More About
• “Selecting Component File Directly from Block” on page 4-3
• “Customizing the Block Name and Appearance” on page 4-29
4-14
Prototype a Component and Get Instant Feedback
To have the block reflect the changes to the underlying source, right-click the block icon and, from
the context menu, select Simscape > Refresh source code. If you make a mistake (for example,
omit the end keyword) when editing the component source, then when you refresh the block, the
compiler issues a diagnostic error message, pointing to the appropriate line in the code.
1 Open the Simscape > Foundation Library > Electrical > Electrical Elements > Variable Resistor
block dialog box. On the Description tab, click the Source code link. The underlying source
code opens in the Editor window.
component variable_resistor
% Variable Resistor :1.5
% Models a linear variable resistor. The relationship between voltage V
% and current I is V=I*R where R is the numerical value presented at the
% physical signal port R. The Minimum resistance parameter prevents
% negative resistance values.
%
% Connections + and - are conserving electrical ports corresponding to
% the positive and negative terminals of the resistor respectively. The
% current is positive if it flows from positive to negative, and the
% voltage across the resistor is given by V(+)-V(-).
inputs
R = { 0.0, 'Ohm' }; % R:left
end
nodes
p = foundation.electrical.electrical; % +:left
n = foundation.electrical.electrical; % -:right
end
parameters
Rmin = { 0, 'Ohm' }; % Minimum resistance R>=0
end
variables
i = { 0, 'A' }; % Current
v = { 0, 'V' }; % Voltage
end
branches
i : p.i -> n.i;
end
intermediates
power_dissipated = v*i;
end
equations
assert(Rmin>=0)
v == p.v - n.v;
if R > Rmin
v == i*R;
else
v == i*Rmin;
end
end
end
4-15
4 Simscape File Deployment
component my_var_res
3 Save the source code as a file called my_var_res.ssc in your current working directory.
4 To create a new model with optimal settings for physical modeling, in the MATLAB Command
Window, type:
ssc_new
5 Open the Simscape > Utilities library and add the Simscape Component block to your model. At
first, the block does not point to any component file, therefore it does not have any ports and the
block icon says Unspecified.
6 Double-click the block to open the source file selector dialog box. Select the my_var_res.ssc
file.
7 Close the block dialog box. The block icon gets updated, reflecting the selected source
component. It now has two conserving electrical ports, + and –, and a physical signal input port
PS.
8 Double-click the block to open its dialog box. At this point, it has the same block name,
description, parameters, and variables, as the Variable Resistor block in the Foundation library.
4-16
Prototype a Component and Get Instant Feedback
9 On the Description tab, click the Source code link to start editing the source code. Change the
block name and description:
component my_var_res
% Variable Resistor with Energy Sensor
% Variable linear resistor that outputs total electrical energy.
10 To have the block reflect the changes to the underlying source, on the Description tab, click
11 Declare the output e and add the equation calculating total electrical energy. The component
source now looks like this:
4-17
4 Simscape File Deployment
component my_var_res
% Variable Resistor with Energy Sensor
% Variable linear resistor that outputs total electrical energy.
inputs
R = { 0.0, 'Ohm' }; % PS:left
end
outputs
e = { 0, 'J' };
end
nodes
p = foundation.electrical.electrical; % +:left
n = foundation.electrical.electrical; % -:right
end
parameters
Rmin = { 0, 'Ohm' }; % Minimum resistance R>=0
end
variables
i = { 0, 'A' }; % Current
v = { 0, 'V' }; % Voltage
end
branches
i : p.i -> n.i;
end
equations
assert(Rmin>=0)
v == p.v - n.v;
if R > Rmin
v == i*R;
else
v == i*Rmin;
end
e == integ(v*i);
end
end
12
Refresh the block again. Instead of using the button on the Description tab, you can right-
click the block icon and, from the context menu, select Simscape > Refresh source code.The
block icon now has an additional physical signal output port e.
13 Connect the block to a simple test rig to verify the correct performance.
4-18
Prototype a Component and Get Instant Feedback
Note There is a limitation that the name of the model cannot be the same as the name of the
source file for the Simscape Component block. Therefore, if you save the test rig model, make
sure to give it a different name, such as my_var_res_test.
4-19
4 Simscape File Deployment
See Also
Related Examples
• “Model Linear Resistor in Simscape Language” on page 1-3
• “Customize Block Display” on page 4-41
• “Deploy a Component File in Block Diagram” on page 4-5
• “Switch Between Different Source Components” on page 4-8
More About
• “Selecting Component File Directly from Block” on page 4-3
• “Customizing the Block Name and Appearance” on page 4-29
4-20
Building Custom Block Libraries
In this section...
“Workflow Overview” on page 4-21
“Organizing Your Simscape Files” on page 4-21
“Using Source Protection for Simscape Files” on page 4-22
“Converting Your Simscape Files” on page 4-22
Workflow Overview
To generate a custom block library from Simscape component files, follow these steps:
1 Organize your Simscape files on page 4-21. Simscape files must be saved in package
directories. The package hierarchy determines the resulting library structure.
2 Optionally, provide source protection on page 4-22. If you want to share your models with
customers without disclosing the component or domain source, you can generate Simscape
protected files and share those.
3 Build the custom block library on page 4-22. You can use either the regular Simscape source
files or Simscape protected files to do this. Each top-level package generates a separate custom
Simscape block library.
Once you generate the custom Simscape library, you can open it and drag the customized blocks from
it into your models.
Each package where you store your Simscape files generates a separate custom block library.
Package directories may be organized into subdirectories, with names also beginning with a +
character. After you build a custom block library, each such subdirectory will appear as a sublibrary
under the top-level custom library.
For example, you may have a top-level package directory, named +SimscapeCustomBlocks, and it
has three subdirectories, +Electrical, +Hydraulic, and +Mechanical, each containing Simscape
files. By default, the custom block library generated from this package will be called
SimscapeCustomBlocks_lib (you can specify a different name). The library will have three
sublibraries with names corresponding to the package subdirectories (Electrical, Hydraulic, and
Mechanical). For information on building custom block libraries, see “Converting Your Simscape
Files” on page 4-22.
4-21
4 Simscape File Deployment
• ssc_protect — Protects individual files and directories. Once you encrypt the files, you can
share them without disclosing the component or domain source. Use them, just as you would the
Simscape source files, to build custom block libraries with the ssc_build command.
• ssc_mirror — Creates a protected copy of a whole package in a specified directory. Setting a
flag lets you also build a custom block library from the protected files and place it in the mirror
directory, thus eliminating the need to run the ssc_build command. Use the ssc_mirror
command to quickly prepare a whole package for sharing with your customers, without disclosing
the component or domain source.
Unlike Simscape source files, which have the extension .ssc, Simscape protected files have the
extension .sscp and are not humanly-readable. You can use them, just as the Simscape source files,
to build custom block libraries. Protected files have to be organized in package directories, in the
same way as the Simscape source files. For information on organizing your files, see “Organizing Your
Simscape Files” on page 4-21. For information on building custom block libraries, see “Converting
Your Simscape Files” on page 4-22.
For example, you may have a top-level package directory, where you store your Simscape files, named
+SimscapeCustomBlocks. You can generate a custom block library either from the package parent
directory, or from a directory inside the package. From the package parent directory, at the MATLAB
command prompt, type:
ssc_build SimscapeCustomBlocks;
Note The package directory name begins with a leading + character, whereas the argument to
ssc_build must omit the + character.
This command generates a Simulink model file called SimscapeCustomBlocks_lib in the parent
directory of the top-level package (that is, in the same directory that contains your
+SimscapeCustomBlocks package). Because this directory is on the MATLAB path, you can open
the library by typing its name at the MATLAB command prompt. In our example, type:
SimscapeCustomBlocks_lib
The model file generated by running the ssc_build command is the custom Simscape library
containing all the sublibraries and blocks generated from the Simscape files located in the top-level
package. Once you open the custom Simscape library, you can drag the customized blocks from it into
your models.
4-22
Building Custom Block Libraries
When building a custom library from a package, ssc_build lets you specify a different name and
location for the library file than the default ones. For more information, see ssc_build.
Creating Sublibraries
Package directories may be organized into subdirectories, with names also beginning with a +
character. After you run the ssc_build command, each such subdirectory will appear as a
sublibrary under the top-level custom library. You can customize the name and appearance of
sublibraries by using library configuration files.
Note When you add or modify component files in package subdirectories, you still run the
ssc_build command on the top-level package directory. This updates all the sublibraries.
You may have more than one top-level package directory, that is, more than one package directory
located in a directory on the MATLAB path. Each top-level package directory generates a separate
top-level custom library.
See Also
ssc_build | ssc_mirror | ssc_protect
Related Examples
• “Create a Custom Block Library” on page 4-27
More About
• “Customizing the Library Name and Appearance” on page 4-25
• “When to Rebuild a Custom Library” on page 4-24
4-23
4 Simscape File Deployment
4-24
Customizing the Library Name and Appearance
A library configuration file must be located in the package directory and named lib.m.
Library configuration files are not required. You can choose to provide lib.m for some subpackages,
all subpackages, or for none of the subpackages. If a subpackage does not contain a lib.m file, the
sublibrary is built using the default values. The top-level package can also contain a lib.m file.
Options such as library name, and other options that do not make sense for a top-level library, are
ignored during build. However, having a file with the same name and options in the top-level package
provides a uniform mechanism that lets you easily change the library hierarchy.
The following table describes the supported options. The only option that is required in a lib.m file is
Name; others are optional.
4-25
4 Simscape File Deployment
• jpg
• bmp
• png
If there are multiple image files, the formats take precedence in the order listed above. For example,
if a subpackage contains both lib.jpg and lib.bmp, lib.jpg is the image that will appear in the
parent library.
You can turn off customizing the library icon by setting showIcon to false in the library
customization file lib.m. In this case, the default library icon will be used. For more information, see
“Library Configuration Files” on page 4-25.
See Also
Related Examples
• “Create a Custom Block Library” on page 4-27
More About
• “Building Custom Block Libraries” on page 4-21
4-26
Create a Custom Block Library
- +MySimscapeLibrary
|-- +MechanicalElements
| |-- lib.m
| |-- lib.jpg
| |-- inertia.ssc
| |-- spring.ssc
|-- +ElectricalElements
| |-- ...
|-- +HydraulicElements
| |-- ...
This means that you have a top-level package called +MySimscapeLibrary, which contains three
subpackages, +MechanicalElements, +ElectricalElements, and +HydraulicElements. The
+MechanicalElements package contains two component files, inertia.ssc and spring.ssc, a
library icon file lib.jpg, and the following library configuration file lib.m:
function lib ( libInfo )
libInfo.Name = 'Basic Mechanical Elements';
libInfo.Annotation = sprintf('This library contains basic mechanical elements');
libInfo.ShowName = true;
ssc_build MySimscapeLibrary;
Notice that the sublibrary generated from the +MechanicalElements package is presented in its
parent library with a customized icon and name (Basic Mechanical Elements).
4-27
4 Simscape File Deployment
4-28
Customizing the Block Name and Appearance
The following example shows a component file, named spring.ssc, and the resulting library block
and dialog box.
component spring
nodes
r = foundation.mechanical.rotational.rotational;
c = foundation.mechanical.rotational.rotational;
end
parameters
k = { 10, 'N*m/rad' };
end
variables
theta = { 0, 'rad' };
t = { 0, 'N*m' };
w = { 0, 'rad/s' };
end
branches
t : r.t -> c.t;
end
equations
assert(k>0)
w == r.w - c.w;
t == k * theta;
w == theta.der;
end
end
4-29
4 Simscape File Deployment
If you click the Source code link, the spring.ssc file opens in the MATLAB Editor window.
The following sections show you how to annotate the component file to improve the block cosmetics.
You can provide meaningful names for the block itself and for its parameters and variables in the
dialog box, as well as supply a short description of its purpose. You can also substitute a custom block
icon for the default image and change the names and the default orientation of the ports.
component spring
%Rotational Spring
...
end
4-30
Customizing the Block Name and Appearance
component spring
%Rotational Spring
% This block implements a simple rotational spring.
...
end
To create a paragraph break in the block description, use a blank commented line:
4-31
4 Simscape File Deployment
component spring
%Rotational Spring
% This block implements a simple rotational spring.
...
parameters
k = { 10, 'N*m/rad' }; % Spring rate
end
...
end
Use the same technique to specify meaningful names for the top-level public variables of the
component. These variables appear in the Initial Targets section of the block dialog box, and giving
them descriptive names helps with the block-level variable initialization prior to simulation.
the resulting Initial Targets section of the block dialog box looks like this:
4-32
Customizing the Block Name and Appearance
For complex components with large numbers of parameters, you can enhance the block usability by
grouping parameters based on their function or on the effect that they model. For example, you can
separate electrical and mechanical parameters for a motor, or place all temperature-dependent
parameters in a separate group. You do this by using the block layout annotation, UILayout.
UILayout annotation lets you define titled groups of component parameters, the order of these
groups, and the order of parameters in each group. When you deploy the component as a custom
Simscape block, these groups translate into dialog box tabs (and into Property Inspector tree nodes).
• UILayout is a class-level annotation, meaning that it can appear only once per component file.
• UILayout annotation must contain a nonempty array of UIGroup constructs. The order of the
groups defines the order of the dialog box tabs.
• Each UIGroup construct must include a title string and a nonempty comma-separated list of
component parameters. The title string serves as the title of the dialog box tab, and the listed
parameters appear on that tab, in list order.
4-33
4 Simscape File Deployment
• Component parameters with ExternalAccess=modify not listed in any of the groups appear at
the end of the first tab in declaration order.
• A parameter cannot belong to more than one group. Listing the same parameter in multiple
groups results in an error.
• This annotation does not affect component variables. Whether you use the block layout annotation
or not, variables are listed on a separate Variables tab in declaration order.
• Create multiple tabs in a block dialog box. To do this, define multiple groups of parameters. Each
group is displayed on a separate tab.
• Change the parameter order in the block dialog box, compared to the declaration order. To do this,
define one group of parameters, titled "Parameters", and list the component parameters in
desired order.
This feature makes authoring the component source independent of the resulting block layout. You
can arrange parameter declaration blocks in a way that helps code readability, and later reorder
parameters in the block interface, as needed. For a detailed example, see “Use Advanced Techniques
to Customize Block Display” on page 4-43.
There are two ways to control the port label and location in the block icon:
• Use separate controls for port labels and locations. This is the recommended way because it
provides more flexibility. Specify the port labels by using comments immediately following the
node, input, or output declaration, similar to specifying meaningful names for parameters and
variables. Specify the port side separately, by using the annotations section in the component
file. For more information, see “Customize Port Labels on the Block Icon” on page 4-34 and
“Control Port Locations Using Annotations” on page 4-35.
• Use comments immediately following the node, input, or output declaration, to specify both the
name and location of the block port. This is a legacy method that allows you to have ports only on
two opposite sides of the block icon (left and right, or top and bottom). For more information, see
“Use Comments to Control Port Locations” on page 4-36.
The default port label corresponds to the name of the node, input, or output, as specified in the
declaration block. Similar to specifying meaningful names for block parameters and variables, you
can customize a port label by supplying a comment immediately following the node, input, or output
declaration. For example:
nodes
p = foundation.electrical.electrical; % +
n = foundation.electrical.electrical; % -
end
4-34
Customizing the Block Name and Appearance
If you specify an empty comment string after a node, input, or output declaration, the corresponding
port will not have its name displayed. For example, the following syntax suppresses the port label for
the physical signal input port PS:
inputs
PS; %
end
Use the annotations section in the component file to specify the port locations. For example:
nodes
H = foundation.thermal.thermal;
p = foundation.electrical.electrical; % +
n = foundation.electrical.electrical; % -
end
annotations
H : Side = top;
p : Side = left;
n : Side = right;
end
• You can use Side annotations for nodes, inputs, and outputs.
• Member attributes must be uniquely defined. Therefore, you cannot use the same member ID on
the left side of the Side annotations more than once.
nodes
p = foundation.electrical.electrical;
n = foundation.electrical.electrical;
end
annotations
[p, n] : Side = left;
n : Side = right; % error: multiple definitions for 'Side' of port 'n'
end
If you specify different locations for the same port by using both the annotations and the
comments, the location in the annotations section takes precedence.
outputs
o = {0, 'V'}; %o:right
end
annotations
o : Side = top; % annotation takes precedence, so port will be located on the top
end
• You can use the same member ID multiple times to declare different annotation attributes.
nodes
n1 = foundation.electrical.electrical;
n2 = foundation.electrical.electrical;
n3 = foundation.electrical.electrical;
end
annotations
[n1, n2] : ExternalAccess = none;
[n2, n3] : Side = right;
end
• Similarly, you can declare different annotation attributes for the same member ID in one
statement.
nodes
n1 = foundation.electrical.electrical;
4-35
4 Simscape File Deployment
n2 = foundation.electrical.electrical;
n3 = foundation.electrical.electrical;
end
annotations
[n1, n2] : ExternalAccess = none, Side = top;
n3 : Side = right;
end
• You cannot conditionally switch port sides, that is, include Side annotations in branches of a
conditional statement.
parameters
thermal_effects = false; % Model thermal effects?
end
nodes (ExternalAccess=none)
H = foundation.thermal.thermal;
end
if thermal_effects
% Expose thermal port
annotations
H : ExternalAccess = modify;
H : Side = bottom; % error: cannot have 'Side' annotations inside conditional sections
end
end
To place a conditionally visible port on a specific side of the block (for example, on the bottom),
use the following syntax:
parameters
thermal_effects = false; % Model thermal effects?
end
nodes (ExternalAccess=none)
H = foundation.thermal.thermal;
end
annotations
H : Side = bottom;
end
if thermal_effects
% Expose thermal port
annotations
H : ExternalAccess = modify;
end
end
Note This is a legacy method that has multiple limitations. Therefore, the recommended method is to
use the annotations section, as described in “Control Port Locations Using Annotations” on page 4-
35.
You can also use a comment that immediately follows the node, input, or output declaration to specify
both the port label and location. The comment can be on the same line or on a separate line. The
comment must begin with the % character and be of the format label:location, where label is a
string corresponding to the input port name in the block diagram, and location is one of the
following strings: left, right, top, bottom. You can locate all ports either on one side of the block
or on two opposite sides, for example left and right, or top and bottom. You can omit the location if
you want to keep the default location of the port (on the left side).
4-36
Customizing the Block Name and Appearance
You can also leave the port label field empty and specify just the location. In this case, the port will
not have its name displayed. For example, the following syntax suppresses the port label and locates
it on the top of the block icon:
r = foundation.mechanical.rotational.rotational; % :top
If you specify an empty comment string after a node, input, or output declaration, the corresponding
port will not be labeled and will be located on the left side of the block icon.
The following are examples of node declarations and the resulting block icons.
nodes
r = foundation.mechanical.rotational.rotational; % rod
c = foundation.mechanical.rotational.rotational; % case
end
nodes
r = foundation.mechanical.rotational.rotational;
c = foundation.mechanical.rotational.rotational; % c:right
end
nodes
r = foundation.mechanical.rotational.rotational; % rod
c = foundation.mechanical.rotational.rotational; % case:right
end
nodes
r = foundation.mechanical.rotational.rotational; % rod
c = foundation.mechanical.rotational.rotational; % :right
end
4-37
4 Simscape File Deployment
• Explicitly, using the annotations section in the component file. This is the recommended way
because it provides more flexibility. You can keep the image files in a separate folder and specify
relative paths for the block icons. You can also specify conditional custom icons for different block
variants. For more information, see “Using Annotations” on page 4-38.
• Implicitly, using the file naming conventions. This method is convenient if you ship complete
library packages to customers. For more information, see “Using File Naming Conventions” on
page 4-39.
Using Annotations
Use the annotations section in the component file to specify the name of the custom block icon.
The file name must contain the file extension. For example:
annotations
Icon = 'custom_spring.jpg';
end
The file name can include a relative path from the folder containing the component file to the folder
containing the image file, for example:
annotations
Icon = '../../block_icons/custom_spring.jpg';
end
The annotations section also lets you specify conditional custom icons. This is especially useful if
the number of ports changes for different variants. For example:
component MyPipe
parameters
thermal_variant = false; % Model thermal effects?
end
if thermal_variant
% Use icon with additional thermal port
annotations
Icon = 'pipe_thermal.jpg';
end
else
% Use regular icon, with two fluid ports
annotations
Icon = 'pipe.jpg';
end
end
4-38
Customizing the Block Name and Appearance
Instead of explicitly specifying a custom block icon using the annotations section, you can do it
implicitly, by placing an image file with the same name as the component in the folder containing the
component file.
This method is convenient if you ship complete library packages to customers. For example, if the
subpackage containing the component file spring.ssc also contains a file named spring.jpg, then
that image file is automatically used for the icon representing this block in the custom library.
1 If the annotations section does not explicitly specify a custom icon image, or if that image is
not found, the software looks in the folder containing the component file for an image file with
the same name as the component.
2 If there are multiple image files with the same name, the formats take precedence in the order
listed in “Supported File Formats” on page 4-39. For example, if the subpackage contains both
spring.jpg and spring.bmp, spring.jpg is the image that will appear in the custom library.
The following image file formats are supported for custom block icons:
• svg
• jpg
• bmp
• png
Caution Using svg format together with domain-specific line styles can lead to unexpected results,
because domain line styles and colors can propagate to parts of the custom block icon. For more
information on turning domain-specific line styles on and off, see “Domain-Specific Line Styles”.
The image type must be an RGB (truecolor) image, stored as an m-by-n-by-3 data array. For more
information, see “RGB (Truecolor) Images”.
When you use an image file to represent a component in the custom block library, the following
syntax in the component file lets you specify the scaling and rotation properties of the image file:
component name
% [ CustomName [ : scale [ : rotation ] ] ]
...
where
4-39
4 Simscape File Deployment
You cannot specify MATLAB expressions for the scale, just numbers.
rotation Specifies whether the block icon rotates with the block:
• rotates means that the icon rotates when you rotate the block.
This is the default behavior.
• fixed means that the ports rotate when you rotate the block, but
the icon always stays in default orientation.
component spring
% Rotational Spring : 0.5 : fixed
specifies that the spring image size is scaled to half of its default size and always stays in its default
orientation, regardless of the block rotation.
See Also
annotations
Related Examples
• “Customize Block Display” on page 4-41
• “Use Advanced Techniques to Customize Block Display” on page 4-43
4-40
Customize Block Display
component spring
% Rotational Spring
% This block implements a simple rotational spring.
nodes
r = foundation.mechanical.rotational.rotational; % rod
c = foundation.mechanical.rotational.rotational; % case
end
annotations
r : Side = left;
c : Side = right;
Icon = 'custom_spring.jpg';
end
parameters
k = { 10, 'N*m/rad' }; % Spring rate
end
variables
theta = { 0, 'rad' }; % Deformation
t = { 0, 'N*m' }; % Torque
w = { 0, 'rad/s' }; % Angular velocity
end
branches
t : r.t -> c.t;
end
equations
assert(k>0)
w == r.w - c.w;
t == k * theta;
w == theta.der;
end
end
4-41
4 Simscape File Deployment
See Also
annotations
More About
• “Customizing the Block Name and Appearance” on page 4-29
• “Use Advanced Techniques to Customize Block Display” on page 4-43
4-42
Use Advanced Techniques to Customize Block Display
The following source code for the DCMotorWithGroups component includes declaration blocks for
nodes and user-visible parameters, as well as control logic and annotations. The source code in this
example does not include sections of code that have no effect on the block dialog box display, such as
other declarations, intermediates, branches, and equations.
component DCMotorWithGroups
% DC Motor
% This block represents the electrical and torque characteristics of a
% DC motor.
%
% When a positive current flows from the electrical + to - ports, a
% positive torque acts from the mechanical C to R ports. Motor torque
% direction can be changed by altering the sign of the back-emf
% constant.
nodes
p = foundation.electrical.electrical; % +:top
n = foundation.electrical.electrical; % -:bottom
R = foundation.mechanical.rotational.rotational; % R:top
C = foundation.mechanical.rotational.rotational; % C:bottom
end
parameters
Ra = {3.9, 'Ohm'}; % Armature resistance
La = {12e-6, 'H'}; % Armature inductance
Kv = {0.072e-3, 'V/rpm'}; % Back-emf constant
J = {0.01, 'g*cm^2'}; % Rotor inertia
lam = {0, 'N*m/(rad/s)'}; % Rotor damping
speed0 = {0, 'rpm'}; % Initial rotor speed
i_noload = {0, 'A'}; % No-load current
V_i_noload = {1.5, 'V'}; % DC supply voltage when measuring no-load current
end
annotations
UILayout = [UIGroup("Electrical Torque",Ra,La,Kv,r_damp,i_noload,V_i_noload)
UIGroup("Mechanical",J,lam,speed0)]
4-43
4 Simscape File Deployment
end
end
The UILayout annotation defines two groups, Electrical Torque and Mechanical, each with a
list of parameters. When you generate a block from the DCMotorWithGroups component, each
UIGroup becomes a separate section in the block dialog box, the title string serves as the title of the
section, and these parameters appear under that section in listed order.
In addition, the DCMotorWithGroups component provides two methods to specify rotor damping:
The if statement in the component source specifies the control logic for conditional parameter
visibility, depending on the selected value of the control parameter, r_damp (Rotor damping
parameterization). The control parameter uses an enumeration that is located in a separate file,
damping.m:
This enumeration file can be located either in same folder as the component file or on the MATLAB
path. For more information, see “Specifying Display Strings for Enumeration Members” on page 3-15.
In the resulting block dialog, the Rotor damping parameterization parameter has a drop-down list
of values:
• By damping value
• By no-load current
When you generate a block from the DCMotorWithGroups component, the block dialog box groups
the parameters under two sections:
4-44
Use Advanced Techniques to Customize Block Display
If you set the Rotor damping parameterization parameter to By no-load current, two
additional parameters appear in the Electrical Torque section, and the Rotor damping parameter
in the Mechanical section is hidden.
Note that in the Electrical Torque section, the No-load current and DC supply voltage when
measuring no-load current parameters appear below the Rotor damping parameterization
parameter, even though they were declared earlier, in a separate declaration block. If the component
was not using the block layout annotation, you could have achieved the same effect by changing the
parameter declaration order, but that would have detracted from code readability.
See Also
annotations
4-45
4 Simscape File Deployment
More About
• “Customizing the Block Name and Appearance” on page 4-29
• “Defining Conditional Visibility of Component Members” on page 2-83
• “Enumerations” on page 3-14
4-46
Checking File and Model Dependencies
Similarly, Simscape files and custom libraries also depend on certain files to build successfully, or to
correctly visualize and execute in MATLAB. These files can include all component files for building a
library, domain files, custom image files for blocks or libraries, and so on.
Dependency analysis tools for Simscape files consist of the following command-line options:
• simscape.dependency.file — Return the set of existing full path dependency files and
missing files for a single Simscape file, for a specific dependency type.
• simscape.dependency.lib — Return the set of existing full path dependency files and missing
files for a Simscape custom library package. You can optionally specify dependency type and
library model file name.
• simscape.dependency.model — Return the set of Simscape related dependency files and
missing files for a given model containing Simscape and Simulink blocks.
The Dependency Analyzer also includes dependencies for the Simscape blocks present in the model.
For more information on the Dependency Analyzer, see “Analyze Model Dependencies”.
This way, dependency information is not exposed to a model user, who has only protected files.
However, the developer, who has both the source and protected files, is able to perform complete
dependency analysis.
4-47
4 Simscape File Deployment
- +MySimscapeLibrary
|-- +MechanicalElements
| |-- lib.m
| |-- lib.jpg
| |-- spring.ssc
| |-- spring.jpg
| |-- ...
To check dependencies for the file spring.ssc, type the following at the MATLAB command prompt:
[a, b] = simscape.dependency.file('MySimscapeLibrary.MechanicalElements.spring')
This command returns two cell arrays of strings: array a, containing full path names of existing
dependency files (such as spring.jpg), and array b, containing names of missing files. If none of the
files are missing, array b is empty.
For example, to return all dependency files for a top-level package +MySimscapeLibrary, change
your working directory to the folder containing this package and type the following at the MATLAB
command prompt:
[a, b] = simscape.dependency.lib('MySimscapeLibrary')
If you are running this command from a working directory inside the package, you can omit the
library name, because it is the only argument, and type:
[a, b] = simscape.dependency.lib
This command returns two cell arrays of strings: array a, containing full path names of all existing
dependency files and array b, containing names of missing files. If none of the files are missing, array
b is empty.
To determine which files are necessary to share the library package, type:
[a, b] = simscape.dependency.lib('MySimscapeLibrary',simscape.DependencyType.Simulink)
In this case, the arrays a and b contain all files necessary to build the library, run the models built
from its blocks, and visualize them correctly.
To check dependencies on Simscape blocks and files only, use the function
simscape.dependency.model. For example, open the model dc_motor and type:
4-48
Checking File and Model Dependencies
[a b c d] = simscape.dependency.model('dc_motor')
This command returns two cell arrays of strings and two lists of structures. Array a contains full path
names of all existing dependency files. Array b contains names of missing files. Structure lists c and d
indicate reference types for existing and missing reference files, respectively. Each structure includes
a field 'names' as a list of file names causing the reference, and a field 'type' as the reference type
for each file. Two reference types are used: 'Simscape component' indicates reference from a
model block. 'Simscape' indicates reference from a file.
If none of the files are missing, array b and list d are empty.
4-49
4 Simscape File Deployment
Getting Started
This case study explains how to build your own library of custom blocks based on component files. It
uses an example library of capacitor models. The library makes use of the Simscape Foundation
electrical domain on page 6-4, and defines three simple components. For more advanced topics,
including adding multiple levels of hierarchy, adding new domains, and customizing the appearance
of a library, see “Case Study — Electrochemical Library” on page 4-55.
The example library comes built and on your path so that it is readily executable. However, it is
recommended that you copy the source files to a new directory, for which you have write permission,
and add that directory to your MATLAB path. This will allow you to make changes and rebuild the
library for yourself. The source files for the example library are in the following package directory:
matlabroot/toolbox/physmod/simscape/simscapedemos/+Capacitors
where matlabroot is the MATLAB root directory on your machine, as returned by entering
matlabroot
After copying the files, change the directory name +Capacitors to another name, for example
+MyCapacitors, so that your copy of the library builds with a unique name.
ssc_build MyCapacitors
in the MATLAB Command Window. If building from within the +MyCapacitors package directory,
you can omit the argument and type just
ssc_build
MyCapacitors_lib
For more information on the library build process, see “Building Custom Block Libraries” on page 4-
21.
4-50
Case Study — Basic Custom Block Library
Adding a Block
To add a block, write a corresponding component file and place it in the package directory. For
example, the Ideal Capacitor block in your MyCapacitors_lib library is produced by the
IdealCapacitor.ssc file. Open this file in the MATLAB Editor and examine its contents.
component IdealCapacitor
% Ideal Capacitor
% Models an ideal (lossless) capacitor. The output current I is related
% to the input voltage V by I = C*dV/dt where C is the capacitance.
nodes
p = foundation.electrical.electrical; % +:top
n = foundation.electrical.electrical; % -:bottom
end
parameters
C = { 1, 'F' }; % Capacitance
end
variables
i = { 0, 'A' }; % Current
v = {value = { 0, 'V' }, priority = priority.high}; % Voltage drop
end
branches
i : p.i -> n.i; % Through variable i from node p to node n
end
equations
assert(C > 0)
v == p.v-n.v; % Across variable v from p to n
i == C*v.der; % Capacitor equation
end
end
First, let us examine the elements of the component file that affect the block appearance. Double-
click the Ideal Capacitor block in the MyCapacitors_lib library to open its dialog box, and compare
the block icon and dialog box to the contents of the IdealCapacitor.ssc file. The block name,
Ideal Capacitor, is taken from the comment on line 2. The comments on lines 3 and 4 are then taken
to populate the block description in the dialog box. The block ports are defined by the nodes section.
The comment expressions at the end of each line control the port label and location. Similarly in the
parameters section, the comments are used to define parameter names in the block dialog box. For
details, see “Customizing the Block Name and Appearance” on page 4-29.
Also notice that in the equation section there is an assert to ensure that the capacitance value is
always greater than zero. This is good practice to ensure that a component is not used outside of its
domain of validity. The Simscape Foundation library blocks have such checks implemented where
appropriate.
4-51
4 Simscape File Deployment
Ideal Ultracapacitor
Ultracapacitors, as their name suggests, are capacitors with a very high capacitance value. The
relationship between voltage and charge is not constant, unlike for an ideal capacitor. Suppose a
manufacturer data sheet gives a graph of capacitance as a function of voltage, and that capacitance
increases approximately linearly with voltage from the 1 farad at zero volts to 1.5 farads when the
voltage is 2.5 volts. If the capacitance voltage is denoted v, then the capacitance can be approximated
as:
C = 1 + 0.2 · v
For a capacitor, current i and voltage v are related by the standard equation
dv
i=C
dt
and hence
dv
i = (C0 + Cv · v)
dt
where C0 = 1 and Cv = 0.2. This equation is implemented by the following line in the equation section
of the Simscape file IdealUltraCapacitor.ssc:
i == (C0 + Cv*v)*v.der;
In order for the Simscape software to interpret this equation, the variables (v and i) and the
parameters (C0 and Cv) must be defined in the declaration section. For more information, see
“Declare Component Variables” on page 2-8 and “Declare Component Parameters” on page 2-13.
4-52
Case Study — Basic Custom Block Library
This block is implemented by the component file LossyUltraCapacitor.ssc. Open this file in the
MATLAB Editor and examine its contents.
component LossyUltraCapacitor
% Lossy Ultracapacitor
% Models an ultracapacitor with resistive losses. The capacitance C
% depends on the voltage V according to C = C0 + V*dC/dV. A
% self-discharge resistance is included in parallel with the capacitor,
% and an equivalent series resistance in series with the capacitor.
nodes
p = foundation.electrical.electrical; % +:top
n = foundation.electrical.electrical; % -:bottom
end
parameters
C0 = { 1, 'F' }; % Nominal capacitance C0 at V=0
Cv = { 0.2, 'F/V'}; % Rate of change of C with voltage V
R = {2, 'Ohm' }; % Effective series resistance
Rd = {500, 'Ohm' }; % Self-discharge resistance
end
variables
i = { 0, 'A' }; % Current
vc = {value = { 0, 'V' }, priority = priority.high}; % Capacitor voltage
end
branches
i : p.i -> n.i; % Through variable i from node p to node n
end
equations
assert(C0 > 0)
assert(R > 0)
assert(Rd > 0)
let
v = p.v-n.v; % Across variable v from p to n
in
i == (C0 + Cv*vc)*vc.der + vc/Rd; % Equation 1
v == vc + i*R; % Equation 2
end
end
end
The additional variable is used to denote the voltage across the capacitor, vc. The equations can then
be expressed in terms of v, i, and vc using Kirchhoff’s current and voltage laws. Summing currents at
the capacitor + node gives the first Simscape equation:
4-53
4 Simscape File Deployment
v == vc + i*R;
As a check, the number of equations required for a component used in a single connected network is
given by the sum of the number of ports plus the number of internal variables minus one. This is not
necessarily true for all components (for example, one exception is mass), but in general it is a good
rule of thumb. Here this gives 2 + 1 - 1 = 2.
In the Simscape file, the initial condition (initial voltage in this example) is applied to variable vc with
priority = priority.high, because this is a differential variable. In this case, vc is readily
identifiable as the differential variable as it has the der (differentiator) operator applied to it.
During the library build, if there is an image file in the directory with the same name as the Simscape
component file, then this is used to define the icon for the block. For example, the Ideal Capacitor
block defined by IdealCapacitor.ssc uses the IdealCapacitor.jpg to define its block icon. If
you do not include an image file, then the block displays its name in place of an icon. For details, see
“Customize the Block Icon” on page 4-38.
4-54
Case Study — Electrochemical Library
Getting Started
This case study explores more advanced topics of building custom Simscape libraries. It uses an
example library for modeling electrochemical systems. The library introduces a new electrochemical
domain and defines all of the fundamental components required to build electrochemical models,
including an electrochemical reference, through and across sensors, sources, and a cross-domain
component. The example illustrates some of the salient features of Physical Networks modeling, such
as selection of Through and Across variables and how power is converted between domains. We
suggest that you work through the previous section, “Case Study — Basic Custom Block Library” on
page 4-50, before looking at this more advanced example.
The example library comes built and on your path so that it is readily executable. However, it is
recommended that you copy the source files to a new directory, for which you have write permission,
and add that directory to your MATLAB path. This will allow you to make changes and rebuild the
library for yourself. The source files for the example library are in the following package directory:
matlabroot/toolbox/physmod/simscape/simscapedemos/+ElectroChem
where matlabroot is the MATLAB root directory on your machine, as returned by entering
matlabroot
After copying the files, change the directory name +ElectroChem to another name, for example
+MyElectroChem, so that your copy of the library builds with a unique name.
ssc_build MyElectroChem
4-55
4 Simscape File Deployment
in the MATLAB Command Window. If building from within the +MyElectroChem package directory,
you can omit the argument and type just
ssc_build
For more information on the library build process, see “Building Custom Block Libraries” on page 4-
21.
As an example of an application requiring the addition of a new domain, consider a battery where the
underlying equations involve both electrical and chemical processes [1 on page 4-64].
Two half-cells are separated by a membrane that prevents the ions flowing between cells, and hence
electrons flow from the solid lead anode to the platinum cathode. The two half-cell reactions are:
2+
Pb Pb + 2e−
Fe2 + Fe3 + + e−
The current results in the lead being oxidized and the iron being reduced, with the overall reaction
given by:
2+
Pb + 2Fe3 + Pb + 2Fe2 +
The chemical reaction can be modeled using the network concepts of Through and Across variables
(for details, see “Basic Principles of Modeling Physical Networks”). The Through variable represents
4-56
Case Study — Electrochemical Library
flow, and the Across variable represents effort. When selecting the Through and Across variables, you
should use SI units and the product of the two variables is usually chosen to have units of power.
In the electrochemical reactions, an obvious choice for the Through variable is the molar flow rate ṅ
of ions, measured in SI units of mol/s. The corresponding Across variable is called chemical potential,
and must have units of J/mol to ensure that the product of Through and Across variables has units of
power, J/s. The chemical potential or Gibb’s free energy per mol is given by:
μ = μ0 + RTlna
where μ0 is the standard state chemical potential, R is the perfect gas constant, T is the temperature,
and a is the activity. In general, the activity can be a function of a number of different parameters,
including concentration, temperature, and pressure. Here it is assumed that the activity is
proportional to the molar concentration defined as number of moles of solute divided by the mass of
solvent.
To see the electrochemical domain definition, open the Simscape file +MyElectroChem/
ElectroChem.ssc.
domain ElectroChem
% Electrochemical Domain
% Define through and across variables for the electrochemical domain
variables
% Chemical potential
mu = { 1.0 'J/mol' };
end
variables(Balancing = true)
% Molar flow
ndot = { 1.0 'mol/s' };
end
end
The molar fundamental dimension and unit is predefined in the Simscape unit registry. If it had not
been, then you could have added it with:
pm_adddimension('mole','mol')
Note The case study does not involve modifying the domain definition. However, if at a later point
you decide to modify this electrochemical domain definition and see the effect of these modifications
on the custom components, make sure to change all the node declarations in the component files
from ElectroChem.ElectroChem to MyElectroChem.ElectroChem. Otherwise, your component
files still point to the domain definition in the original package.
4-57
4 Simscape File Deployment
nodes
A = ElectroChem.ElectroChem; % A:top
end
connections
connect(A, *);
end
end
The component has one electrochemical port, named A, located at the top of the block icon.
connect(A, *);
For more information on component connections and the implicit reference node syntax, see
“Connections to Implicit Reference Node” on page 2-68.
nodes
A = ElectroChem.ElectroChem; % A:top
B = ElectroChem.ElectroChem; % B:bottom
end
parameters
mu0 = {0, 'J/mol'}; % Chemical potential
end
variables(Access=private)
4-58
Case Study — Electrochemical Library
branches
ndot: A.ndot -> B.ndot; % Through variable ndot from node A to node B
end
equations
let
mu = A.mu - B.mu; % Across variable from A to B
in
mu == mu0;
end
end
end
The dual of an ideal Across source is an ideal Through source, which maintains the Through variable
to some set value regardless of the value of the Across variable. In the electrical domain, this
corresponds to the DC Current Source block in the Foundation library. In the example library, this
source is not implemented.
nodes
A = ElectroChem.ElectroChem; % A:top
B = ElectroChem.ElectroChem; % B:bottom
end
outputs
out = { 0, 'mol/s' }; % PS:top
end
variables(Access=private)
ndot = { 0, 'mol/s' }; % Molar flow rate
end
branches
ndot: A.ndot -> B.ndot; % Through variable ndot from node A to node B
end
equations
let
mu = A.mu - B.mu; % Across variable from A to B
in
mu == 0; % No potential drop
out == ndot; % Equate value of molar flow to PS output
end
end
end
The flow rate is presented as a Physical Signal, which can then in turn be passed to Simulink via a
PS-Simulink Converter block. The branches section and the let statement in the equation section
define the relationship between Through and Across variables for the sensor. In this case, an ideal
4-59
4 Simscape File Deployment
flow sensor has zero potential drop, that is mu == 0, where mu is the chemical potential. The second
equation assigns the value of the Through variable to the Physical Signal output.
nodes
A = ElectroChem.ElectroChem; % A:top
B = ElectroChem.ElectroChem; % B:bottom
end
outputs
out = { 0, 'J/mol' }; % PS:top
end
variables(Access=private)
ndot = { 0, 'mol/s' }; % Molar flow rate
end
branches
ndot: A.ndot -> B.ndot; % Through variable ndot from node A to node B
end
equations
let
mu = A.mu - B.mu; % Across variable from A to B
in
ndot == 0; % Draws no molar flow
out == mu; % Equate value of chemical potential difference to PS output
end
end
end
The chemical potential is presented as a Physical Signal, which can then in turn be passed to
Simulink via a PS-Simulink Converter block. The branches section and the let statement in the
equation section define the relationship between Through and Across variables for the sensor. In this
case, an ideal chemical potential sensor draws no flow, that is ndot == 0, where ndot is the flow
rate. The second equation assigns the value of the Across variable to the Physical Signal output.
ṅ = ν
n
a=
C0M
μ = μ0 + RTlna
4-60
Case Study — Electrochemical Library
where n is the number of moles of the ion, C0 is the standard concentration of 1 mol/kg, and M is the
mass of the solute.
nodes
A = ElectroChem.ElectroChem; % A:top
end
parameters
mu0 = {-7.42e+04, 'J/mol'}; % Standard state oxidizing potential
m_solvent = {1, 'kg'}; % Mass of solvent
T = {300, 'K'}; % Temperature
end
parameters (Access=private)
R = {8.314472, '(J/K)/mol'}; % Universal gas constant
C0 = {1, 'mol/kg'}; % Standard concentration
n1 = {1e-10, 'mol'}; % Minimum number of moles
end
variables
ndot = { 0, 'mol/s' }; % Molar flow rate
n = {value = { 0.01, 'mol' }, priority = priority.high}; % Quantity of ions
end
branches
ndot : A.ndot -> *; % Through variable ndot
end
equations
n.der == ndot;
if n > n1
A.mu == mu0 + log(n/(C0*m_solvent))*R*T;
else
A.mu == mu0 + (log(n1/(C0*m_solvent)) + n/n1 - 1)*R*T;
end
end
end
This component introduces two Simscape language features not yet used in the blocks looked at so
far. These are:
• Use of a conditional statement in the equation section. This is required to prevent taking the
logarithm of zero. Hence if the molar concentration is less than the specified level n1, then the
operand of the logarithm function is limited. Without this protection, the solver could perturb the
value of n to zero or less.
• Definition of private parameters that can be used in the equation section. Here the Universal Gas
constant (R) and the Standard Concentration (C0) are defined as private parameters. Their values
could equally well be used directly in the equations, but this would reduce readability of the
definition. Similarly, the lower limit on the molar concentration n1 is also defined as a private
parameter, but could equally well have been exposed to the user.
4-61
4 Simscape File Deployment
i
ν=
zF
where ν is the molar flow rate, i is the current, z is the number of electrons per ion, and F is the
Faraday constant. The second equation comes from equating the electrical and chemical powers:
V 2 − V 1 i = μ2 − μ1 ν
ν μ2 − μ1
V 2 − V 1 = μ2 − μ1 =
i zF
This is the Nernst equation written in terms of chemical potential difference, (μ2 – μ1). These
chemical-electrical converter equations are implemented by the component file +MyElectroChem/
+Elements/Chem2Elec.ssc.
component Chem2Elec
% Chemical to Electrical Converter
% Converts chemical energy into electrical energy (and vice-versa)
% assuming no losses. The electrical current flow i is related to the
% molar flow of electrons ndot by i = -ndot*z*F where F is the Faraday
% constant and z is the number of exchanged electrons.
nodes
p = foundation.electrical.electrical; % +:top
n = foundation.electrical.electrical; % -:top
A = ElectroChem.ElectroChem; % A:bottom
B = ElectroChem.ElectroChem; % B:bottom
end
parameters
z = {1, '1'}; % Number of exchanged electrons
end
parameters(Access=private)
F = {9.6485309e4, 'C/mol'}; % Faraday constant
end
variables
i = { 0, 'A' }; % Current
ndot = { 0, 'mol/s' }; % Molar flow rate
end
branches
i : p.i -> n.i; % Through variable i from node p to node n
ndot: A.ndot -> B.ndot; % Through variable ndot from node A to node B
end
equations
let
4-62
Case Study — Electrochemical Library
k = 1/(z*F);
v = p.v - n.v; % Across variable v from p to n
mu = A.mu - B.mu; % Across variable mu from A to B
in
v == k*mu; % From equating power
ndot == -k*i; % Balance electrons (Faraday's Law)
end
end
end
Note the use of the let-in-end construction in the component equations. An intermediate term k is
declared as
1
k=
zF
This component has four ports but only two equations. This is because the component interfaces two
different physical networks. Each of the networks has two ports and one equation, thus satisfying the
requirement for n–1 equations, where n is the number of ports. In the case of a cross-domain
component, the two equations are coupled, thereby defining the interaction between the two physical
domains.
The Faraday constant is a hidden parameter, because it is a physical constant that block users would
not need to change. Therefore, it will not appear in the block dialog box generated from the
component file.
In the electrochemical library example, lib.m files are also placed in each subpackage directory to
customize the name and appearance of respective sublibraries. For example, open
+MyElectroChem/+Sensors/lib.m in the MATLAB Editor. The following line causes the sublibrary
to be named Electrochemical Sensors:
In the absence of the lib.m file, the library would be named after the subpackage name, that is,
Sensors. For more information, see “Library Configuration Files” on page 4-25.
4-63
4 Simscape File Deployment
References
[1] Pêcheux, F., B. Allard, C. Lallement, A. Vachoux, and H. Morel. “Modeling and Simulation of Multi-
Discipline Systems using Bond Graphs and VHDL-AMS.” International Conference on Bond Graph
Modeling and Simulation (ICBGM). New Orleans, USA, 23–27 Jan. 2005.
4-64
5
Language Reference
across
Establish relationship between component variables and nodes
Syntax
across( variable1, node1.variableA, node2.variableB )
Version History
Introduced in R2008b
5-2
annotations
annotations
Control appearance of Simscape block based on the component
Syntax
annotations
[Id1, Id2] : ExternalAccess=value;
UILayout = [UIGroup("Title 1",p1,p2) UIGroup("Title 2",p3)]
Icon = 'filename';
[port1, port2] : Side=value;
[param1, param2] : UnitDropdown = common
[var1, int2] : LoggingUnit = 'unit expression'
end
Version History
Introduced in R2019a
See Also
parameters | nodes | inputs | outputs | variables
Topics
“Defining Conditional Visibility of Component Members” on page 2-83
“Attribute Lists” on page 2-104
“Use Advanced Techniques to Customize Block Display” on page 4-43
“Customize the Block Icon” on page 4-38
“Customize the Names and Locations of the Block Ports” on page 4-34
“Physical Signal Unit Propagation”
“How to Specify Units in Block Dialogs”
5-3
5 Language Reference
assert
Program customized run-time errors and warnings
Syntax
assert (predicate_condition, message, Action);
Version History
Introduced in R2011b
Prior to R2019a, you specified the assert action by using the Warn = true|false attribute. This
attribute still works. Currently, there are no plans to remove it.
Internally, the old attribute values are automatically mapped to the appropriate values of the new
Action attribute:
You cannot use the Warn and Action attributes together in a single assert construct. When
authoring new components, use the Action attribute because it provides more flexibility.
See Also
equations
Topics
“Programming Run-Time Errors and Warnings” on page 2-50
5-4
branches
branches
Establish relationship between component Through variables and nodes
Syntax
branches
a : node1.a -> node2.a;
end
Description
branches begins the branches section, which is terminated by an end keyword. This section
contains one or more branch statements, which establish the relationship between the Through
variables of the component and the domain.
and a component declares two nodes, node1 and node2, associated with this domain, and a variable
a:
variables
a = { 0, 'N' };
end
The name of the component variable does not have to match that of the domain variable, but the units
must be commensurate (in this example, 'N', 'kg*m/s^2', 'lbf', and so on).
To establish a connection between the component variable a and the domain Through (balancing)
variable a, write a branch statement, such as:
branches
a : node1.a -> node2.a;
end
node1.a and node2.a identify the conserving equations on node1 and node2, and the component
variable a is a term participating in those conserving equations. The branch statement declares that
a flows from node1 to node2. Therefore, a is subtracted from the conserving equation identified by
node1.a, and a is added to the conserving equation identified by node2.a.
A component can use each conserving equation identifier multiple times. For example, the component
declares the following variables and branches:
variables
a1 = { 0, 'N' }
a2 = { 0, 'N' }
a3 = { 0, 'N' }
end
5-5
5 Language Reference
branches
a1 : node1.a -> node2.a;
a2 : node1.a -> node2.a;
a3 : node2.a -> node1.a;
end
Then, assuming that node1 and node2 are not referenced by any other branch or connect
statements, the conserving equations at these nodes are:
• For node1
- a1 - a2 + a3 == 0
• For node2
a1 + a2 - a3 == 0
Syntax Rules
• Each conserving equation belongs to a node associated with a domain. All variables participating
in that conserving equation must have commensurate units.
• A node creates one conserving equation for each of the Through (balancing) variables in the
associated domain. Branch statements do not create new equations. They add and subtract terms
in the existing conserving equations at the nodes.
• The second and third arguments do not need to be associated with the same domain. For example,
one can be associated with a gas domain, and the other with a thermal domain, with the heat flow
exchange defined by the branch statement.
• You can replace either the second or the third argument with * to indicate the reference node.
When you use *, the variable indicated by the first argument is still added to or subtracted from
the equation indicated by the other identifier, but no equation is affected by the *.
Examples
If a component declaration section contains two electrical nodes, p and n, and a variable i =
{0,'A'}; specifying current, you can establish the following relationship in the branches section:
branches
i : p.i -> n.i;
end
This statement defines current i as a Through variable flowing from node p to node n.
For a grounding component, which has one electrical node V, define current i as a Through variable
flowing from node V to the reference node:
5-6
branches
branches
i : V.i -> *;
end
For a mutual inductor or transformer, with primary and secondary windings, the branches section
must contain two statements, one for each winding:
branches
i1 : p1.i -> n1.i;
i2 : p2.i -> n2.i;
end
For a component such as a constant volume pneumatic chamber, where you need to establish the heat
flow exchange between the pneumatic and the thermal domains, the declaration section contains the
two nodes and the heat flow variable:
nodes
A = foundation.pneumatic.pneumatic;
H = foundation.thermal.thermal;
end
variables
h = { 0 , 'J/s' };
end
and the branches section establishes the heat flow exchange between the two domains:
branches
h : A.Q -> H.Q;
end
This statement defines the heat flow h as a Through variable flowing from the pneumatic node A,
associated with the chamber inlet, to the thermal node H, associated with the thermal mass of gas in
the chamber.
Version History
Introduced in R2013b
See Also
nodes | variables
Topics
“Define Relationship Between Component Variables and Nodes” on page 2-23
5-7
5 Language Reference
component
Component model keywords
Syntax
component
nodes
inputs
outputs
parameters
variables
components
intermediates
branches
connections
equations
events
annotations
Version History
Introduced in R2008b
See Also
domain
Topics
“Creating Custom Components” on page 1-13
5-8
components
components
Declare member components included in composite component
Syntax
components(ExternalAccess=observe)
a = package_name.component_name;
end
Version History
Introduced in R2012b
See Also
connections | parameters
Topics
“Declaring Member Components” on page 2-61
5-9
5 Language Reference
connect
Connect two or more component ports of the same type
Syntax
connect(n1, n2);
connect(s, d1);
Version History
Introduced in R2012b
See Also
connections
Topics
“Specifying Component Connections” on page 2-66
5-10
connections
connections
Define connections for member component ports in composite component
Syntax
connections connect(a, b); end
Version History
Introduced in R2012b
See Also
connect
Topics
“Declaring Member Components” on page 2-61
“Specifying Component Connections” on page 2-66
5-11
5 Language Reference
delay
Return past value of operand
Syntax
delay(u,tau)
delay(u,tau, History = u0, MaximumDelay = taumax)
Version History
Introduced in R2012a
See Also
equations
5-12
der
der
Return time derivative of operand
Syntax
der(x)
x.der
Version History
Introduced in R2008b
See Also
equations
5-13
5 Language Reference
domain
Domain model keywords
Syntax
domain
variables
variables(Balancing = true)
parameters
intermediates
Version History
Introduced in R2008b
See Also
component
Topics
“When to Define a New Physical Domain” on page 1-11
“Foundation Domain Types and Directory Structure” on page 6-2
5-14
edge
edge
Trigger event
Syntax
edge(b)
Description
edge(b) takes a scalar boolean expression b as input. It returns true, and triggers an event, when
and only when the input argument changes value from false to true. The return data type of edge is
event. Event data type is a special category of boolean type, which returns true only instantaneously,
and returns false otherwise.
The following graphic illustrates the difference between boolean and event data types.
You use the edge operator to define event predicates in when clauses. For more information, see
events.
Examples
edge(b)
5-15
5 Language Reference
edge(~b)
Trigger an Event Both on the Rising Edge and the Falling Edge
To trigger an event both on the rising edge and on the falling edge of condition b, use:
edge(b)||edge(~b)
For more information on data derivation rules between boolean and event data types, see “Event Data
Type and edge Operator” on page 2-54.
To trigger an event at a specific time, for example, 2 seconds after the start of simulation, use:
edge(time>{2.0,'s'})
Version History
Introduced in R2016a
See Also
events | initialevent
Topics
“Triggered Delay Component” on page 2-57
“Enabled Component” on page 2-58
“Discrete Event Modeling” on page 2-54
5-16
entry
entry
Specify actions to be performed upon entering a mode
Syntax
entry v_old = v; end
Version History
Introduced in R2020b
See Also
modecharts | modes | transitions | initial
Topics
“State Reset Modeling” on page 3-11
“Mode Chart Modeling” on page 3-2
5-17
5 Language Reference
equations
Define component equations
Syntax
equations
Expression1 == Expression2;
end
Version History
Introduced in R2009a
See Also
assert | delay | der | function | integ | intermediates | tablelookup | time
Topics
“Defining Component Equations” on page 2-26
“Using Conditional Expressions in Equations” on page 2-35
“Using Intermediate Terms in Equations” on page 2-37
5-18
events
events
Model discrete events
Syntax
events
when EventPredicate
AssignmentList
end
end
Description
events begins the events section, which is terminated by an end keyword. The events section in a
component file manages event updates. It is executed throughout the simulation.
The when clause serves to update the values of the event variables. The syntax is
when EventPredicate
var1 = expr1;
var2 = expr2;
...
end
The variables in the body of the when clause must be declared as event variables on page 2-54. When
the event predicate returns true, all the variables in the body of the when clause simultaneously get
updated to the new values.
when EventPredicate
var1 = expr1;
var2 = expr2;
...
elsewhen EventPredicate
var1 = expr3;
...
end
Syntax Rules
5-19
5 Language Reference
Examples
When the control signal becomes positive, the event variable x gets updated to the current value of
the input signal u. Output y outputs the value of x. Therefore, the output signal y gets updated to the
current value of the input signal u on the rising edge of the control signal, and then holds that value
between the events.
Version History
Introduced in R2016a
See Also
edge | initialevent
Topics
“Enabled Component” on page 2-58
5-20
events
5-21
5 Language Reference
function
Reuse expressions in component equations and in member declarations of domains and components
Syntax
function out = FunctionName(in1,in2)
definitions
out = Expression1(in1,in2);
end
end
Description
The function keyword begins the Simscape function declaration, which is terminated by an end
keyword.
The keyword function must be followed by the function header, which includes the function name,
inputs, and outputs.
The body of the function must be enclosed inside the definitions block, which is terminated by an
end keyword. The definitions block contains equations that express the output arguments of the
function in terms of its input arguments. This block is required.
• Main function — You must place the function declaration in a file of the same name with a file
name extension of .ssc. The file name must match the function name. For example, function foo
must be in a file called foo.ssc. The file must begin with the function keyword. Only blank
lines and comments can precede function.
• Local function — Include the function declaration in a component, domain, or function file, after
the final end keyword that concludes the description of the component, domain, or main function.
The local function is accessible only by that component, domain, or main function.
Syntax Rules
5-22
function
o == FunctionName(5,2);
• Simscape function files can reside directly on MATLAB path or in package directories. For more
information, see “Organizing Your Simscape Files” on page 4-21.
• You can use source protection, as described in “Using Source Protection for Simscape Files” on
page 4-22.
• Importing a package imports all the Simscape functions in this package. For more information, see
“Importing Domain and Component Classes” on page 2-110.
• If a MATLAB function and a Simscape function have the same name, the MATLAB function has
higher precedence.
Examples
This example shows how you can write a function that computes the square of a sum of two numbers,
for reuse in multiple components.
Use the function in a component. The MyComp component calls the SumSquared function to compute
the square of a sum of its parameters p1 and p2.
5-23
5 Language Reference
component MyComp
outputs
o = 0;
end
parameters
p1 = 5;
p2 = 2;
end
equations
o == SumSquared(p1,p2);
end
end
When you need to use a function in a single component only, defining it as a local function:
In this example, the rotational spring component uses a local function to modify its torque equation.
The component file includes the local function localTorque after the final end keyword that
concludes the description of the component:
component spring_with_local_function
nodes
r = foundation.mechanical.rotational.rotational;
c = foundation.mechanical.rotational.rotational;
end
parameters
k = { 10, 'N*m/rad' };
end
variables
theta = { 0, 'rad' };
t = { 0, 'N*m' }; % torque through
w = { 0, 'rad/s' }; % velocity across
end
branches
t : r.t -> c.t; % torque through from node r to node c
end
equations
assert(k>0) % spring rate must be greater than zero
w == r.w - c.w; % velocity across between node r and node c
t == localTorque(k,theta);
w == theta.der;
end
end
5-24
function
end
end
Version History
Introduced in R2017b
See Also
equations
Topics
“Simscape Functions” on page 3-24
5-25
5 Language Reference
import
Import model classes
Syntax
import package_or_class;
import package.*;
Version History
Introduced in R2013b
See Also
Topics
“Importing Domain and Component Classes” on page 2-110
5-26
initial
initial
Specify initial mode in mode chart
Syntax
initial init_mode : predicate_condition end
Version History
Introduced in R2017a
See Also
modecharts | modes | transitions
Topics
“Mode Chart Modeling” on page 3-2
“Switch with Hysteresis” on page 3-5
5-27
5 Language Reference
initialevent
Initialize event variables
Syntax
events
when initialevent
AssignmentList
end
end
Version History
Introduced in R2017b
See Also
edge | events
Topics
“Discrete Event Modeling” on page 2-54
5-28
inputs
inputs
Define component inputs, that is, Physical Signal input ports of block
Syntax
inputs in1 = { value , 'unit' }; end
Version History
Introduced in R2008b
See Also
outputs | nodes
Topics
“Declare Component Inputs and Outputs” on page 2-18
“Physical Signal Unit Propagation”
5-29
5 Language Reference
integ
Perform time integration of expression
Syntax
integ(expr,t_L)
Version History
Introduced in R2016a
See Also
equations
5-30
intermediates
intermediates
Define intermediate terms for use in equations
Syntax
intermediates int_term1 = expr1; end
Version History
Introduced in R2018b
See Also
equations
Topics
“Using Intermediate Terms in Equations” on page 2-37
5-31
5 Language Reference
modecharts
Declare mode charts that include operating modes and transitions
Syntax
modecharts (ExternalAccess = value)
mc1 = modechart
...
end
end
Description
modecharts begins a mode charts declaration section, which is terminated by an end keyword.
modecharts is a top-level section in a component file. It can contain one or more modechart
constructs. Each modechart construct declares one mode chart. A mode chart declaration must
describe a complete set of operating modes and transition rules between these modes.
For example, the following syntax declares two mode charts, mc1 and mc2.
A mode chart is defined within the scope of its parent component. In other words, its equations and
predicates reference the component members, such as parameters and variables.
5-32
modecharts
For a detailed example of using modecharts, see “Switch with Hysteresis” on page 3-5.
A mode chart cannot be modifiable in the user interface. Therefore, the following rules apply:
• A modecharts declaration section can have its ExternalAccess attribute set to observe or
none, but not to modify.
• The default Access attribute value is public, and the corresponding default value for the
ExternalAccess attribute is modify. Therefore, if you do not set the Access attribute for a
modecharts declaration section, you must explicitly set its ExternalAccess attribute to
observe or none. For example:
Set the ExternalAccess attribute to none if you do not want the mode chart to be visible
anywhere outside the language. For example:
Version History
Introduced in R2017a
See Also
modes | transitions | initial | entry
Topics
“Switch with Hysteresis” on page 3-5
“Mode Chart Modeling” on page 3-2
5-33
5 Language Reference
modes
Declare operating modes in mode chart
Syntax
modes
mode m1
...
end
end
Description
modes begins a modes declaration section in a mode chart. The modes section, terminated by an end
keyword, can contain one or more mode constructs. Each mode construct declares one mode.
For example, the following syntax declares two modes, m1 and m2.
modes
mode m1
...
end
mode m2
...
end
end
mode is a named construct. It is terminated by an end keyword. Each mode declaration contains a
complete set of equations that describe this operating mode.
modes
mode m1
equations
...
end
end
mode m2
equations
...
end
end
end
For every mode, the total number of equation expressions, their dimensionality, and their order must
be the same. This restriction is the same as for the equations in different branches of the if-
elseif-else statement.
This restriction does not apply to the assert expressions, because they are not included in the
expression count.
5-34
modes
A mode declaration can contain an entry section, which lets you specify the actions to be performed
upon entering the mode. These actions are event variable updates based on the value of a continuous
variable immediately before entering the mode.
modes
mode m1
equations
...
end
end
mode m2
entry
...
end
equations
...
end
end
end
The entry section is separate from the equations section, and the event variable updates in the
entry section are not counted in the number of equation expressions for the mode.
To implement a state reset, mode charts can contain instantaneous modes and compound transitions.
An instantaneous mode is a mode that is active only for one event iteration. You declare
instantaneous modes the same way as regular modes, using the same syntax. The same mode can be
used as an instantaneous mode in one case and a regular mode in another, depending on the
transitions declared in a mode chart. To specify that a mode is instantaneous, list it as the middle
mode in a compound transition.
For a detailed example of using modes, see “Switch with Hysteresis” on page 3-5.
Version History
Introduced in R2017a
See Also
modecharts | entry | transitions | initial
Topics
“Switch with Hysteresis” on page 3-5
“Mode Chart Modeling” on page 3-2
5-35
5 Language Reference
nodes
Define component nodes, that is, conserving ports of block
Syntax
nodes a = package_name.domain_name; end
Version History
Introduced in R2008b
See Also
inputs | outputs
Topics
“Declare Component Nodes” on page 2-16
“Define Relationship Between Component Variables and Nodes” on page 2-23
“Customize the Names and Locations of the Block Ports” on page 4-34
“Arrays of Nodes” on page 3-43
5-36
outputs
outputs
Define component outputs, that is, Physical Signal output ports of block
Syntax
outputs out1 = { value , 'unit' }; end
Version History
Introduced in R2008b
See Also
inputs | nodes
Topics
“Declare Component Inputs and Outputs” on page 2-18
5-37
5 Language Reference
parameters
Declare domain or component parameters
Syntax
parameters
par1 = {value,'unit'};
end
Description
parameters begins a parameters declaration section, which is terminated by an end keyword:
• In a component file, this section contains declarations for the component parameters. Component
parameters let you specify adjustable parameters for the Simscape block generated from the
component file. Parameters appear in the block dialog box and can be modified when building and
simulating a model.
• In a domain file, this section contains declarations for the domain parameters. The main purpose
of domain parameters is to propagate the same parameter value to all or some of the components
connected to the domain.
parameters
par1 = {value,'unit'};
end
value is the initial parameter value. unit is a valid unit string, defined in the unit registry.
To declare a unitless parameter, you can either use the same syntax:
par1 = {value,'1'};
par1 = value;
For component parameters, adding a comment after the parameter declaration lets you specify the
parameter name, the way you want it to appear in the block dialog box:
parameters
comp_par1 = {value,'unit'}; % Parameter name
end
Examples
5-38
parameters
This example declares a component parameter k, with a default value of 10 N*m/rad, specifying the
spring rate of a rotational spring. In the block dialog box and Property Inspector, this parameter will
be named Spring rate.
parameters
k = {10,'N*m/rad'}; % Spring rate
end
The purpose of domain parameters is to propagate the same parameter value to all or some of the
components connected to the domain. For example, this hydraulic domain contains one Across
variable, p, one Through variable, q, and one parameter, t.
domain t_hyd
variables
p = {1e6,'Pa'}; % pressure
end
variables(Balancing = true)
q = {1e-3,'m^3/s'}; % flow rate
end
parameters
t = {303,'K'}; % fluid temperature
end
end
All components with nodes connected to this domain will have access to the fluid temperature
parameter t and can use this parameter in their equations.
Version History
Introduced in R2008b
See Also
value
Topics
“Declare Component Parameters” on page 2-13
“Working with Domain Parameters” on page 2-99
5-39
5 Language Reference
setup
(Not recommended) Prepare component for simulation
Note setup is not recommended. For more information, see “Compatibility Considerations”.
Syntax
function setup
[...]
end
function setup %#simple
[...]
end
Version History
Introduced in R2008b
Starting in R2019a, run-time capable domain parameters have been implemented. Unlike component
parameters, domain parameters propagate to other components connected to the circuit. Therefore,
when you set the parameter as Run-time in the source component, it is possible that another
component connected to the same circuit is using this parameter in the context which prevents it
from being run-time configurable. For example, if one of the components connected to the circuit
uses a domain parameter in its setup function, you get an error when trying to simulate the model.
There are no plans to remove setup at this time. However, to avoid errors with run-time domain
parameters, it is recommended that you avoid using the setup function in your custom components.
Other constructs available in Simscape language let you achieve the same results without
compromising run-time capabilities.
5-40
setup
See Also
assert
Topics
“Programming Run-Time Errors and Warnings” on page 2-50
“Declaration Functions” on page 3-21
“Variable Priority for Model Initialization” on page 2-9
“Source Components” on page 2-99
5-41
5 Language Reference
tablelookup
Return value based on interpolating set of data points
Syntax
tablelookup(x1d, x2d, x3d, x4d, fd, x1, x2, x3, x4, interpolation = linear|
smooth, extrapolation = linear|nearest|error)
Version History
Introduced in R2012a
See Also
equations | makima | PS Lookup Table (1D) | PS Lookup Table (2D) | PS Lookup Table (3D) | PS
Lookup Table (4D)
Topics
“Using Lookup Tables in Equations” on page 2-48
5-42
through
through
Establish relationship between component variables and nodes
Syntax
through( variableI, node1.variableA, node2.variableB )
Version History
Introduced in R2008b
5-43
5 Language Reference
time
Access global simulation time
Syntax
time
Version History
Introduced in R2008b
See Also
equations
Topics
“Use Simulation Time in Equations” on page 2-32
5-44
transitions
transitions
Define transitions between modes in mode chart
Syntax
transitions from_mode -> to_mode : predicate_condition end
Version History
Introduced in R2017a
See Also
modecharts | modes | initial
Topics
“Mode Chart Modeling” on page 3-2
“Switch with Hysteresis” on page 3-5
“State Reset Modeling” on page 3-11
5-45
5 Language Reference
value
Convert variable or parameter to unitless value with specified unit conversion
Syntax
value(a,'unit')
value(a,'unit','type')
Version History
Introduced in R2008b
See Also
parameters | variables
Topics
“Declaring a Member as a Value with Unit” on page 2-5
5-46
variables
variables
Declare domain or component variables
Syntax
variables
v1 = {value,'unit'};
end
Description
variables begins a variables declaration section, which is terminated by an end keyword:
• In a component file, this section contains declarations for the variables associated with the
component.
• In a domain file, this section contains declarations for the Across variables associated with the
domain. Additionally, domain files must have a separate variables declaration section, with the
Balancing attribute set to true, which contains declarations for the Through variables
associated with the domain.
Component Variables
In a component file, the following syntax defines an Across, Through, or internal variable,
comp_var1, as a value with unit on page 2-5. value is the initial value. unit is a valid unit string,
defined in the unit registry.
variables
comp_var1 = {value,'unit'};
end
For component variables, you can additionally specify the initialization priority, the acceptable
initialization range, and the nominal value and unit by declaring the variable as a field array.
variables
comp_var2 = {value = {value,'unit'},
priority = priority.value,
imin={value,'unit'},imax={value,'unit'},
nominal = {value,'unit'}};
end
The first field in the array is value (value with unit on page 2-5). The other fields are optional and
can come in any order.
The priority field can be one of three values listed in the following table:
Priority field in Simscape language Resulting default priority in the block dialog
box
priority = priority.high High
5-47
5 Language Reference
Priority field in Simscape language Resulting default priority in the block dialog
box
priority = priority.low Low
priority = priority.none (this is the None
default)
Note It is recommended that you use the priority attribute sparingly. The default priority value,
priority.none (which is equivalent to leaving out the priority attribute entirely), is suitable in
most cases. The block user can modify the variable priority value, as needed, in the Variables tab of
the block dialog box prior to simulation.
The imin and imax fields let you specify the minimum and maximum acceptable values for variable
initialization, for example:
variables
x = {value={0,'deg'},imin={0,'deg'},imax={360,'deg'}};
end
When multiple initialization solutions exist, this syntax lets you guide the solver towards the
preferred solution. For more information, see “Block-Level Variable Initialization”. If the specified
range cannot be satisfied during initialization, the solver issues an error. The solver tries to satisfy
the initialization range for a variable regardless of whether its initialization priority is high, low, or
none.
The default initialization range is (-inf,inf). Therefore, you do not have to specify both values to
define the range, it is sufficient to specify only imin or imax. For example, use this syntax to limit the
temperature to positive values:
variables
T = {value={293.15,'K'},imin={0,'K'}};
end
When you specify imin or imax, these values define an open range.
Note The block user does not have control over the variable initialization range. Only the block
author can specify the acceptable minimum and maximum values for variable initialization in the
component file, both for continuous and for event variables.
The nominal field must be a value with unit on page 2-5, where value is the nominal value, that is,
the expected magnitude of the variable. unit is a valid unit string, defined in the unit registry.
Note It is recommended that you use the nominal attribute sparingly. The default nominal values,
which come from the model value-unit table, are suitable in most cases. The block user can also
modify the nominal values and units for individual blocks by using either the block dialog box or
set_param and get_param functions, if needed. For more information, see “Modify Nominal Values
for a Block Variable”.
You can also specify the variable name, the way you want it to appear in the Initial Targets section
of the block dialog box, as a comment:
5-48
variables
variables
comp_var1 = {value,'unit'}; % Variable name
end
Domain Variables
In a domain file, the following syntax defines an Across variable, domain_across_var1, as a value
with unit on page 2-5. value is the initial value. unit is a valid unit string, defined in the unit
registry.
variables
domain_across_var1 = {value,'unit'};
end
You can specify initialization ranges for domain Across variables, for example, to exclude negative
values for pressure or temperature. The syntax is the same as for component variables:
variables
domain_across_var1 = {value={value,'unit'},imin={value,'unit'},imax={value,'unit'}};
end
In a domain file, the following syntax defines a Through variable, domain_through_var1, as a value
with unit on page 2-5. value is the initial value. unit is a valid unit string, defined in the unit
registry.
variables(Balancing = true)
domain_through_var1 = {value,'unit'};
end
Examples
variables
w = {0,'rad/s'}; % Angular velocity
end
In the Initial Targets section of the block dialog box, this variable will be named Angular velocity
and will have the default initialization priority of none. The block user will be able to change this
initialization priority as needed.
variables
x = {value = {0,'mm'},priority = priority.high}; % Spring deformation
end
5-49
5 Language Reference
In the Initial Targets section of the block dialog box, this variable will be named Spring
deformation and will have the high initialization priority by default. The block user will be able to
change this initialization priority as needed.
variables(Balancing = true)
t = {1,'N*m'};
end
Version History
Introduced in R2008b
See Also
value
Topics
“Declare Component Variables” on page 2-8
“Declare Through and Across Variables for a Domain” on page 2-6
5-50
6
Simscape Foundation libraries are organized in a package containing domain and component
Simscape files. The name of the top-level package directory is +foundation, and the package
consists of subpackages containing domain files, structured as follows:
- +foundation
|-- +electrical
| |-- electrical.ssc
| |-- three_phase.ssc
| |-- ...
|-- +gas
| |-- gas.ssc
| |-- ...
|-- +hydraulic
| |-- hydraulic.ssc
| |-- ...
|-- +isothermal_liquid
| |-- isothermal_liquid.ssc
| |-- ...
|-- +magnetic
| |-- magnetic.ssc
| |-- ...
|-- +mechanical
| |-- +rotational
| | |-- rotational.ssc
| | |-- ...
| |-- +translational
| | |-- translational.ssc
| | |-- ...
|-- +moist_air
| |-- moist_air.ssc
| |-- moist_air_source.ssc
| |-- ...
|-- +pneumatic (kept for compatibility purposes)
6-2
Foundation Domain Types and Directory Structure
| |-- pneumatic.ssc
| |-- ...
|-- +thermal
| |-- thermal.ssc
| |-- ...
|-- +thermal_liquid
| |-- thermal_liquid.ssc
| |-- ...
|-- +two_phase_fluid
| |-- two_phase_fluid.ssc
| |-- ...
To use a Foundation domain in a component declaration, refer to the domain name using the full path,
starting with the top package directory. The following example uses the syntax for the Simscape
Foundation mechanical rotational domain:
r = foundation.mechanical.rotational.rotational;
6-3
6 Simscape Foundation Domains
Electrical Domain
The electrical domain declaration is shown below.
domain electrical
% Electrical Domain
parameters
Temperature = { 300.15 , 'K' }; % Circuit temperature
GMIN = { 1e-12 , '1/Ohm' }; % Minimum conductance, GMIN
end
variables
v = { 0 , 'V' };
end
variables(Balancing = true)
i = { 0 , 'A' };
end
end
To refer to this domain in your custom component declarations, use the following syntax:
foundation.electrical.electrical
See Also
More About
• “Foundation Domain Types and Directory Structure” on page 6-2
6-4
Three-Phase Electrical Domain
domain three_phase
% Three-Phase Electrical Domain
parameters
Temperature = { 300.15 , 'K' }; % Circuit temperature
GMIN = { 1e-12 , '1/Ohm' }; % Minimum conductance, GMIN
end
variables
V = { [ 0 0 0 ], 'V' };
end
variables(Balancing = true)
I = { [ 0 0 0 ], 'A' };
end
end
To refer to this domain in your custom component declarations, use the following syntax:
foundation.electrical.three_phase
See Also
More About
• “Foundation Domain Types and Directory Structure” on page 6-2
6-5
6 Simscape Foundation Domains
Gas Domain
To view the complete domain source file, at the MATLAB Command prompt, type:
open([matlabroot '/toolbox/physmod/simscape/library/m/+foundation/+gas/gas.ssc'])
Abbreviated gas domain declaration is shown below, with intermediate lookup table values omitted
for readability.
domain gas
% Gas Domain
parameters
gas_spec = foundation.enum.gas_spec.perfect_gas; % Gas specification
% 1 - perfect_gas
% 2 - semiperfect_gas
% 3 - real_gas
log_T_TLU1 = {[
5.01063529409626
5.07517381523383
...
7.60090245954208
], '1'}; % Log temperature vector
h_TLU1 = {[
275.264783730547
285.377054177734
...
2377.14064127409
], 'kJ/kg'}; % Specific enthalpy vector
cp_TLU1 = {[
1.01211492398124
1.01042105529234
...
1.24628356718428
], 'kJ/(kg*K)'}; % Specific heat at constant pressure vector
cv_TLU1 = {[
0.725174216111164
0.723480347422265
...
0.959342859314206
], 'kJ/(kg*K)'}; % Specific heat at constant volume vector
mu_TLU1 = {[
10.3766056544352
10.9908682444892
...
68.0682900809450
], 'uPa*s'}; % Dynamic viscosity vector
k_TLU1 = {[
14.1517155766309
15.0474512994325
...
114.486299090693
], 'mW/(m*K)'}; % Thermal conductivity vector
6-6
Gas Domain
Pr_TLU1 = {[
0.742123270231960
0.738025627675206
...
0.740982912785154
], '1'}; % Prandtl number vector
a_TLU1 = {[
245.095563145758
253.217606015000
...
863.440849227825
], 'm/s'}; % Speed of sound vector
int_dh_T_TLU1 = {[
0
0.0652630980004620
0.126478959779276
...
2.79681971660776
], 'kJ/(kg*K)'}; % integral of dh/T vector
log_T_TLU2 = {[
5.01063529409626
5.07517381523383
...
7.60090245954208
], '1'}; % Log temperature vector
log_p_TLU2 = {[
9.21034037197618
9.90348755253613
...
16.1180956509583
], '1'}; % Log pressure vector
log_rho_TLU2 = {[
-1.45933859209149 -0.765580954956293 ... 2.84006136461620
], '1'}; % Log density table
s_TLU2 = {[
3.85666832168988 3.65733557342939 ... 4.66584072487367
], 'kJ/(kg*K)'}; % Specific entropy table
h_TLU2 = {[
276.007989595737 275.926922934925 ... 2386.79535914098
], 'kJ/kg'}; % Specific enthalpy table
cp_TLU2 = {[
1.00320557010184 1.00416915257750 ... 1.24767439351222
], 'kJ/(kg*K)'}; % Specific heat at constant pressure table
cv_TLU2 = {[
0.715425577953031 0.715655648411093 ... 0.960303115685940
], 'kJ/(kg*K)'}; % Specific heat at constant volume table
mu_TLU2 = {[
10.3604759816291 10.3621937105615 ... 68.3249440282350
], 'uPa*s'}; % Dynamic viscosity table
k_TLU2 = {[
14.0896194596466 14.0962928994967 ... 114.905858092359
], 'mW/(m*K)'}; % Thermal conductivity table
Pr_TLU2 = {[
0.737684026417089 0.738165370950116 ... 0.741888050943969
], '1'}; % Prandtl number table
a_TLU2 = {[
245.567929192228 245.496359667264 ... 878.939999571000
], 'm/s'}; % Speed of sound table
6-7
6 Simscape Foundation Domains
log_drho_dp_TLU2 = [
-10.6690690699104 -10.6678475863467 ... -13.2956456388403
]; % Log derivative of density with respect to pressure table
log_drho_dT_TLU2 = [
-6.46809263806814 -5.77245144865022 ... -4.77782516923660
]; % Log derivative of density with respect to temperature table
drhou_dp_TLU2 = [
5.41617782089664 5.42024592837099 ... 3.03095417965253
]; % Derivative of internal energy per unit volume with respect to pressure table
drhou_dT_TLU2 = {[
-0.195280173069178 -0.391714814336739 ... 1.27305147462835
], 'kJ/(m^3*K)'}; % Derivative of internal energy per unit volume with respect to temperature table
pT_region_flag = foundation.enum.pT_region_G.from_props;
% Valid pressure-temperature region parameterization
% 1 - from_props
% 2 - min_max
% 3 - validity
pT_validity_TLU2 = ones(24, 20); % Pressure-temperature validity matrix
variables
p = {0.1, 'MPa'}; % Pressure
T = {300, 'K' }; % Temperature
end
variables (Balancing=true)
mdot = {0, 'kg/s'}; % Mass flow rate
Phi = {0, 'kW' }; % Energy flow rate
end
end
• 1 — Perfect (default)
• 2 — Semiperfect
6-8
Gas Domain
• 3 — Real
In the Foundation Gas library, the Gas Properties (G) block serves as the source for domain parameter
values, including the selection of the gas model. For more information on propagation of domain
parameters, see “Working with Domain Parameters” on page 2-99.
The domain declaration also contains sets of parameters that define gas properties for each gas
model.
Properties for semiperfect and real gas are in the form of lookup table data. These parameter
declarations propagate to the components connected to the Gas domain, and therefore you can use
them in the tablelookup function in the component equations.
To refer to this domain in your custom component declarations, use the following syntax:
foundation.gas.gas
See Also
More About
• “Foundation Domain Types and Directory Structure” on page 6-2
6-9
6 Simscape Foundation Domains
Hydraulic Domain
Note Isothermal liquid domain, introduced in R2020a, provides a more robust and flexible way of
modeling isothermal hydraulic systems.
parameters
density = { 850 , 'kg/m^3' }; % Fluid density
viscosity_kin = { 18e-6 , 'm^2/s' }; % Kinematic viscosity
bulk = { 0.8e9 , 'Pa' }; % Bulk modulus at atm. pressure and no gas
alpha = { 0.005 , '1' }; % Relative amount of trapped air
end
variables
p = { 0 , 'Pa' };
end
variables(Balancing = true)
q = { 0 , 'm^3/s' };
end
end
To refer to this domain in your custom component declarations, use the following syntax:
foundation.hydraulic.hydraulic
See Also
More About
• “Foundation Domain Types and Directory Structure” on page 6-2
6-10
Isothermal Liquid Domain
parameters
bulk_modulus_model = foundation.enum.bulk_modulus_model.const; % Isothermal bulk modulus model
% 1 - const
% 2 - linear
air_dissolution_model = simscape.enum.onoff.off; % Air dissolution model
% 1 - on
% 0 - off
rho_L_atm = {998.21, 'kg/m^3'}; % Liquid density at atmospheric pressure (no entrained air)
beta_L_atm = {2.1791e9, 'Pa' }; % Liquid isothermal bulk modulus at atmospheric pressure (no entrained air)
beta_gain = {6, '1' }; % Isothermal bulk modulus vs. pressure increase gain
nu_atm = {1.0034e-6, 'm^2/s' }; % Kinematic viscosity at atmospheric pressure
air_fraction = {0.005, '1' }; % Volumetric fraction of entrained air in mixture at atmospheric pressure
rho_g_atm = {1.225, 'kg/m^3'}; % Gas (air) density at atmospheric condition
polytropic_index = {1.0, '1' }; % Air polytropic index
p_atm = {0.101325, 'MPa' }; % Atmospheric pressure
p_crit = {3, 'MPa' }; % Pressure at which all entrained air is dissolved
p_min = {0.1, 'Pa' }; % Minimum valid pressure
end
variables
p = {0.1, 'MPa'}; % Pressure
end
end
6-11
6 Simscape Foundation Domains
To refer to this domain in your custom component declarations, use the following syntax:
foundation.isothermal_liquid.isothermal_liquid
See Also
More About
• “Foundation Domain Types and Directory Structure” on page 6-2
6-12
Magnetic Domain
Magnetic Domain
The magnetic domain declaration is shown below.
domain magnetic
% Magnetic Domain
parameters
mu0 = { 4*pi*1e-7 'Wb/(m*A)' }; % Permeability constant
end
variables
mmf = { 0 , 'A' };
end
variables(Balancing = true)
phi = { 0 , 'Wb' };
end
end
To refer to this domain in your custom component declarations, use the following syntax:
foundation.magnetic.magnetic
See Also
More About
• “Foundation Domain Types and Directory Structure” on page 6-2
6-13
6 Simscape Foundation Domains
domain rotational
% Mechanical Rotational Domain
variables
w = { 0 , 'rad/s' };
end
variables(Balancing = true)
t = { 0 , 'N*m' };
end
end
To refer to this domain in your custom component declarations, use the following syntax:
foundation.mechanical.rotational.rotational
See Also
More About
• “Foundation Domain Types and Directory Structure” on page 6-2
6-14
Mechanical Translational Domain
domain translational
% Mechanical Translational Domain
variables
v = { 0 , 'm/s' };
end
variables(Balancing = true)
f = { 0 , 'N' };
end
end
To refer to this domain in your custom component declarations, use the following syntax:
foundation.mechanical.translational.translational
See Also
More About
• “Foundation Domain Types and Directory Structure” on page 6-2
6-15
6 Simscape Foundation Domains
Abbreviated moist air domain declaration is shown below, with intermediate lookup table values
omitted for readability.
domain moist_air
% Moist Air Domain
parameters
trace_gas_model = foundation.enum.trace_gas_model.none; % Trace gas model
% 1 - none
% 2 - track_fraction
% 3 - track_properties
log_p_ws_TLU = [
0.537480914463376
1.37059832527040
...
16.4965444877527
16.6206369090880]; % Log of water vapor saturation pressure vector in Pa
h_w_vap_TLU = {[
2836.88241275372
2837.81392500514
...
1027.62017777647
892.733785613825], 'kJ/kg'}; % Water specific enthalpy of vaporization vector
h_a_TLU = {[
342.416126230579
349.005511058471
...
747.258774447567
757.813011774199], 'kJ/kg'}; % Dry air specific enthalpy vector
h_w_TLU = {[
2396.55944251649
2408.68643343608
...
3155.43043805905
3175.80160435813], 'kJ/kg'}; % Water vapor specific enthalpy vector
h_g_TLU = {[
342.416126230579
349.005511058471
...
747.258774447567
757.813011774199], 'kJ/kg'}; % Trace gas specific enthalpy vector
mu_a_TLU = {[
14.2568883320012
14.6140127728333
...
31.2307628592324
31.5791070262086], 'uPa*s'}; % Dry air dynamic viscosity vector
mu_w_TLU = {[
6.81365662228272
6-16
Moist Air Domain
7.04953750742707
...
21.1317199525111
21.4937680016671], 'uPa*s'}; % Water vapor dynamic viscosity vector
mu_g_TLU = {[
14.2568883320012
14.6140127728333
...
31.2307628592324
31.5791070262086], 'uPa*s'}; % Trace gas dynamic viscosity vector
k_a_TLU = {[
19.8808489374933
20.4162454629695
...
46.7832370779530
47.3667074066625], 'mW/(m*K)'}; % Dry air thermal conductivity vector
k_w_TLU = {[
11.4628821597600
11.9419974889350
...
43.1675775109350
44.0380174089350], 'mW/(m*K)'}; % Water vapor thermal conductivity vector
k_g_TLU = {[
19.8808489374933
20.4162454629695
...
46.7832370779530
47.3667074066625], 'mW/(m*K)'}; % Trace gas thermal conductivity vector
cp_a_coeff = {[
1.02664779928781
-0.000177515573577911
3.66581785159269e-07], 'kJ/(kg*K)'}; % Dry air specific heat polynomial coefficients
cp_w_coeff = {[
1.47965047747103
0.00120021143370507
-3.86145131678391e-07], 'kJ/(kg*K)'}; % Water vapor specific heat polynomial coefficients
cp_g_coeff = {[
1.02664779928781
-0.000177515573577911
3.66581785159269e-07], 'kJ/(kg*K)'}; % Trace gas specific heat polynomial coefficients
Pr_a_TLU = [
0.720986465349271
0.719589372441350
...
0.704694042255749
0.705614770118245]; % Dry air Prandtl number pressure vector
Pr_w_TLU = [
1.02327757654022
...
1.01351190334830
1.01402827396757]; % Water vapor Prandtl number pressure vector
Pr_g_TLU = [
0.720986465349271
0.719589372441350
...
0.704694042255749
0.705614770118245]; % Trace gas Prandtl number pressure vector
int_dh_T_a_TLU = {[
0
0.0299709934765051
...
6-17
6 Simscape Foundation Domains
1.05826245662507
1.07533673877425], 'kJ/(kg*K)'}; % Dry air integral of dh/T vector
int_dh_T_w_TLU = {[
0
0.0551581028022933
...
1.96804836665268
2.00100413885432], 'kJ/(kg*K)'}; % Water vapor integral of dh/T vector
int_dh_T_g_TLU = {[
0
0.0299709934765051
...
1.05826245662507
1.07533673877425], 'kJ/(kg*K)'}; % Trace gas integral of dh/T vector
variables
p = {0.1, 'MPa'}; % Pressure
T = {300, 'K' }; % Temperature
x_w = 0; % Specific humidity
x_g = 0; % Trace gas mass fraction
end
variables (Balancing=true)
mdot = {0, 'kg/s'}; % Mixture mass flow rate
Phi = {0, 'kW' }; % Mixture energy flow rate
mdot_w = {0, 'kg/s'}; % Water vapor mass flow rate
mdot_g = {0, 'kg/s'}; % Trace gas mass flow rate
end
end
6-18
Moist Air Domain
• foundation.enum.trace_gas_model.none — None
• foundation.enum.trace_gas_model.track_fraction — Track mass fraction only
• foundation.enum.trace_gas_model.track_properties — Track mass fraction and gas
properties
In the Foundation Moist Air library, the Moist Air Properties (MA) block serves as the source for
domain parameter values, including the selection of the trace gas model. For more information on
propagation of domain parameters, see “Working with Domain Parameters” on page 2-99.
The moist air mixture is composed of three gas species. The default domain parameter values
correspond to dry air, water vapor, and carbon dioxide:
You can modify these parameter values in the Moist Air Properties (MA) block to model any three-
species gas mixture.
The domain declaration also contains sets of parameters that define various dry air, water vapor, and
trace gas properties in the form of lookup table data. The table lookup is with respect to the
temperature vector, T_TLU. These parameter declarations propagate to the components connected to
the Moist Air domain, and therefore you can use them in the tablelookup function in the
component equations.
To refer to this domain in your custom component declarations, use the following syntax:
foundation.moist_air.moist_air
See Also
“Moist Air Source Domain” on page 6-20
More About
• “Modeling Moist Air Systems”
• “Working with Domain Parameters” on page 2-99
• “Foundation Domain Types and Directory Structure” on page 6-2
6-19
6 Simscape Foundation Domains
To view the complete domain source file, at the MATLAB Command prompt, type:
open([matlabroot '/toolbox/physmod/simscape/library/m/+foundation/+moist_air/moist_air_source.ssc
Abbreviated moist air source domain declaration is shown below, with intermediate lookup table
values omitted for readability.
domain moist_air_source
% Moist Air Source Domain
% This domain is used only for connecting sources of moisture and trace gas
% to moist air components.
parameters
trace_gas_model = foundation.enum.trace_gas_model.track_properties; % Trace gas model
% 1 - none
% 2 - track_fraction
% 3 - track_properties
h_w_vap_TLU = {[
2836.88241275372
2837.81392500514
...
1027.62017777647
892.733785613825], 'kJ/kg'}; % Water specific enthalpy of vaporization vector
h_w_TLU = {[
2396.55944251649
2408.68643343608
...
3155.43043805905
3175.80160435813], 'kJ/kg'}; % Water vapor specific enthalpy vector
h_g_TLU = {[
439.555216260064
444.670268200251
...
814.123440770426
824.984623198037], 'kJ/kg'}; % Trace gas specific enthalpy vector
variables
T = {300, 'K'}; % Temperature
x_w = 0; % Specific humidity
x_g = 0; % Trace gas mass fraction
end
variables (Balancing=true)
Phi = {0, 'kW' }; % Mixture energy flow rate
mdot_w = {0, 'kg/s'}; % Water vapor mass flow rate
mdot_g = {0, 'kg/s'}; % Trace gas mass flow rate
end
end
6-20
Moist Air Source Domain
• foundation.enum.trace_gas_model.none — None
• foundation.enum.trace_gas_model.track_fraction — Track mass fraction only
• foundation.enum.trace_gas_model.track_properties — Track mass fraction and gas
properties
In the Foundation Moist Air library, the Moist Air Properties (MA) block serves as the source for
domain parameter values, including the selection of the trace gas model. For more information on
propagation of domain parameters, see “Working with Domain Parameters” on page 2-99.
The domain declaration also contains sets of parameters that define water vapor and trace gas
properties in the form of lookup table data. The table lookup is with respect to the temperature
vector, T_TLU. These parameter declarations propagate to the components connected to the Moist Air
Source domain, and therefore you can use them in the tablelookup function in the component
equations.
You do not need to independently specify the water vapor and trace gas properties for the Moist Air
Source domain. The Moist Air library blocks with an S port are set up in such a way that they
propagate the properties from the regular Moist Air domain to the Moist Air Source domain
connected to their S port. This way, the water vapor and trace gas properties are consistent between
the Moist Air domain and the Moist Air Source domain.
To refer to this domain in your custom component declarations, use the following syntax:
foundation.moist_air.moist_air_source
See Also
“Moist Air Source Domain” on page 6-20
More About
• “Modeling Moisture and Trace Gas Levels”
• “Working with Domain Parameters” on page 2-99
• “Foundation Domain Types and Directory Structure” on page 6-2
6-21
6 Simscape Foundation Domains
Thermal Domain
The thermal domain declaration is shown below.
domain thermal
% Thermal domain
variables
T = { 0 , 'K' };
end
variables(Balancing = true)
Q = { 0 , 'J/s' };
end
end
To refer to this domain in your custom component declarations, use the following syntax:
foundation.thermal.thermal
See Also
More About
• “Foundation Domain Types and Directory Structure” on page 6-2
6-22
Thermal Liquid Domain
open([matlabroot '/toolbox/physmod/simscape/library/m/+foundation/+thermal_liquid/thermal_liquid.
Abbreviated thermal liquid domain declaration is shown below, with intermediate lookup table values
omitted for readability.
domain thermal_liquid
% Thermal Liquid Domain
parameters (Size=variable)
% Default liquid property tables for water
% Rows of the tables correspond to the temperature vector
% Columns of the tables correspond to the pressure vector
pT_validity_TLU = {[
1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1
0 1 1 1 1 1 1 1 1 1 1 1
0 1 1 1 1 1 1 1 1 1 1 1
0 1 1 1 1 1 1 1 1 1 1 1
0 1 1 1 1 1 1 1 1 1 1 1
0 1 1 1 1 1 1 1 1 1 1 1
0 1 1 1 1 1 1 1 1 1 1 1
], '1'}; % Pressure-temperature validity matrix
rho_TLU = {[
999.8 999.8 ... 978.2 980.3
], 'kg/m^3'}; % Density table
u_TLU = {[
0.0002 0.0018 ... 407.1700 405.9800
], 'kJ/kg'}; % Specific internal energy table
nu_TLU = {[
1.7917 1.7914 ... 0.3000 0.3007
], 'mm^2/s'}; % Kinematic viscosity table
cp_TLU = {[
4.2199 4.2194 ... 4.1245 4.1157
], 'kJ/(kg*K)'}; % Specific heat at constant pressure table
k_TLU = {[
561.0400 561.0900 ... 703.3500 706.0000
], 'mW/(m*K)'}; % Thermal conductivity table
beta_TLU = {[
1.9649 1.9654 ... 2.3455 2.3788
], 'GPa'}; % Isothermal bulk modulus table
alpha_TLU = {1e-4 * [
-0.6790 -0.6760 ... 6.8590 6.8000
], '1/K'}; % Isobaric thermal expansion coefficient table
mu_TLU = {[
1.79134166000000 ... 0.294776210000000
], 'cP'}; % Dynamic viscosity table
Pr_TLU = {[
13.4736964762477 ... 1.71842839588810
], '1'}; % Prandtl number table
end
parameters
pT_region_flag = {1, '1' }; % Valid pressure-temperature region parameterization
% 0 - By minimum and maximum value
% 1 - By validity matrix
6-23
6 Simscape Foundation Domains
variables
p = {0.1, 'MPa'}; % Pressure
T = {300, 'K' }; % Temperature
end
variables (Balancing=true)
mdot = {0, 'kg/s'}; % Mass flow rate
Phi = {0, 'kW' }; % Energy flow rate
end
end
It also contains lookup tables, declared as variable-sized domain parameters, for the following liquid
thermodynamic properties:
• Density
• Specific internal energy
• Kinematic viscosity
• Specific heat at constant pressure
• Thermal conductivity
• Isothermal bulk modulus
• Isobaric thermal expansion coefficient
• Dynamic viscosity
6-24
Thermal Liquid Domain
• Prandtl number
These variable-sized parameter declarations propagate to the components connected to the Thermal
Liquid domain, and therefore you can use them in the tablelookup function in the component
equations. In particular, the thermal liquid blocks in the Foundation library use these lookup tables
for interpolation purposes.
To refer to this domain in your custom component declarations, use the following syntax:
foundation.thermal_liquid.thermal_liquid
See Also
More About
• “Foundation Domain Types and Directory Structure” on page 6-2
6-25
6 Simscape Foundation Domains
open([matlabroot '/toolbox/physmod/simscape/library/m/+foundation/+two_phase_fluid/two_phase_flui
Abbreviated two-phase fluid domain declaration is shown below, with intermediate lookup table
values omitted for readability.
domain two_phase_fluid
% Two-Phase Fluid Domain
parameters
p_min = {1e-3, 'MPa' }; % Minimum valid pressure
p_max = {95, 'MPa' }; % Maximum valid pressure
u_min = {0, 'kJ/kg'}; % Minimum valid specific internal energy
u_max = {4000, 'kJ/kg'}; % Maximum valid specific internal energy
p_crit = {22.0640, 'MPa' }; % Critical pressure
p_atm = {0.101325, 'MPa' }; % Atmospheric pressure
q_rev = {0.01, 'Pa' }; % Dynamic pressure threshold for flow reversal
transition_range = {0.1, '1'}; % Range in vapor quality for smoothing of density partial derivatives
unorm_TLU = {[
-1
-0.958333333333333
...
1.95833333333333
2
], '1'}; % Normalized internal energy vector
unorm_liq_TLU = {[
-1
-0.958333333333333
...
-0.0416666666666666
0
], '1'}; % Normalized liquid internal energy vector
unorm_vap_TLU = {[
1
1.04166666666667
...
1.95833333333333
2
], '1'}; % Normalized vapor internal energy vector
unorm_mix_TLU = {[
0
0.0204081632653061
...
0.979591836734694
1
], '1'}; % Normalized mixture internal energy vector
p_TLU = {[
0.00100000000000000
...
95.0000000000000
], 'MPa' }; % Pressure vector
v_TLU = {[
0.00100020732544948 ... 0.00646806895821810
], 'm^3/kg'}; % Specific volume table
s_TLU = {[
-7.05045840376749e-13 ... 6.81117017439253
], 'kJ/kg/K'}; % Specific entropy table
T_TLU = {[
273.159998291077 ... 1348.81511704704
6-26
Two-Phase Fluid Domain
nu_TLU = {[
1.79172848157620 ... 0.361552941837863
], 'mm^2/s'}; % Kinematic viscosity table
k_TLU = {[
0.555598831086800 ... 0.250538481070411
], 'W/(m*K)'}; % Thermal conductivity table
Pr_TLU = {[
13.6057970740934 ... 0.671580102714643
], '1' }; % Prandtl number table
DrhoDp_liq_TLU = {[
0.509755264394891 ... 1.80807388692342
], 'kg/m^3/MPa'}; % Partial derivative of liquid density with pressure
% at constant specific internal energy table
DrhoDp_vap_TLU = {[
7.36831747174794 ... 1.45923555583730
], 'kg/m^3/MPa'}; % Partial derivative of vapor density with pressure
% at constant specific internal energy table
DrhoDp_mix_TLU = {[
1350.39031864440 ... 1.80807388692342
], 'kg/m^3/MPa'}; % Partial derivative of mixture density with pressure
% at constant specific internal energy table
DrhoDu_liq_TLU = {[
0.0160937306771423 ... -0.350392782066966
], 'kg^2/m^3/kJ'}; % Partial derivative of liquid density with specific internal energy
% at constant pressure table
DrhoDu_vap_TLU = {[
-1.79894990819782e-05 ... -0.0610611856834271
], 'kg^2/m^3/kJ'}; % Partial derivative of vapor density with specific internal energy
% at constant pressure table
DrhoDu_mix_TLU = {[
-0.0137995431136761 ... -0.350392782066966
], 'kg^2/m^3/kJ'}; % Partial derivative of mixture density with specific internal energy
% at constant pressure table
u_sat_liq_TLU = {[
29.2976389515495
...
2242.74587564859
], 'kJ/kg'}; % Saturated liquid specific internal energy vector
u_sat_vap_TLU = {[
2384.48887142334
...
2242.74587564859
], 'kJ/kg'}; % Saturated vapor specific internal energy vector
end
variables
p = { 0.1, 'MPa' }; % Pressure
u = { 1500, 'kJ/kg' }; % Specific internal energy
end
variables(Balancing = true)
mdot = { 0, 'kg/s' }; % Mass flow rate
Phi = { 0, 'kW' }; % Energy flow rate
end
end
6-27
6 Simscape Foundation Domains
It also contains lookup table data, declared as domain parameters, for the following fluid properties:
These parameter declarations propagate to the components connected to the Two-Phase Fluid
domain, and therefore you can use them in the tablelookup function in the component equations.
In particular, the two-phase fluid blocks in the Foundation library use these lookup tables for
interpolation purposes.
To refer to this domain in your custom component declarations, use the following syntax:
foundation.two_phase_fluid.two_phase_fluid
See Also
More About
• “Foundation Domain Types and Directory Structure” on page 6-2
6-28
Pneumatic Domain
Pneumatic Domain
Note As of R2016b, the gas domain on page 6-6 replaces the pneumatic domain as the recommended
way of modeling pneumatic systems. The pneumatic domain definition is still provided with the
software, for compatibility reasons. However, it can be removed in a future release.
parameters
gam = { 1.4, '1' }; % Ratio of specific heats
c_p = { 1005 , 'J/kg/K' }; % Specific heat at constant pressure
c_v = { 717.86 , 'J/kg/K' }; % Specific heat at constant volume
R = { 287.05, 'J/kg/K' }; % Specific gas constant
viscosity = { 18.21e-6, 'Pa*s' }; % Viscosity
Pa = { 101325, 'Pa' }; % Ambient pressure
Ta = { 293.15, 'K' }; % Ambient temperature
end
variables
p = { 0 , 'Pa' };
T = { 0 , 'K' };
end
variables(Balancing = true)
G = { 0 , 'kg/s' };
Q = { 0 , 'J/s' };
end
end
These parameter values correspond to gas properties for dry air and ambient conditions of 101325 Pa
and 20 degrees Celsius.
To refer to this domain in your custom component declarations, use the following syntax:
foundation.pneumatic.pneumatic
6-29
6 Simscape Foundation Domains
See Also
More About
• “Foundation Domain Types and Directory Structure” on page 6-2
6-30