回 帖 发 新 帖 刷新版面

主题:jstzhurj老师,我又将程序简化了,能否看下?

还是上次那代码。我想了下,由于相邻的两个特征值之间可能有好几个p,比如在eigenvalue(4)和eigenvalue(5)之间有8个p,分别是23、24、25、。。。、30,他们的conr值相同,我只要算一个就可以了,然后把这个值赋给其他的conr,比如得到了conr(23),可以把conr(23)直接赋给conr(24、25、26、...、30),这样就不用再重复计算了,我改了下程序,帮忙看下吧?呵呵

q=1
  do i=1,4*m*n-1  !每个i找满足的p,先对i循环
   conduc=0.0
   k=0
   do p=q,450000 
     if((eigenvalue(i)<=Ef(p)).and.(eigenvalue(i+1)>Ef(p))) then !如果p满足条件,就执行下面的操作,再看下满足这个条件的p有几个
        q=p+1   !p+1看下还能否满足条件,如果能那就k+1,直到不能满足条件跳出if语句
        k=k+1   !计算总的能满足i条件的p的个数
      end if
         do temp=1,i
         do j=i+1,4*m*n
          ea=matmul(traneigv(temp,:),hx)
          ec=matmul(traneigv(temp,:),hy)
          eb=matmul(traneigv(j,:),hx)
          ed=matmul(traneigv(j,:),hy)
          conduc=conduc+(dot_product(ea,eigenvector(:,j))*dot_product(ed,eigenvector(:,temp))    
        end do       
       end do  
  conr(p)=2*pi*aimag(conduc)/S
  !将能满足i条件的所有conr(p)都赋值,如果k>1,那就说明不止一个能满足条件了
  if(k>1) then
    do ii=1,k
     conr(p+ii)=conr(p)
    end do
  end if
     q=p
     exit   !退到计算下一个i的地方
    end do
     
  end do

回复列表 (共58个回复)

31 楼

matlab运算得到了比较好的结果。
换成complex*16又试了,fortran不行,跟matlab得到的结果不同,我看了,还是特征向量的问题啊。数学上倒是说过,对于一个矩阵来说,特征向量有很多个,我曾经把公式带进去试过:Hr=Ar,H,A,r分别是矩阵、矩阵特征值和特征向量,在matlab下,二者严格相等,但是在fortran下,二者只在三位小数范围内相等,后面的就不相等了。今天把fortran得到的矩阵和matlab得到的矩阵拿出来看了下,基本是相同的矩阵,至少矩阵元素前10位数是相等的。真不明白为什么会得到这种结果出来。如果运行几次就会发现,每次得到的矩阵特征向量还都差不多,尽管跟matlab得到的结果差距较大。
[em69][em69][em60][em60][em30][em30][em32][em32][em41][em41][em51][em51][em11][em11][em12][em12][em13][em13][em14][em14][em9][em9][em80][em80][em72][em72][em72][em19][em19][em16][em16][em4][em4][em3][em3][em2][em2][em1][em1][em7][em7][em7]

32 楼

[quote]matlab运算得到了比较好的结果。
换成complex*16又试了,fortran不行,跟matlab得到的结果不同,我看了,还是特征向量的问题啊。数学上倒是说过,对于一个矩阵来说,特征向量有很多个,我曾经把公式带进去试过:Hr=Ar,H,A,r分别是矩阵、矩阵特征值和特征向量,在matlab下,二者严格相等,但是在fortran下,二者只在三位小数范围内相等,后面的就不相等了。今天把fortran得到的矩阵和matlab得到的矩阵拿出来看了下,基本是相同的矩阵,至少矩阵元素前10位数是相等的。真不明白为什么会得到这种结果出来。如果运行几次就会发现,每次得到的矩阵特征向量还都差不多,尽管跟matlab得到的结果差距较大。
[em69][em69][em60][em60][em30][em30][em32][em32][em41][em41][em51][em51][em11][em11][em12][em12][em13][em13][em14][em14][em9][em9][em80][em80][em72][em72][em72][em19][em19][em16][em16][em4][em4][em3][em3][em2][em2][em1][em1][em7][em7][em7][/quote]

Hr=Ar在Fortran下不严格相等,这是库函数的问题。要看这种误差是多少?我以为若是误差很小(小于百分之几)就可以暂且不管了,本人对这方面涉及很少,不知有没有更好的库函数。除此之外,程序是否还有其他更大的问题呢?

既然每次算的特征向量相等,loop=10这种无意义的循环也就没有必要了。[em18][em18][em67][em67][em77][em77]

33 楼


 do j=1,4*m*n
  do i=1,450000-1
    if((Ef(i)<=eigenvalue(j)) .and. (eigenvalue(j)<Ef(i+1))) then
      ds(i)=ds(i)+1
      exit
    end if    
  end do
 end do

这段程序怎么这么让人费解?你明白循环嵌套执行的过程么?!

34 楼


能做到这样就很高兴了,可能程序还有更大的问题,谢谢大姐。自己再检查公式,检查程序看下哪里出问题了吧。我看到徐士良程序集上有给出的解实矩阵特征向量的程序,不知道有没有解虚数矩阵特征向量的程序?
[em32][em32][em35][em35][em36][em36][em37][em37][em38][em38][em30][em30][em72][em72][em62][em62][em68][em68][em80][em80][em78][em78][em77][em77][em4][em4][em4][em4][em4][em8][em8][em8][em8][em8]

35 楼

[quote]
 do j=1,4*m*n
  do i=1,450000-1
    if((Ef(i)<=eigenvalue(j)) .and. (eigenvalue(j)<Ef(i+1))) then
      ds(i)=ds(i)+1
      exit
    end if    
  end do
 end do

这段程序怎么这么让人费解?你明白循环嵌套执行的过程么?![/quote]

确实很费解。应该是这样吧:
!计算态密度
 do i=1,450000-1
  do j=1,4*m*n
    if((Ef(i)<=avereig(j)) .and. (avereig(j)<Ef(i+1))) then
      ds(i)=ds(i)+1
      exit
    end if    
  end do
 end do
这地方我计算态密度,就是两个相邻的Ef之间有几个本征值。先从i=1开始检查,看本征值有没有落在Ef(1)和Ef(2)之间的,如果有avereig(j)的话,ds(i)+1,直到有某个avereig(j)不在这个区间,那么退出循环,就到i循环继续下一个循环。

36 楼

[quote][quote]
 do j=1,4*m*n
  do i=1,450000-1
    if((Ef(i)<=eigenvalue(j)) .and. (eigenvalue(j)<Ef(i+1))) then
      ds(i)=ds(i)+1
      exit
    end if    
  end do
 end do

这段程序怎么这么让人费解?你明白循环嵌套执行的过程么?![/quote]

确实很费解。应该是这样吧:
!计算态密度
 do i=1,450000-1
  do j=1,4*m*n
    if((Ef(i)<=avereig(j)) .and. (avereig(j)<Ef(i+1))) then
      ds(i)=ds(i)+1
      exit
    end if    
  end do
 end do
这地方我计算态密度,就是两个相邻的Ef之间有几个本征值。先从i=1开始检查,看本征值有没有落在Ef(1)和Ef(2)之间的,如果有avereig(j)的话,ds(i)+1,直到有某个avereig(j)不在这个区间,那么退出循环,就到i循环继续下一个循环。[/quote]


exit?满足条件就退出?这样ds最多等于1,还能累加么?exit不是乱用的!!!

37 楼

加个else应该可以了吧?满足条件就累计,不满足就退出。还有个耗时问题。由于我这里Ef(i)和
avereig(j)都是单调递增的,我也参照以前给的做法,设一个q变量吧
q1=1
q2=1
do i=q1,450000-1
  do j=q2,4*m*n
    if((Ef(i)<=avereig(j)) .and. (avereig(j)<Ef(i+1))) then
      ds(i)=ds(i)+1
    else
      q1=i+1  !不用让i从1开始循环了,从i+1开始循环,前面那些已经检查过了
      q2=j    !如果j不满足这个条件,就让j的循环从这个数开始
      exit
    end if    
  end do
 end do

38 楼

[quote]加个else应该可以了吧?满足条件就累计,不满足就退出。还有个耗时问题。由于我这里Ef(i)和
avereig(j)都是单调递增的,我也参照以前给的做法,设一个q变量吧
q1=1
q2=1
do i=q1,450000-1
  do j=q2,4*m*n
    if((Ef(i)<=avereig(j)) .and. (avereig(j)<Ef(i+1))) then
      ds(i)=ds(i)+1
    else
      q1=i+1  !不用让i从1开始循环了,从i+1开始循环,前面那些已经检查过了
      q2=j    !如果j不满足这个条件,就让j的循环从这个数开始
      exit
    end if    
  end do
 end do
[/quote]

你编程是东一榔头西一拐!i变量还要你操心吗?退出之后它自动加1执行了,什么条件退出?!哎......[em1][em6][em7][em21][em21]

39 楼


早饭没吃,吃完回来再看[em13][em13][em13][em13][em13][em13][em72][em72][em72][em72][em21][em21][em21][em21][em21][em21][em21][em21][em21][em21][em11][em11][em11][em11][em11]

40 楼

当avereig(j)不在Ef(i)和Ef(i+1)之间的时候就退出。
比如Ef(12)=0.01,Ef(13)=0.21,
avereig(1)=0.05,avereig(2)=0.1,avereig(3)=0.15,avereig(4)=0.20,avereig(5)=0.25,当j=5的时候,avereig(5)就不在Ef(12)和Ef(13)之间,就退出,看下avereig(5)在不在Ef(13)和Ef(14)之间,在的话就统计ds。

q1=1
do i=q1,450000-1
  do j=q2,4*m*n
    if((Ef(i)<=avereig(j)) .and. (avereig(j)<Ef(i+1))) then
      ds(i)=ds(i)+1
    else
      q1=i+1  !不用让i从1开始循环了,从i+1开始循环,前面那些已经检查过了
      exit
    end if    
  end do
 end do

我来回复

您尚未登录,请登录后再回复。点此登录或注册