矩阵方程未及时更新

时间:2017-02-16 03:11:02

标签: matrix fortran matrix-multiplication

作为一个简单的例子来说明我的观点,我试图从t = 0开始求解下面的等式f(t+1) = f(t) + f(t)*Tr (f^2),其中Tr是矩阵的轨迹(对角元素的总和)。下面我提供一个基本代码。我的代码编译没有错误,但没有按我的意愿更新解决方案。我的预期结果也低于我手工计算的结果(通过矩阵乘法手动检查非常容易)。

在下面的示例代码中,我有两个存储解决方案的变量,g用于我实现的f(t=0),然后我将f(t+1)存储为f

complex,dimension(3,3) :: f,g
integer :: k,l,m,p,q

假设g = f(t = 0)定义如下

do l=1,3 !matrix index loops
  do k=1,3 !matrix index loops

        if (k == l) then

            g(k,l) = cmplx(0.2,0)

        else if ( k /= l) then

            g(k,l) = cmplx(0,0)

        end if


  end do 
end do

我已经检查过这个结果确实是我想要的,所以我知道在t = 0时f被正确定义。

现在我尝试在t = 0时使用这个矩阵并找到所有时间的矩阵,由等式f(t+1) = f(t)+f(t)*Tr(f^2)控制,但这是我没有正确实现我想要的代码的地方。

do m=1,3 !loop for 3 time iterations

       do p=1,3 !loops for dummy indices for matrix trace
         do q=1,3 

               g(1,1) = g(1,1) + g(1,1)*g(p,q)*g(p,q) !compute trace here
               f(1,1) = g(1,1)  

               !f(2,2) = g(2,2) + g(2,2)*g(p,q)*g(p,q)
               !f(3,3) = g(3,3) + g(3,3)*g(p,q)*g(p,q)

               !assume all other matrix elements are zero except diagonal


    end do
  end do   

end do

打印此结果由

完成
print*, "calculated f where m=", m
do k=1,3
   print*, (f(k,l), l=1,3) 
end do

这时我意识到我的代码没有正确实现。
当我打印f(k,l)时,我希望t = 1得到0.224*identity matrix的结果,现在我明白了。但是对于t = 2,输出不正确。所以我的代码在第一次迭代时正确更新,但之后没有。

我正在寻找一个解决方案,以便如何正确实现我希望获得我期望的结果的等式。

1 个答案:

答案 0 :(得分:2)

我会回答你似乎遇到麻烦的几件事。首先,追踪。 3x3矩阵的轨迹为A(1,1)+A(2,2)+A(3,3)。第一个和第二个索引是相同的,因此我们使用一个循环变量。计算NxN矩阵A的跟踪:

trace = 0.
do i=1,N
   trace = trace + A(i,i)
enddo

认为您正试图循环pq来计算不正确的跟踪。在这个总和中,您将添加A(2,3)这样的错误。

其次,要计算更新,我建议您将更新后的f计算为fNew,然后您的代码如下所示:

do m=1,3   ! time
   ! -- Compute f^2 (with loops not shown)
   f2 = ...

   ! -- Compute trace of f2 (with loop not shown)
   trace = ...

   ! -- Compute new f
   do j=1,3
      do i=1,3
         fNew(i,j) = f(i,j) + trace*f(i,j)
      enddo
   enddo

   ! -- Now update f, perhaps recording fNew-f for some residual
   ! -- The LHS and RHS are both arrays of dimension (3,3),
   ! -- so fortran will automatically perform an array operation
   f = fNew
enddo

这种方法有两个优点。首先,您的代码实际上看起来像您正在尝试的数学,并且很容易遵循。对于不那么简单的现实问题,这是非常非常重要。其次,如果fNew(i,j)依赖于f(i+1,j),则您不会更新到下一个时间级别,而仍需要使用当前时间级别值。