# Array Functions¶

There are a great many functions in Modelica that are related to arrays. In this section, we’ll go through different categories of functions and describe how they are used.

## Array Construction Functions¶

We already talked about Array Construction. We saw the different syntactic constructs that can be used to build vectors and matrices. Furthermore, we saw how matrices can be built from other matrices. There are several functions in Modelica that can be used for constructing vectors, matrices and higher-dimension arrays as both an alternative or complement to those previous presented.

`fill`

¶

The `fill`

function is used to create an array where each element in
the array has the same value. The arguments for `fill`

are:

```
fill(v, d1, d2, ..., dN)
```

where `v`

is the value to be given to each element in the array and
the remaining arguments are the sizes of each dimension. The elements
in the resulting array will have the same type as `v`

. So, to fill
a 5x7 array of reals with the value `1.7`

, we could use the
following:

```
parameter Real x[5,7] = fill(1.7, 5, 7);
```

This would result in a matrix filled as follows:

`zeros`

¶

When working with arrays, a common use case is to create an array that
contains only zero elements. This is essentially the same
functionality as the `fill`

function, but since the value is known
it is only necessary to specify the sizes. Using `zeros`

we can
initialize an array as follows:

```
parameter Real y[2,3,5] = zeros(2, 3, 5);
```

`ones`

¶

The `ones`

function is identical to the `zeros`

function except
that every element in the resulting array has the value \(1\).
So, for example:

```
parameter Real z[3,5] = ones(3, 5);
```

This would result in a matrix filled as follows:

`identity`

¶

Another common need is to easily build an identity matrix, one whose
diagonal elements are all \(1\) while all other elements are
\(0\). This can be done very easily with the `identity`

. The
identity function takes a single integer argument. This argument
determines the number of rows and columns in the resulting matrix.
So, invoking `identity`

as:

```
identity(5);
```

would produce the following matrix:

`diagonal`

¶

The `diagonal`

function is used to create a matrix where all
non-diagonal elements are \(0\). The only argument to diagonal is
an array containing the values of the diagonal elements. So, to
create the following diagonal matrix:

one could use the following Modelica code:

```
diagonal({2.0, 3.0, 4.0, 5.0});
```

`linspace`

¶

The `linspace`

function builds a vector where the values of the
elements are all linearly distributed over an interval. The
`linspace`

function is invoked as follows:

```
linspace(v0, v1, n);
```

where `v0`

is the value of the first elements in the vector, `v1`

is the last element in the vector and `n`

is the total number of
values in the vector. So, for example, invoking `linspace`

as:

```
linspace(1.0, 5.0, 9);
```

would yield the vector:

```
{1.0, 1.5, 2.0, 3.5, 3.0, 3.5, 4.0, 4.5, 5.0}
```

## Conversion Functions¶

The following functions provide a means to transform arrays into other arrays.

`scalar`

¶

The `scalar`

function is invoked as follows:

```
scalar(A)
```

where `A`

is an array with an arbitrary number of dimensions as long
as each dimension is of size \(1\). The `scalar`

function
returns the (only) scalar value contained in the array. For example,

```
scalar([5]) // Argument is a two-dimensional array (matrix)
```

and

```
scalar({5}) // Argument is a one-dimensional array (vector)
```

would both give the scalar value `5`

.

`vector`

¶

The `vector`

function is invoked as follows:

```
vector(A)
```

where `A`

is an array with an arbitrary number of dimensions as long
as only one dimension has a size greater than \(1\). The
`vector`

function returns the contents of the array as a vector
(*i.e.,* an array with only a single dimension). So, for example, if
we passed a column or row matrix, *e.g.*,

```
vector([1;2;3;4]) // Argument is a column matrix
```

or

```
vector([1,2,3,4]) // Argument is a row matrix
```

we would get back:

```
{1,2,3,4}
```

`matrix`

¶

The `matrix`

function is invoked as follows:

```
matrix(A)
```

where `A`

is an array with an arbitrary number of dimensions as long
as only two dimension have a size greater than \(1\). The
`matrix`

function returns the contents of the array as a matrix
(*i.e.,* an array with only two dimensions).

## Mathematical Operations¶

In linear algebra, there are many different types of mathematical operations that are commonly performed on vectors and matrices. Modelica provides functions to perform most of these operations. In this way, Modelica equations can be made to look very much like their mathematical counterparts in linear algebra.

Let’s start with operations like addition, subtraction, multiplication, division and exponentiation. For the most part, these operations work just as they do in mathematics when applied to the various combinations of scalars, vectors and matrices. However, for completeness and reference, the following tables summarize how these operations are defined.

Explanation of Notation

Each of the operations described below involves two arguments, \(a\) and \(b\), and a result, \(c\). If an argument represents a scalar, it will have no subscripts. If it is a vector, it will have one subscript. If it is a matrix, it will have two subscripts. If the operation is defined for arbitrary arrays, a case will be included with three subscripts. If a given combination is not shown, then it is not allowed.

### Addition (`+`

)¶

Expression | Result |

\(a + b\) | \(c = a + b\) |

\(a_{i} + b_{i}\) | \(c_{i} = a_{i} + b_{i}\) |

\(a_{ij} + b_{ij}\) | \(c_{ij} = a_{ij} + b_{ij}\) |

\(a_{ijk} + b_{ijk}\) | \(c_{ijk} = a_{ijk} + b_{ijk}\) |

### Subtraction (`-`

)¶

Expression | Result |

\(a - b\) | \(c = a - b\) |

\(a_{i} - b_{i}\) | \(c_{i} = a_{i} - b_{i}\) |

\(a_{ij} - b_{ij}\) | \(c_{ij} = a_{ij} - b_{ij}\) |

\(a_{ijk} - b_{ijk}\) | \(c_{ijk} = a_{ijk} - b_{ijk}\) |

### Multiplication (`*`

and `.*`

)¶

There are two types of multiplication operators. The first is the
normal multiplication operator, `*`

, that follows the usual
mathematical conventions of linear algebra that matrix-vector
products, *etc.*. The behavior of the `*`

operator is summarized in
the following table:

Expression | Result |

\(a * b\) | \(c = a * b\) |

\(a * b_i\) | \(c_i = a * b_i\) |

\(a * b_{ij}\) | \(c_{ij} = a * b_{ij}\) |

\(a * b_{ijk}\) | \(c_{ijk} = a * b_{ijk}\) |

\(a_i * b\) | \(c_i = a_i * b\) |

\(a_{ij} * b\) | \(c_{ij} = a_{ij} * b\) |

\(a_{ijk} * b\) | \(c_{ijk} = a_{ijk} * b\) |

\(a_{i} * b_{i}\) | \(c = \sum_i a_{i} * b_{i}\) |

\(a_{i} * b_{ij}\) | \(c_j = \sum_i a_{i} * b_{ij}\) |

\(a_{ij} * b_{j}\) | \(c_i = \sum_j a_{ij} * b_{j}\) |

\(a_{ik} * b_{kj}\) | \(c_{ij} = \sum_k a_{ik} * b_{kj}\) |

The second type of multiplication operator is a special element-wise
version, `.*`

, which doesn’t perform any summations and simply
applies the operator element-wise to all array elements.

Expression | Result |

\(a\) `.*` \(b\) |
\(c = a * b\) |

\(a_{i}\) `.*` \(b_{i}\) |
\(c_{i} = a_{i} * b_{i}\) |

\(a_{ij}\) `.*` \(b_{ij}\) |
\(c_{ij} = a_{ij} * b_{ij}\) |

\(a_{ijk}\) `.*` \(b_{ijk}\) |
\(c_{ijk} = a_{ijk} * b_{ijk}\) |

### Division (`/`

and `./`

)¶

As with Multiplication (* and .*), there are two division
operators. The first is the normal division operator, `/`

, which
can be used to divide arrays by a scalar value. The following table
summarizes its behavior:

Expression | Result |

\(a / b\) | \(c = a / b\) |

\(a_i / b\) | \(c_i = a_i / b\) |

\(a_{ij} / b\) | \(c_{ij} = a_{ij} / b\) |

\(a_{ijk} / b\) | \(c_{ijk} = a_{ijk} / b\) |

In addition, there is also an element-wise version of the division
operator, `./`

, whose behavior is summarized in the following table:

Expression | Result |

\(a\) `./` \(b\) |
\(c = a / b\) |

\(a_{i}\) `./` \(b_{i}\) |
\(c_{i} = a_{i} / b_{i}\) |

\(a_{ij}\) `./` \(b_{ij}\) |
\(c_{ij} = a_{ij} / b_{ij}\) |

\(a_{ijk}\) `./` \(b_{ijk}\) |
\(c_{ijk} = a_{ijk} / b_{ijk}\) |

### Exponentiation (`^`

and `.^`

)¶

As with Multiplication (* and .*) and Division (/ and ./), the
exponentiation operator comes in two forms. The first is the standard
exponentiation operator, `^`

. The standard version can be used in
two different ways. The first is to raise one scalar to the power of
another (*i.e.,* \(a\) `^`

\(b\)). The other is to raise a
square matrix to a scalar power (*i.e.,* \(a_{ij}\) `^`

\(b\)).

The other form of exponentiation is the element-wise form indicated
with the `.^`

operator. Its behavior is summarized in the following
table:

Expression | Result |

\(a\) `.^` \(b\) |
\(c = a^b\) |

\(a_{i}\) `.^` \(b_{i}\) |
\(c_{i} = a_{i}^{b_{i}}\) |

\(a_{ij}\) `.^` \(b_{ij}\) |
\(c_{ij} = a_{ij}^{b_{ij}}\) |

\(a_{ijk}\) `.^` \(b_{ijk}\) |
\(c_{ijk} = a_{ijk}^{b_{ijk}}\) |

### Equality (`=`

)¶

The equality operator, `=`

used to construct equations can be used
with scalars as well as arrays **as long as the left hand side and
right hand side have the same number of dimensions and the sizes of
each dimension are the same**. Assuming this requirement is met, then
the operator is simply applied element-wise. This means that the
operator is applied between each element on the left hand side and its
counterpart on the right hand side.

### Assignment (`:=`

)¶

The `:=`

(assignment) operator is applied in the same element-wise
way as the Equality (=) operator.

### Relational Operators¶

All relational operators (`and`

, `or`

, `not`

, `>`

, `>=`

,
`<=`

, `<`

) are applied in the same element-wise way as the
Equality (=) operator.

`transpose`

¶

The `transpose`

function takes a matrix as an argument and returns a
transposed version of that matrix.

`outerProduct`

¶

The `outerProduct`

function takes two arguments. Each argument must
be a vector and they must have the same size. The function returns a
matrix which represents the outer product of the two vectors.
Mathematically speaking, assume \(a\) and \(b\) are vectors of the
same size. Invoking `outerProduct(a,b)`

will return a matrix,
\(c\), whose elements are defined as:

`symmetric`

¶

The `symmetric`

function takes a square matrix as an argument. It
returns a matrix of the same size where all the elements below the
diagonal of the original matrix have been replaced by elements
transposed from above the diagonal. In other words,

`skew`

¶

The `skew`

function takes a vector with three components and returns
the following skew-symmetric matrix:

`cross`

¶

The `cross`

function takes two vectors (each with 3 components) and
returns the following vector (with three components):

## Reduction Operators¶

Reduction operators are ones that reduce arrays down to scalar values.

`min`

¶

The `min`

function takes an array and returns the smallest value in
the array. For example:

```
min({10, 7, 2, 11}) // 2
min([1, 2; 3, -4]) // -4
```

`max`

¶

The `max`

function takes an array and returns the largest value in
the array. For example:

```
max({10, 7, 2, 11}) // 11
max([1, 2; 3, -4]) // 3
```

`sum`

¶

The `sum`

function takes an array and returns the sum of all
elements in the array. For example:

```
sum({10, 7, 2, 11}) // 30
sum([1, 2; 3, -4]) // 2
```

`product`

¶

The `product`

function takes an array and returns the product of all
elements in the array. For example:

```
product({10, 7, 2, 11}) // 1540
product([1, 2; 3, -4]) // -24
```

## Miscellaneous Functions¶

`ndims`

¶

The `ndims`

function takes an array as its argument and returns the
number of dimensions in that array. For example:

```
ndims({10, 7, 2, 11}) // 1
ndims([1, 2; 3, -4]) // 2
```

`size`

¶

The `size`

function can be invoked two different ways. The first
way is with a single argument that is an array. In this case,
`size`

returns a vector where each component in the vector
corresponds to the size of the corresponding dimension in the array. For example:

```
size({10, 7, 2, 11}) // {4}
size([1, 2, 3; 3, -4, 5]) // {2, 3}
```

It is also possible to call `size`

with an optional additional
argument indicating a specific dimension number. In that case, it
will return the size of that specific dimension as a scalar integer.
For example,

```
size({10, 7, 2, 11}, 1) // 4
size([1, 2, 3; 3, -4, 5], 1) // 2
size([1, 2, 3; 3, -4, 5], 2) // 3
```

## Vectorization¶

In this section, we’ve discussed the numerous functions in Modelica that are designed to work with arguments that are arrays. But a very common use case is to apply a function element-wise to every element in a vector. Modelica supports this use case through a feature called “vectorization”. If a function is designed to take a scalar, but is passed an array instead, the Modelica compiler will automatically apply that function to each element in the vector.

To understand how this works, first consider a normal evaluation using
the `abs`

function:

```
abs(-1.5) // 1.5
```

Obviously, `abs`

is normally meant to accept a scalar argument and
return a scalar. But in Modelica, we can also do this:

```
abs({0, -1, 1, -2, 2}) // {0, 1, 1, 2, 2}
```

Since this function is designed for scalar, the Modelica compiler will transform:

```
abs({0, -1, 1, -2, 2})
```

into

```
{abs(0), abs(-1), abs(1), abs(-2), abs(2)}
```

In other words, it transforms the function applies to a vector of scalars into a vector a functions applied to scalar.

**This feature also works functions that take multiple arguments** as
long as only **one** of the expected scalar arguments is a vector. To
understand this slightly more complex functionality, consider the
modulo function, `mod`

. If applied to scalar arguments we get the
following behavior:

```
mod(5, 2) // 1
```

If we turn the first argument into a vector, we get:

```
mod({5, 6, 7, 8}, 2) // {1, 0, 1, 0}
```

In other words, it transforms:

```
mod({5, 6, 7, 8}, 2)
```

into

```
{mod(5,2), mod(6,2), mod(7,2), mod(8,2)}
```

However, this vectorization does **not** apply if more than one scalar
arguments is presented as a vector. For example, the following
expression will be an error:

```
mod({5, 6, 7, 8}, {2, 3}) // Illegal
```

because `mod`

expects two scalar arguments, but it was passed two
vector arguments.