Applying Best Practices for Building Large Simulink Models
By Brad Hieb and Erick Saldana Sanvicente, MathWorks
As systems grow in scale and complexity, engineering teams encounter a set of entirely new challenges that don’t exist at smaller scales.
Almost always, a significant increase in scale requires a shift in approach—not just in scope but in kind. This principle also applies to Simulink® models when working with Model-Based Design. When best practices are not followed, a host of issues begin to emerge when transitioning from simple proof-of-concept models to large-scale models with hundreds of thousands of blocks, including problems with poor model architecture, data management, interfaces, file management, and simulation performance. The building blocks of these large models may be small, often developed by different individuals, teams, and even departments. When there is standardization and best practices are followed, these models can be smoothly grown to scale.
This article describes a set of best practices for managing the challenges commonly encountered when working with large, complex models in Simulink. Because this topic itself is quite broad, the goal here is not to provide detailed, prescriptive guidance, but rather to present the basics of each best practice along with links to additional resources that can be explored for a deeper understanding of how it can be applied.
Use Model Reference for Model Componentization
When we work with customers, it is not uncommon to see large models that lack meaningful componentization. Teams start off with a simple model to test ideas out; over time new elements or features are added, and all the work is done in a single, monolithic model file that soon becomes unwieldy.
In Simulink, there are several ways to componentize large models, and the best approach will depend on the specific use case under consideration. For example, a team that simply wants to visually organize a group of blocks or components may opt for an in-model virtual subsystem. For a different team that wants to create widely used utilities that change infrequently, a linked subsystem (or library) is a better option. If the goal is to develop or simulate a component as a standalone model, then model reference is the best approach.
Model reference is also the key to componentization for large-scale models. One reason for this is that model reference in Simulink enables teams to develop components in parallel as independent models. Each component is fully functional and simulatable, as well as saved in its own SLX file so each team can work independently without interfering with another team’s work—which is all but impossible to do when the entire design is captured in a single file. Just as important, these independent reference models can be placed inside larger models for easy integration (Figure 1). This architecture can reduce build times using cached instances of reference models and incremental builds. It also enables the use of accelerator and rapid accelerator modes, which are covered in more detail below in the section on performance.
Scale Up Data Management with Data Dictionaries
Let’s reconsider the same scenario that led to problems with componentization: A team starts with a simple model as an early proof of concept and then continues to elaborate upon it over time. For a simple model, many engineers will store variables, parameters, and other data in the base workspace. This approach works fine for informal workflows, quick parameter tuning, rapid prototyping, single-developer projects, or use cases that require universal visibility of parameters. As models increase in scope and complexity, however, relying on the base workspace for data management has some drawbacks. For example, because the base workspace is cleared every time an engineer closes their session, it must be manually saved either in MATLAB® code (.m) or a MATLAB file (.mat).
Data dictionaries are better suited than the base workspace for managing data on projects that involve large models, distributed development, or scoped data. There are a few reasons for this (see Figure 2). The first is data persistence. Data is saved in a specific file format in data dictionary (.sldd) files, enabling teams to define, manage, and update data separately from the model and the base workspace. Second, teams can partition data into multiple dictionaries to further improve data organization. Third, data dictionaries work well in change-tracking workflows, in which teams can view what changes were made, when they were made, and who made them—and even revert to earlier versions when needed.
It’s important to note here that the choice between using the base workspace and data dictionaries is not all-or-nothing. The two approaches can coexist, so a team can gradually migrate from the base workspace into one or more data dictionaries over time.
Simplify Interfaces with Buses
When connecting subsystems in a componentized, hierarchical model, it may initially seem that the most straightforward approach is to use a separate signal line for each element that is passed from one component to another. Of course, this works for simple interfaces, but the approach can quickly result in models that are more complex, cluttered, and difficult to manage than necessary.
In Simulink, buses can simplify interfaces and reduce clutter by representing a set of signals (or elements) with a single line, much like several wires bundled together. The value of this is easy to see with a simple example. Consider a fault detection component for identifying anomalous conditions in a battery system. The component has 11 different inputs, including maximum and minimum cell voltage, maximum and minimum cell temperature, contactor states, pack voltage and current, and current limits. While it is certainly possible to create the component with 11 individual input ports, it is cleaner to separate the inputs into logical groups and use a bus for each group. For example, because the cell voltage and cell temperature signals all originate from the same component and are all related, it makes sense to group them into a single four-element bus (Figure 3). Clearly, this is a relatively trivial example, but it illustrates how buses can be used to simplify not only component interfaces but, more broadly, complex models.
Improve File Management with Projects
One side effect of following the best practices outlined thus far is an increase in the number of files that must be managed. When the entire design is in a single model, the set of files a team has to manage is relatively small, but it can quickly grow when componentization and data dictionaries are actively employed. Without a file management strategy, this proliferation of files can become problematic.
When working in Simulink, teams can use projects to help automate file management activities, so they have more time to spend on modeling, simulation, and other high-value activities. For example, when setting up a project, the team will specify the folders in the project path. These folders are added to the search path when the project is opened (and removed when the project is closed) ensuring that all users of the project have access to the files within them. The team can also specify startup files that automate setting up the environment for your project and shutdown files that clean up the environment by undoing setup steps, for example. In addition, projects can be configured to open frequently used files at launch and create shortcuts for commonly used tasks.
Projects can also help teams avoid common mistakes. For example, with a complex model hierarchy, it is not unusual for two model files with the same name to exist in different directories. When using a project, an engineer will see a warning when such shadowed files are detected. Also, engineers are prompted to save any unsaved changes when a project is closed, helping to avoid lost work.
Finally, projects help streamline source control, with common operations such as refresh, commit, push, pull, fetch, and other common operations accessible directly from the user interface (Figure 4).
Optimize Simulation Performance
The best practices we have covered so far have been focused primarily on the structure of large models and their associated data and files. In conversations with customers who have implemented these best practices, we are often asked about improving simulation performance: “Now that we have a better way to build large models, how can we get them to simulate faster?”
Several tools are available for improving simulation performance. As a first step, we recommend Performance Advisor, which runs a series of checks to identify configuration settings that may be slowing simulations. Next, for any model that includes initialization MATLAB code (in a callback, for example), it is a good idea to run the MATLAB Profiler app to identify where MATLAB is spending the most time. Simulink Profiler assesses model execution time and identifies issues that may be contributing to poor simulation performance. Finally, for teams using a variable-step solver, we recommend running Solver Profiler, which analyzes solver behavior, identifies potential issues (such as solver resets or exceptionally small time steps), and provides recommendations for resolving them. Guidance on each of these tools, including how and when to use them, is available in the Troubleshoot and Speed Up Simulation Performance guide (see table).
Teams that have componentized their large model can speed simulations using accelerator mode or rapid accelerator mode, which replace the interpreted code normally used in Simulink simulations with generated code. During model initialization, Simulink checks a cache for any components for which code has already been generated. This incremental build process greatly reduces initialization time for large models with many components, because only those components that have changed since the last simulation will need to be rebuilt (and added to the cache).
Another way to reduce initialization time—specifically when simulating a model iteratively—is with fast restart. When a team performs multiple simulation runs without making any structural changes to the model, fast restart can speed up the process by performing the simulations without compiling the model and terminating the simulation each time. Instead, upon the first simulation the model is compiled and initialized, and then a snapshot of the model operating point is captured for each subsequent simulation (Figure 5).
In conclusion, as engineering teams navigate the complexities of scaling Simulink models, adhering to best practices becomes essential. This article has outlined essential strategies for model componentization, data management, and performance optimization, emphasizing the importance of a structured approach to model development. By leveraging tools such as Performance Advisor, MATLAB Profiler, and Solver Profiler, teams can enhance simulation performance and improve productivity. These practices ensure that large-scale models remain manageable, efficient, and adaptable. As the landscape of Model-Based Design continues to evolve, these guidelines will help teams to build robust models that meet the demands of increasingly complex engineering challenges. For further exploration, readers are encouraged to engage with the additional resources and training opportunities highlighted throughout this paper.
The content of this article is based on a talk titled “Best Practices for Building Large Models from Components to Complex Systems” (see “Learn More” for this talk, along with more webinars and training), which we presented at the MathWorks Automotive Conference. As we noted at the outset, this is a vast topic that cannot be exhaustively covered in a single article or talk.
Published 2025