Hi,
How would you go about using (accessing) units in python?
If I have a model like this:
package MechanicalObjectExample {
abstract item def MechanicalObject {
attribute mass :> ISQ::mass;
assert constraint {
(mass > 0) and (shape != null)
}
}
abstract item mechanicalObjects[*] : MechanicalObject;
metadata def <mec> MechanicalObjectMetadata :> Metaobjects::SemanticMetadata {
:>> baseType = mechanicalObjects meta SysML::Usage;
}
part def DroneSystem {
part def Drone {
#mec part battery {
attribute :>> mass = 2.5 [SI::kg];
item shape[1] : ShapeItems::Box :>> shape {
attribute :>> length = 10 [SI::cm];
attribute :>> width = 4 [SI::cm];
attribute :>> height = 3 [SI::cm];
}
}
#mec part propulsionUnit {
attribute :>> mass = 0.5 [SI::kg];
item shape[1] : ShapeItems::Cylinder :>> shape;
}
}
}
}
Can you provide a code snippet showing how you access and use the units so I can do calculations in python space?
Thanks,
Robert
Hi,
quantity expressions are just regular operator expressions, typically of the form of <expr> [<unit ref>]. The left-hand side expr is the first argument, right-hand side unit expression - the second argument. In a valid model, this is accessible via Python sequence unpacking expr, units = op_expr.arguments.collect().
The simplest case is when unit expression is just a reference - the unit is a referent of FeatureReferenceExpression.
Thanks @Daumantas ,
I have reduced the model and made some example code.
I still don’t see how I can get to the units themselves.
thissrc="""
package MechanicalObjectExample {
private import ScalarValues::*;
part def DroneSystem {
part def Drone {
part battery {
/*attribute mass:ISQ::MassValue = 2.5 [SI::kg];*/
attribute m:Real=2.5;
}
part propulsionUnit {
attribute mass:ISQ::MassValue = 0.5 [SI::kg];
}
}
}
}"""
model, diagnostics = syside.load_model(sysml_source=thissrc)
def find_attribute_values(element: syside.Element, level: int = 0) -> None:
if element.try_cast(syside.AttributeUsage):
#if element.name is not None: print(" " * level, element.name)
attr = element.cast(syside.AttributeUsage)
expression = next(iter(attr.owned_elements), None)
if expression is not None and isinstance(expression, syside.OperatorExpression):
expression, units = expression.arguments.collect()
print (f"units = {units}")
if expression is not None and isinstance(expression, syside.LiteralRational):
print(f"{attr.declared_name}: {expression.value}")
for child in element.owned_elements.collect():
find_attribute_values(child, level + 1)
for document_resource in model.documents:
with document_resource.lock() as document:
find_attribute_values(document.root_node)
This gives me:
m: 2.5
units = MechanicalObjectExample::DroneSystem::Drone::propulsionUnit::mass::(anonymous OperatorExpression)::(anonymous Feature)::(anonymous FeatureReferenceExpression)
mass: 0.5
How can I get to “[SI::kg]”?
Thanks,
Robert
How can I get to “[SI::kg]”?
That would be units.referent, or units.cast(syside.FeatureReferenceExpression).referent for type-checked code.
v0.8.2 added experimental_quantities option to Compiler, see Compiler.evaluate