如何将三对角矩阵创建为1D

时间:2019-02-22 04:23:52

标签: c++ algorithm matrix fortran

因此对于我的应用程序,我需要创建一个三对角矩阵。使用任何语言都可以轻松完成此操作,您可以遍历所有行和列,然后设置主要对角线值,次对角线值和超级对角线值。通常,这是在二维数组上执行的。

对于我的应用程序,我需要创建一个“三对角线”的一维数组。换句话说,是:取2d三对角矩阵,然后将其变成1d。我可以从2d开始,然后编写一些将2d数组转换为1d数组的函数。我可以的我想知道我们是否可以直接进入一维“三对角线”?例如,假设2D数组是10 * 10,那么我的1D数组将是100个元素长,那么我将需要找出哪个索引是主,超级和次对角线。

是否可以这样做?请让我知道并谢谢您

3 个答案:

答案 0 :(得分:1)

主对角线上的元素位于索引(i,i)上,并且其中n个元素;在(i,i-1)和(i,i + 1)的上对角线和下对角线,其中有n-1个(i分别从2开始,在n-1结束)。

一种选择是使用三个向量,并将元素存储在这三个向量的相应索引i上。

您还可以将所有值打包在单个长度为3n的向量中(如果要保留空间,则打包为3n-2)。根据要寻址的对角线,将n或2n添加到索引。对于元素(i,j),对角线的索引由j-i + 2给出。

答案 1 :(得分:0)

您可以仅使用2D数组指针查看您的1D数组。 Fortran:

  integer, target :: A(100)

  integer, pointer :: B(:,:)

  B(1:10,1:10) => A

  B = 0
  do i = 1, 10
    B(i,i) = 1
  end do

  print '(*(1x,g0))', A
end


> gfortran diag1d.f90 
> ./a.out 
 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1

在C ++中,转换也很容易。

答案 2 :(得分:0)

还请考虑:

  • @YvesDaoust的答案,因为提出了一种更好的存储策略:与其存储三对角矩阵的所有元素,不如存储非零值。如果值得的话,您可以编写派生类型来封装行为。

  • @VladmirF的答案,因为指针关联可能比通过reshape复制整个数组更好(取决于您的用例),如果您想要的只是临时索引更改(为了方便)在处理数据时。

说,让我们来看一下答案。

  • 填充三对角矩阵与构建任何矩阵都不是不同的问题。我认为这并不重要。只需记住,Fortran会以Column Major顺序(基于1的索引)存储数组。

  • 如果存储是连续的,则更改数据的形状很容易并且显而易见。您可以建立pointer关联或使用reshape将其转移到新变量。

  • 提取主,对角线和子对角线也是一个琐碎的问题,可以通过简单地操作数组索引三元组来完成。看:

    program tridiagonal
      implicit none
      integer, parameter :: n = 4
      integer :: A(n, n), B(n**2), main(n), sub(n-1), sup(n-1)
    
      A(1,:) = [1, 4, 0, 0]
      A(2,:) = [3, 4, 1, 0]
      A(3,:) = [0, 2, 3, 4]
      A(4,:) = [0, 0, 1, 3]
                                ! Remember, colum major
      B = reshape(A, shape(B))  ! 1, 3, 0, 0, 4, 4, 2, 0, 0, 1, 3, 1, 0, 0, 4, 3
    
      main = B(  1:n**2:n+1)    ! 1, 4, 3, 3
      sub  = B(  2:n**2:n+1)    ! 3, 2, 1
      sup  = B(n+1:n**2:n+1)    ! 4, 1, 4
    end