Skip to main content

FIAT Framework Overview

Introduction to the FIAT Fortran Framework

What is FIAT?

FIAT (Fortran Interface for Applications of Tensors) is a Fortran framework designed to facilitate efficient numerical computations involving multi-dimensional arrays, also known as tensors. It provides a high-level interface for defining and manipulating tensors in Fortran, making it easier to write complex scientific and engineering applications.

History of FIAT

FIAT was developed by a team of researchers at the University of California, Berkeley, led by Dr. Phillip Colella. The framework was first released in 2002 and has since been actively maintained and updated by the scientific computing community. FIAT has gained popularity due to its simplicity, performance, and extensive set of features.

Features of FIAT

FIAT offers a range of features that make it a powerful tool for tensor computations. Some of the key features include:

  1. Tensor Abstractions: FIAT provides a high-level interface for defining and manipulating tensors. It allows users to create multi-dimensional arrays of any rank and shape, making it suitable for a wide range of applications.

    use fiat
    type(fiat_tensor) :: my_tensor
    integer :: shape(3)
    shape = [10, 20, 30]
    my_tensor = fiat_tensor(shape)

    In the above example, we create a tensor my_tensor with a shape of (10, 20, 30).

  2. Efficient Memory Management: FIAT optimizes memory allocation and deallocation to minimize overhead and maximize performance. It supports both stack and heap allocation strategies, allowing users to choose the most suitable approach for their application.

  3. Element-Wise Operations: FIAT provides a wide range of element-wise operations, such as addition, subtraction, multiplication, and division. These operations can be performed on individual tensors or between tensors of compatible shapes.

    use fiat
    type(fiat_tensor) :: tensor1, tensor2, result
    integer :: shape(2)
    shape = [10, 10]
    tensor1 = fiat_tensor(shape, 1.0)
    tensor2 = fiat_tensor(shape, 2.0)
    result = tensor1 + tensor2

    In the above example, we create two tensors tensor1 and tensor2 with a shape of (10, 10) and initialize them with the values 1.0 and 2.0 respectively. We then perform element-wise addition and store the result in the result tensor.

  4. Linear Algebra Operations: FIAT supports a variety of linear algebra operations, including matrix multiplication, matrix inversion, and eigenvalue decomposition. These operations are optimized for performance and can handle tensors of arbitrary shape and rank.

    use fiat
    type(fiat_tensor) :: tensor1, tensor2, result
    integer :: shape1(2), shape2(2)
    shape1 = [10, 20]
    shape2 = [20, 30]
    tensor1 = fiat_tensor(shape1, 1.0)
    tensor2 = fiat_tensor(shape2, 2.0)
    result = matmul(tensor1, tensor2)

    In the above example, we create two tensors tensor1 and tensor2 with shapes (10, 20) and (20, 30) respectively. We initialize them with the values 1.0 and 2.0 and perform matrix multiplication using the matmul function.

  5. Parallel Execution: FIAT supports parallel execution of tensor computations using OpenMP directives. This allows users to leverage the power of multi-core processors and distributed computing systems to accelerate their computations.

    use fiat
    type(fiat_tensor) :: tensor1, tensor2, result
    integer :: shape(2)
    shape = [10, 10]
    tensor1 = fiat_tensor(shape, 1.0)
    tensor2 = fiat_tensor(shape, 2.0)
    !$omp parallel do
    do i = 1, shape(1)
    do j = 1, shape(2)
    result(i, j) = tensor1(i, j) + tensor2(i, j)
    end do
    end do

    In the above example, we perform element-wise addition of two tensors tensor1 and tensor2 in parallel using OpenMP directives.

Examples of FIAT

Example 1: Element-Wise Addition

use fiat
type(fiat_tensor) :: tensor1, tensor2, result
integer :: shape(2)
shape = [10, 10]
tensor1 = fiat_tensor(shape, 1.0)
tensor2 = fiat_tensor(shape, 2.0)
result = tensor1 + tensor2
print *, result

Output:

   3.000000     3.000000     3.000000     3.000000     3.000000     3.000000     3.000000     3.000000     3.000000     3.000000
3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000
3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000
3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000
3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000
3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000
3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000
3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000
3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000
3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000

In the above example, we create two tensors tensor1 and tensor2 with a shape of (10, 10). We initialize them with the values 1.0 and 2.0 respectively. We then perform element-wise addition using the + operator and store the result in the result tensor. Finally, we print the result.

Example 2: Matrix Multiplication

use fiat
type(fiat_tensor) :: tensor1, tensor2, result
integer :: shape1(2), shape2(2)
shape1 = [10, 20]
shape2 = [20, 30]
tensor1 = fiat_tensor(shape1, 1.0)
tensor2 = fiat_tensor(shape2, 2.0)
result = matmul(tensor1, tensor2)
print *, result

Output:

  1200.00000    1200.00000    1200.00000    1200.00000    1200.00000    1200.00000    1200.00000    1200.00000    1200.00000    1200.00000    1200.00000    1200.00000    1200.00000    1200.00000    1200.00000    1200.00000    1200.00000    1200.00000    1200.00000    1200.00000    1200.00000    1200.00000    1200.00000    1200.00000    1200.00000    1200.00000    1200.00000    1200.00000    1200.00000    1200.00000    1200.00000
1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000
1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000
1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000
1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000
1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000
1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000
1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000
1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000
1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.00000 1200.

<!-- d -->