Mechanism to structure Model and SysML Files

Hello,

What’s the best/suggested approach to structure a model? I’m attempting to structure the model with packages according to the logical architecture of the system. Simultaneously I’m attempting to have every package in a separate .sysml file (for easier collaboration and version control).

How can I achieve this with nested packages? My first thought was the following, but I am not sure:

A.sysml:
package A {
public import B;
}

B.sysml:
package B {
part def PartB;
}

C.sysml:
package C {
part def PartC {
part partB : A::B::PartB;
}
}

Thanks!

Tom

Hi Tom,

There are many good approaches how to model structure (as well as behavior and other things for that matter), and the best approach really depends on your situation. We do however recommend splitting model up into standalone files for different subsystems/components to enable modularity, reusability of design assets and for more effective version control and team collaboration (easier to see which design aspects are modified once they are in separate files.

Here is a few rule of thumbs that could help you with modeling large structure in SysML

  1. Keep the sysml file name consistent with the top level package name.
  2. Have only 1 top (root-level) package per file, you can have further nested packages inside.
  3. Have only definitions (i.e. context / blueprints for what you modelling) inside packages. Avoid having usages at package level, because semantics are very different for package level usages.
  4. Each definition should ideally have 1 level depth usages which are defined by other definitions (which could be imported from other packages).
  5. Definitions should not have any other owned definitions (semantically it does not matter where definition is, only usages inside definition have semantic feature membership meaning)

Having this in mind, my recommendation would be have 1 sysml file for top level system, then separate files for subsystems, and separate (or combined file/package if they are small) for components. Then folder and file structure can look something like this:

Folder/file structure:

ExampleTopLevel.sysml

package ExampleTopLevel {
    private import ExampleSubsystemA::*;
    private import ExampleSubsystemB::*;

    part def ExampleSystemDesign {
        part subsystemA : SubsystemA;
        part subsystemB : SubsystemB;
    }
}

ExampleSubsystemA.sysml (note, you do not necessarily need to import other packages, you can use full qualified name ExampleComponentB::ComponentB)

package ExampleSubsystemA {
    private import ExampleComponentA::*;
    
    part def SubsystemA {
        part componentA : ComponentA;
        part componentB : ExampleComponentB::ComponentB;
    }
}

ExampleSubsystemB.sysml

package ExampleSubsystemB {

    private import ExampleComponentC::*;
    private import ExampleComponentD::*;

    part def SubsystemB {
        part componentC : ComponentC;
        part componentD : ComponentD;
    }
}

And components (all the same A/B/C/D in this example):

package ExampleComponentA {
    part def ComponentA {
    }
}

Note, I used the folder structure here to group designs by their hierarchy level. That may not be optimal for larger teams/designs, as you may want to use those groups for each individual subsystem, and perhaps even have multiple levels of internal subsystems with variable depth for each. In that case the better approach to have folders ExampleSubsytemA, ExampleSubsystemB, etc.. Then the component design files could be stored under relevant subsystem folders, or somewhere else altogether. As I mentioned at the start, it all depends on your preferences and situation.

Hope this helps, let us know if you have other questions on this or related topics.

Kind regards
Kestutis Jankevicius

This is something I use as a pattern:

I’ve heard this serveral times, but I think that in my final project model (e.g. the car I’m about to model) I must have at least one usage in my project file outside of any def: the car. Because I will want to run simulations and analysis on it, so I will need at least one prototypical instance. Or is this typically handled in another way?

Unfortunately, usages are not instances, they are meant to capture role in a context. Basically it is a relationship for using a definition inside another definition. When specified in package, the owner becomes “Anything” which means everything now can have this feature: suddenly all contexts (i.e. all definitions) can have that feature. Also package level usages have different [0..*] default multiplicity. On the other hand when inside the definition or another usage, the default multiplicity for part, item, port usages is [1] unless usage is redefining or subsetting another feature (then default multiplicity is inherited from redefined / subsetted feature).

So in your case you would need a “wrapper” definition that provides context for what you design (“car”). It could be “project”, it could be “car in environment”, “car simulation system”, etc, and it could be also part def or other more general structural sysml element used, such as occurrence def.

To learn more about this and similar topics, I encourage you to do our Advent of SysMLv2 course that is freely available on Sensmetry blog, YouTube channel and GitHub, and use as reference The SysML v2 Book which published by @VinceMolnar and Tim Weilkiens.

For doing analysis on a model you may want to create an analysis context (either a part def, or part) where you feature your System-of-Interest in reference and one or more analysis cases (definitions and/or usages depending whether your analysis is a one shot run or you plan to do several analysis over a same analysis definition).
If you want to keep a record of the analysis, you may want to create a git branch for the analysis.
You can use the analysis case as a gateway between the analysis tool you may be using and the system model. I used this approach in this pattern: MBSE Recursive Architecture Wave Pattern 1.1.2 · Sysand

Hi everyone,

I realize it’s an old thread, but I wanted to reflect on the “need to have one usage to simulate” idea.

In fact, (proper) simulators cannot simulate a usage because a usage is a relationship between a context and a value, and in this case, there is no context. Of course, the simulator can create an empty Anything as the context, but it’s pointless and basically a workaround to handle popular demand.

A definition is a blueprint for building, manufacturing, instantiating, or simulating. You give it to the builder/factory/solver/simulator, and it creates a legal instance. That instance may have to use other instances as “ingredients” - these are captured by the usages.

So, whenever you want to simulate something, it’s a clear sign you need a definition. That will define what to simulate.

On @Hormo’s point: yes, it is also a good idea to create a case definition (typically an analysis or verification case, but a case def is also perfectly fine) to define your simulation. The system will then be a usage in the context of the simulation, and the simulator will actually simulate the case. This makes sense when you also have an environment model, want to impose constraints on the simulation, or just configure the simulator. Notice, however, that you still simulate a definition, it’s just not the system but the case.

I hope this helps.