-
Notifications
You must be signed in to change notification settings - Fork 0
Using expressions
Expressions are a really important part of the Physics language. They are used almost everywhere and are what is making the language convenient to use.
This page shows the expressions available in the language.
Since Physics inherit from kernelF, all the expressions available in kernelF are available in Physics. You can find some examples in their reference paper at http://voelter.de/data/pub/kernelf-reference.pdf.
The most common expressions to know are the binary operators : plus +, minus -, divide /, multiply * and logical operators : and &&, or ||, equals ==, less than <=.
You can use condition expressions such as if 3 * 5 < 10 then 100 else 0. The condition must be some boolean expression (logical operation, true, false...) and both alternative should have the same type.
In some cases you might want to store some value somewhere, and use multiple lines with intermediate results. That's what value and block expressions are for.
- A value expression allow to define an intermediate result and can be referenced in subsequent expressions
- A block expression contains multiple expressions, the last one will become the value of the block
For example, the block below will have a value of 8.
{
val a = 3
val b = 5
b + a
}Here is another example of a block expression inside a cartesian coordinates definition.
cartesian(x = {
val distance = [50 km]
distance / [5 h]
}, y = [3 mps], z = [4 mps])Some mathematical expressions are also available from kernelF, such as cos, sin or a sum expression.
In addition to kernelF mathematical expressions, two expressions were defined in the Physics language
- n-root : allow to compute the root of a number (not only square root but cube root and more)
- exp : allow to computer the exponential function, exp(1) will equals e.
In the physics language, you may not only use plain numbers, you can define their dimensions (such as length, time, speed...).
You can specify a unit on regular numbers anywhere in the simulation by inserting its name on the right. Typing 5 m will insert a unit expression with a value of 5 (m) and with "length" as dimension.
To see the list of units available, hit <space> on the right of a number, then press <ctrl> + <space> to display the possibilities.
When the dimensions are compatible, you can use any kind of addition operations, like [5 m] + [5 km].
You may also combine dimensions with multiplying operations, such as [3 mps] + [4 m] / [1 h] + [1 km] * [1 h^-1]
By default, the dimension of a number propagate to its surrounding expression ([3 mps] * 5 / 1 will have a dimension of speed). In some case you might want to use the actual value of the expression without any dimensions.
For example, some math expressions such as sin, asin might not support dimensions (so angles do not fit inside of those). In such case you may use a use as operation (UseUnitExpressionAs) on your numerical values, which allows to remove the dimension and specify the unit of the target value (which wont have dimensions/units anymore).
To add such expression you need to insert a dot on the right of your expression, then type "use as" (+ <ctrl> + <space>) and specify the unit.
[3 m].useAs(km) -> 0.003
[3 m].useAs(m) -> 3
([3 cm] + [5 mm]).useAs(m) -> 0.035
sin([3 deg].useAs(rad)) * [3 m] -> 3 sin(3 * (2 * pi) / 360)Vectors, or coordinates, are used in a lot of places (such as position or velocity definition). You have many way to define them.
Cartesian coordinates are the easiest way to define a vector. You need to specify 3 expressions, one for each 3D coordinate (x, y and z). The types / dimension of the components must match (you cannot set [5 m] to x and [1 mps] to y).
To insert cartesian coordinates, type cartesian coordinates and hit <ctrl> + <space> (you may press <ctrl> + <space> before finishing typing).
Spherical coordinates allow to define a vector from a distance and 2 angles (https://en.wikipedia.org/wiki/Spherical_coordinate_system), whereas cylindrical coordinates use two distances and one angle (https://en.wikipedia.org/wiki/Cylindrical_coordinate_system).
The angles should have the angle dimension (using units such as rad or deg), the distances may be any kind of value (any or no dimension) and will define the dimension used within the vector.
Directional coordinates are the easiest way to make vectors using existing objects or points. You need to provide both an axis (source + destination) and a length along this axis, and you get a vector following the axis with the given length.
directional(
length = [5 m]
axis = self -> myOtherObject
)
By default, the source parameter (on the left of the arrow ->) is optional. The default value then depends on the context :
- If the vector is defined in a property of an object, in an abstract object or force, the source will be the object position (you will see either
selfor the name of your object) - If the vector is defined as position of an object (or is contained in the position expression), or the vector is used outside of above contexts (camera position for instance), the source value will be a zero vector (
[0, 0, 0]).
Relative coordinates provide a way to make a vector relative to an object. To make a vector relative, type "relative" on the right of this vector (hit <ctrl> + <space> if nothing happens).
cartesian(x = [3 m], y = [3 m], z = 0) relative to myObject
[not working yet] You might decide to use the orientation / rotation of the object, in which case you can type oriented on the right of relative to, or use the contextual button when focusing the relative coordinates.
When referencing or using a vector in an expression, you may want to access so properties of this vector (such as length, some coordinates...). You may use those using a dot . operation on the right of your vector expression.
You can access various scalar properties of any vector :
-
x,y,z: cartesian coordinates component -
thetha,phi: spherical coordinates angles -
length: size of the vector
You may also get a transformed version of your vector :
-
opposite: opposite vector (vector with components multiplied by -1) -
resize to <length>: vector of same axis but with the given length (if negative, the direction will be the opposite)
{
val position = cartesian(x = 0, y = [3 m], z = 0)
val someAngle = position.theta + spherical(r = [3 m], theta = 0, phi = [5 rad]).phi
val length = (position * 2).length
position.resize to [3 km].length
}Within the definition of you object or some other place in your code, you can acces two specific expression related to your object :
-
self: it refers to the current object, if used in abstract force for example, this will be the object the force is applied to -
current world: it refers to the current world (the world definition containing the current object)
Those objects might also be accessed through their name (in the simulation file you can type the name of your world, in an object your can type both the name of your world or object).
In a world definition, you may also target other entities (inclusions and objects) of your world by typing their name directly.
These expression can be used on any world object (such as current world) by using a dot . on the right of your object. The resulting expression can also use expressions with the dot according to its type.
current world.<expression>.<other expression>
You can access objects defined in the world using a . and the name of the object right after. This whole expression will be an object or a world (depending on whether you refer to an object definition or a world inclusion), and can be reused wil expressions available for object or world.
current world.myWorldInclusion.myObject -> object
current world.myWorldInclusion -> world
current world.someObject -> objectWith worlds, you may use various target expression using the . operation.
-
position: initial position of the world (even after simulation start) -
velocity: initial velocity of the world (even after simulation start) -
mass: total mass of all the objects (including nested worlds) -
mass center: center of mass of the world, a sum of all positions multiplied by object masses and divided by world total mass
Physical object expressions works the same as world expression, but there is more object specific properties available.
With worlds, you may use various target expression using the . operation.
-
position: real time position of the object -
velocity: real time velocity of the object -
mass: mass of the object (as defined inmass) -
rotation speed: rotation speed of the object -
distance with <position>: distance of the object with another object or position vector
You may also access styles of your object using . operations. These expressions can be used in your simulation definition to override them or display them as metrics.
You can find the list of styles available in the basic concepts page.
current world.someObject.sphere-radiusSome values are available during the simulation and can be useful for defining realistic simulations.
You can use a time expression to use the simulation time within your expressions. This value has a dimension of time so you can compare it or use it with dimensions.
Here is an example of the time expression used to have the mean speed on an object moving straight for the origin as a metric (simulation definition).
Mean Speed = (current world.myObject.position / time).lengthIn some cases during the simulation you may want to access all the other objects at once. This is what allObjects expression is for.
It is an array of all the objects in the simulation (without taking worlds in consideration) and can be used with kernelF collection operators (map, where, findFirst). You can find more details on these operations in the kernelF documentation mentionned above.