def run(self, engine: Engine, run_dir: pathlib.Path) -> None:
    """Run the application.
    Args:
        engine: Application execution engine.
        run_dir: Run directory.
    """
    max_print_size = 8
    matrix = create_psd_matrix(self.matrix_size)
    lower = numpy.zeros_like(matrix)
    n = matrix.shape[0]
    block_size = min(self.block_size, n)
    if matrix.shape[0] <= max_print_size:
        logger.log(
            APP_LOG_LEVEL,
            f'Generated input matrix: {matrix.shape}\n{matrix}',
        )
    else:
        logger.log(
            APP_LOG_LEVEL,
            f'Generated input matrix: {matrix.shape}',
        )
    logger.log(APP_LOG_LEVEL, f'Block size: {block_size}')
    for k in range(0, n, block_size):
        end_k = min(k + block_size, n)
        lower_tasks: dict[tuple[int, int], TaskFuture[Array]] = {}
        lower_tasks[(k, k)] = engine.submit(
            potrf,
            matrix[k:end_k, k:end_k],
        )
        for i in range(k + block_size, n, block_size):
            end_i = min(i + block_size, n)
            lower_tasks[(i, k)] = engine.submit(
                trsm,
                lower_tasks[(k, k)],
                matrix[i:end_i, k:end_k],
            )
        gemm_tasks: dict[tuple[int, int], TaskFuture[Array]] = {}
        for i in range(k + block_size, n, block_size):
            end_i = min(i + block_size, n)
            for j in range(i, n, block_size):
                end_j = min(j + block_size, n)
                syrk_task = engine.submit(
                    syrk,
                    matrix[i:end_i, j:end_j],
                    lower_tasks[(i, k)],
                )
                gemm_tasks[(i, j)] = engine.submit(
                    gemm,
                    syrk_task,
                    lower_tasks[(i, k)],
                    lower_tasks[(j, k)],
                )
        for (i, j), tile in lower_tasks.items():
            end_i = min(i + block_size, n)
            end_j = min(j + block_size, n)
            lower[i:end_i, j:end_j] = tile.result()
        for (i, j), tile in gemm_tasks.items():
            end_i = min(i + block_size, n)
            end_j = min(j + block_size, n)
            matrix[i:end_i, j:end_j] = tile.result()
    if matrix.shape[0] <= max_print_size:
        logger.log(APP_LOG_LEVEL, f'Output matrix:\n{lower}')
    else:
        logger.log(APP_LOG_LEVEL, f'Output matrix: {lower.shape}')