First Example
This guide provides a practical introduction to SysIDE Automator through a hands-on example.
You’ll learn how to load and validate SysML v2 models, extract and analyze model elements, and modify models programmatically.
Getting Started
Let’s begin by creating a simple SysML v2 model that we’ll use throughout this example. This model represents a basic automobile structure with electrical and mechanical components.
Create a new file named example_model.sysml
and paste the following model:
package 'Part Tree Example' {
part def Electrical;
part def Mechanical;
part Automobile {
part 'Drive Train' {
part Battery : Electrical;
part Motor : Electrical;
}
part Chassis {
part Suspension : Mechanical;
part Body : Mechanical;
}
}
}
Model Validation
Before working with the model, it’s important to validate it. To validate your model, open a terminal in the directory containing your model and run:
python -m syside check example_model.sysml
This command will check for any semantic errors or warnings in your model. After running, you should see the following output:
Checks passed!
Note
More about interactive SysIDE Automator usage can be found in the Interactive Version section.
Basic Model Analysis
Let’s create a Python script to analyze our model. We’ll start by creating a simple script that prints all elements in a tree-like structure.
Create a new file right next to the example_model.sysml
file named
analyze_model.py
with the following code:
import syside
# Load the model - this is the first step for any SysIDE Automator script
(model, diagnostics) = syside.load_model(["example_model.sysml"])
def walk_ownership_tree(element: syside.Element, level: int = 0) -> None:
"""Recursively print all elements in the model."""
if element.name is not None:
print(" " * level, element.name)
else:
print(" " * level, "anonymous element")
# Recursive walk through child elements
for child in element.owned_elements.collect():
walk_ownership_tree(child, level + 1)
# Process each document in the model
for document_resource in model.documents:
with document_resource.lock() as document:
print("Walking the ownership tree printing all elements:")
walk_ownership_tree(document.root_node)
Run the script by running the following command in the terminal:
python analyze_model.py
When you run this script, you’ll see the following output:
Walking the ownership tree printing all elements:
anonymous element
Part Tree Example
Electrical
Mechanical
Automobile
Drive Train
Battery
Motor
Chassis
Suspension
Body
Working with Part Types
Our model defines two types of parts: Electrical
and Mechanical
. Let’s enhance
our script to identify and display parts by their type.
Add the following function to your script right after the walk_ownership_tree
function:
def show_parts_of_type(model: syside.Model, part_type: str) -> None:
"""Display all parts of a specific type in the model."""
for part in model.nodes(syside.PartUsage):
for element in part.heritage.elements:
if element.try_cast(syside.PartDefinition):
if element.declared_name == part_type:
print("- ", part.name)
print("\nElectrical parts in the model:")
show_parts_of_type(model, "Electrical")
print("\nMechanical parts in the model:")
show_parts_of_type(model, "Mechanical")
This will output:
Electrical parts in the model:
- Battery
- Motor
Mechanical parts in the model:
- Suspension
- Body
Enhancing the Model
Let’s make our model more realistic by adding a mass requirement. We’ll modify the model to include mass attributes for each part and add a requirement that the total mass must not exceed 500 kg.
Update your example_model.sysml
file with this enhanced version:
package 'Part Tree Example' {
private import ScalarValues;
part def Electrical {
attribute Mass;
}
part def Mechanical {
attribute Mass;
}
part Automobile {
part 'Drive Train' {
part Battery : Electrical {
attribute redefines Mass = 150;
}
part Motor : Electrical {
attribute redefines Mass = 200;
}
attribute DriveTrainMass = Battery.Mass + Motor.Mass;
}
part Chassis {
part Suspension : Mechanical {
attribute redefines Mass = 100;
}
part Body : Mechanical {
attribute redefines Mass = 150;
}
attribute ChassisMass = Suspension.Mass + Body.Mass;
}
attribute TotalMass = 'Drive Train'.DriveTrainMass + 'Chassis'.ChassisMass;
}
requirement def MassLimitation {
doc /* Total mass of the Automobile must not
exceed 500 */
attribute MassActual = Automobile.TotalMass;
attribute MassLimit = 500;
}
}
Validating Requirements
Now let’s create a script to validate our mass requirement. Add the following code to your Python script:
def show_part_decomposition(
element: syside.Element, part_level: int = 0
) -> None:
"""Display a clean part decomposition tree."""
if element.try_cast(syside.PartUsage):
print(" " * part_level, element.name)
new_part_level = part_level + 1
else:
new_part_level = part_level
for child in element.owned_elements.collect():
show_part_decomposition(child, new_part_level)
# Find total mass and mass requirement:
for attribute in model.nodes(syside.AttributeUsage):
if attribute.name == "MassActual":
assert attribute.feature_value_expression is not None
evaluation = syside.Compiler().evaluate(
attribute.feature_value_expression
)
if evaluation[1].fatal:
print(f"Error evaluating {attribute.name}")
else:
total_mass = evaluation[0]
if attribute.name == "MassLimit":
assert attribute.feature_value_expression is not None
evaluation = syside.Compiler().evaluate(
attribute.feature_value_expression
)
if evaluation[1].fatal:
print(f"Error evaluating {attribute.name}")
else:
mass_limit = evaluation[0]
# Display results
print("\nPart decomposition:")
for doc in model.user_docs:
with doc.lock() as locked:
show_part_decomposition(locked.root_node)
print(f"\nTotal mass: {total_mass} kg")
if isinstance(total_mass, (int, float)) and isinstance(
mass_limit, (int, float)
):
if total_mass <= mass_limit:
print("✓ Mass requirement met")
else:
print("✗ Mass requirement not met")
else:
print("✗ Cannot compare mass values - invalid types")
When you run this script, you’ll see:
Part decomposition:
Automobile
Drive Train
Battery
Motor
Chassis
Suspension
Body
Total mass: 600 kg
✗ Mass requirement not met
Summary
In this example, we’ve learned how to:
Create and validate a SysML v2 model
Load and analyze models using SysIDE Automator
Extract and display model elements
Work with part types and hierarchies
Add attributes and requirements to models
Validate requirements programmatically
The example demonstrates that our automobile design exceeds the mass requirement by 100 kg. To meet the requirement, you would need to reduce the mass of some components or redesign the system.
Next Steps
Try modifying the mass values to meet the requirement
Check out the Examples Collection section for more Automator applications