# Mathematical Operations#

DPF provides operators for implementing mathematical operations, ranging from addition and multiplication to FFT and QR solving.

For a complete list, see Operators, under the math section.

```# Import the necessary modules
import ansys.dpf.core as dpf
```

```# Initialize Fields
num_entities = 2
field1 = dpf.Field(nentities=2)
field2 = dpf.Field(nentities=2)

# By default, Fields contain 3d vectors.
# So with three entities we need nine values.
field1.data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]
field2.data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]

field1.scoping.ids = range(num_entities)
field2.scoping.ids = range(num_entities)
```

Once the fields are ready, we can instantiate an operator.

```add_op = dpf.operators.math.add(field1, field2)
```

Finally, we use eval() to compute and retrieve the result.

```field3 = add_op.eval()

# = [[2. 4. 6.] [8. 10. 12.]]
print(field3.data)
```
```[[ 2.  4.  6.]
[ 8. 10. 12.]]
```

# Dot product#

```dot_op = dpf.operators.math.generalized_inner_product(field1, field2)

# (1. * 1.) + (2. * 2.) + (3. * 3.) = 14.
# (4. * 4.) + (5. * 5.) + (6. * 6.) = 77.
field3 = dot_op.eval()
print(field3.data)
```
```[14. 77.]
```

# Power#

```field = dpf.Field(nentities=1)
field1.data = [1.0, 2.0, 3.0]
field1.scoping.ids = [1]

pow_op = dpf.operators.math.pow(field1, 3.0)

# [1. 8. 27.]
field3 = pow_op.eval()
print(field3.data)
```
```[[ 1.  8. 27.]]
```

# L2 norm#

```field1.data = [16.0, -8.0, 2.0]
norm_op = dpf.operators.math.norm(field1)

# [ 18. ]
field3 = norm_op.eval()
print(field3.data)
```
```[18.]
```

# Accumulate#

First we define fields. By default, fields represent 3D vectors so one elementary data is a 3D vector. The optional ponderation field is a field which takes one value per entity, so we need to change its dimensionality (1D).

```num_entities = 3
input_field = dpf.Field(nentities=num_entities)
ponderation_field = dpf.Field(num_entities)
ponderation_field.dimensionality = dpf.Dimensionality([1])

input_field.scoping.ids = range(num_entities)
ponderation_field.scoping.ids = range(num_entities)
```

Fill fields with data. Add nine values because there are three entities.

```input_field.data = [-2.0, 2.0, 4.0, -5.0, 0.5, 1.0, 7.0, 3.0, -3.0]
```

Three weights, one per entity.

```ponderation_field.data = [0.5, 2.0, 0.5]
```

Retrieve the result.

```acc = dpf.operators.math.accumulate(fieldA=input_field, ponderation=ponderation_field)
output_field = acc.outputs.field()

# (-2.0 * 0.5) + (-5.0 * 2.0) + (7.0 * 0.5)  = -7.5
# (2.0  * 0.5) + (0.5  * 2.0) + (3.0 * 0.5)  = 3.5
# (4.0  * 0.5) + (1.0  * 2.0) + (-3.0 * 0.5) = 2.5
print(output_field.data)
```
```[[-7.5  3.5  2.5]]
```

# With scoping#

```field1.data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]
field2.data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]
```

Next, we need to provide information about the scoping. DPF needs to know the IDs of the data we just provided, so that it can apply an operator on a subset of the original data.

By providing these integers we only select the data with an ID in common. Here we are selecting the third elementary data of the first field, and the first elementary data of the second field, Other elementary data is not taken into account when using an operator that needs two operands.

```field1.scoping.ids = [1, 2, 3]
field2.scoping.ids = [3, 4, 5]

# Only the third entity was changed
# because it is the only operator where two operands were provided.
print(field3.data)
# [[8. 10. 12.]]
print(field3.get_entity_data_by_id(3))
```
```[[ 1.  2.  3.]
[ 4.  5.  6.]
[ 8. 10. 12.]
[ 4.  5.  6.]
[ 7.  8.  9.]]
[[ 8. 10. 12.]]
```

Dot product

```dot_op = dpf.operators.math.generalized_inner_product(field1, field2)

# We obtain zeros for IDs where there could not be two operands.
# (7. * 1.) + (8. * 2.) + (9. * 3.) = 50.
# [0. 0. 50. 0. 0.]
field3 = dot_op.eval()
print(field3.data)
```
```[ 0.  0. 50.  0.  0.]
```

Total running time of the script: (0 minutes 0.031 seconds)

Gallery generated by Sphinx-Gallery